Why can't I mapped more api in NestJS? - node.js

To add http://localhost:8080/api/v1/admin (GET) to develop an api with NestJS, we added Get annotation and proceeded with the api development, but the api was not mapped, and if you call that api, a 404notfound error will occur.
What kind of problem?
// admin.controller.ts
import { Body, Controller, Get, HttpCode, Post, UseGuards } from '#nestjs/common';
import {
ApiTags,
ApiOperation,
ApiResponse,
} from '#nestjs/swagger';
import { ReqAdmin } from 'src/lib/decorator/req-admin.decorator';
import { HttpAuthGuard } from 'src/guards/auth/http-auth.guard';
import { BaseResponse } from 'src/models/http/base.response';
import { AdminService } from './admin.service';
import { CreateAdminDto } from './dto/create.admin.dto';
import { LoginAdminDto } from './dto/login.admin.dto';
import { Admin } from 'src/entities/admin.entity';
#Controller('admin')
#ApiTags('관리자 API')
export class AdminController {
constructor(
private readonly adminService: AdminService
) {}
#Get('/')
#UseGuards(HttpAuthGuard)
#ApiOperation({ summary: '내 정보 보기', description: '내정보 보기' })
#ApiResponse({ status: 200, description: '내 정보 조회 성공' })
public async findOne(#ReqAdmin() admin: Admin): Promise<BaseResponse> {
const data = await this.adminService.findOneById(admin.id);
return BaseResponse.object('내정보 조회 성공', {
data,
})
}
#Post('/')
#ApiOperation({ summary: '관리자 생성 API', description: '관리자를 생성한다.' })
#ApiResponse({ status: 201, description: '관리자 생성성공' })
public async create(#Body() createAdminDto: CreateAdminDto) {
await this.adminService.create(createAdminDto);
return BaseResponse.object('관리자 생성성공')
}
#Post('/login')
#HttpCode(200)
#ApiOperation({ summary: '관리자 로그인 API', description: '관리자 로그인' })
#ApiResponse({ status: 200, description: '관리자 로그인성공', type: String })
public async login(#Body() loginAdminDto: LoginAdminDto) {
const token = await this.adminService.login(loginAdminDto);
return BaseResponse.object('관리자 로그인성공', {
'x-access-token': token
})
}
}
// admin.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { Admin } from 'src/entities/admin.entity';
import { TokenModule } from 'src/token/token.module';
import { TokenService } from 'src/token/token.service';
import { AdminController } from './admin.controller';
import { AdminRepository } from './admin.repository';
import { AdminService } from './admin.service';
#Module({
imports: [
TypeOrmModule.forFeature([
Admin
])
],
providers: [AdminService, TokenService],
exports: [AdminService],
controllers: [AdminController]
})
export class AdminModule {}
// terminal
iwonje#iwonje-ui-MacBookAir mcn-admin-backend % nest start
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [NestFactory] Starting Nest
application...
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [InstanceLoader] AppModule
dependencies initialized +42ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [InstanceLoader] TypeOrmModule
dependencies initialized +0ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [InstanceLoader] TypeOrmCoreModule
dependencies initialized +303ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [InstanceLoader] TypeOrmModule
dependencies initialized +0ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [InstanceLoader] AdminModule
dependencies initialized +1ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [RoutesResolver] AdminController
{/api/v1/admin}: +287ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [RouterExplorer] Mapped
{/api/v1/admin, POST} route +1ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [RouterExplorer] Mapped
{/api/v1/admin/login, POST} route +1ms
[Nest] 40115 - 2022. 10. 11. 오후 4:12:15 LOG [NestApplication] Nest application
successfully started +1ms
// app.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule, TypeOrmModuleOptions } from '#nestjs/typeorm';
import { DatabaseTypes } from '../database/database.enum';
import { DatabaseFactory } from '../database/database.factory';
import { AdminModule } from 'src/admin/admin.module';
#Module({
imports: [
TypeOrmModule.forRoot(
DatabaseFactory.createDatabase(DatabaseTypes.MYSQL).options(),
),
AdminModule
],
})
export class AppModule {}

Look like you had added a prefix for your api /api/v1
You can try to call http://localhost:8080/api/v1/admin instead of http://localhost:8080/admin

Related

nestjs-rabbitmq Node.js package not handling messages

Maybe I am missing a basic thing as I am starting out with Nestjs, but somehow I can't get Nest.js to receive messages in a Pub/Sub pattern using: https://github.com/golevelup/nestjs. I create the Messaging Service like so:
#Module({
imports: [
RabbitMQModule.forRoot(RabbitMQModule, {
exchanges: [
{
name: 'tx-nextor',
type: 'topic',
},
],
uri: RABBIT_URI,
channels: {
'channel-1': {
prefetchCount: 15,
default: true,
},
},
}),
MessagingModule,
],
providers: [],
controllers: [],
})
export class MessagingModule {}
Everything is connecting correctly and I can see the connection and channel in the RabbitMQ admin. After I created a subscriber:
#Injectable()
export class ResourceService {
#RabbitSubscribe({
exchange: 'tx-nextor',
routingKey: 'resource.*',
queue: 'resource-history-resource.*.updated',
})
public async updatedHandler(msg: {}, amqpMsg: ConsumeMessage) {
console.log('Subscribe handler ran');
console.log(JSON.stringify(msg));
console.log(`Correlation id: ${amqpMsg.properties.correlationId}`);
return 'test';
}
}
This also connects:
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RoutesResolver] AppController {/}: +8ms
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RouterExplorer] Mapped {/, GET} route +3ms
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RoutesResolver] HistoryController {/history}: +1ms
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RouterExplorer] Mapped {/history/appointment, GET} route +1ms
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RouterExplorer] Mapped {/history/test, POST} route +1ms
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RabbitMQModule] Initializing RabbitMQ Handlers
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RabbitMQModule] Registering rabbitmq handlers from ResourceService
[resource-history] [Nest] 220 - 07/09/2022, 4:30:47 PM LOG [RabbitMQModule] ResourceService.updatedHandler {subscribe} -> tx-nextor::resource.*::resource-history-resource.*.updated
[resource-history] [Nest] 220 - 07/09/2022, 4:30:48 PM LOG [NestApplication] Nest application successfully started +11ms
But after I do this nothing is logged.
Although the consumer is connected, all testmessages are staying on the queue:
Adding RabbitMQModule to the exports in the Module definition solved the issue for me.
Reference: Problems with RabbitMQ and NestJS. I can't publish a message with nestjs-rabbitmq and NestJS
#Module({
imports: [
RabbitMQModule.forRoot(RabbitMQModule, {
exchanges: [
{
name: 'tx-nextor',
type: 'topic',
},
],
uri: RABBIT_URI,
channels: {
'channel-1': {
prefetchCount: 15,
default: true,
},
},
}),
MessagingModule,
],
providers: [],
controllers: [],
exports: [RabbitMQModule],
})
export class MessagingModule {}
Also, in the RabbitMQ Admin, make sure the payload has "" in the value, so it would be "test" vs test (sending JSON also should work)
Hope this helps!

Nest can't resolve dependencies of the SequelizeCoreModule

I'm trying to import SequelizeModule in my app.module.ts but I got the following error:
[Nest] ERROR [ExceptionHandler] Nest can't resolve dependencies of the
SequelizeCoreModule (SequelizeModuleOptions, ?). Please make sure that
the argument ModuleRef at index [1] is available in the
SequelizeCoreModule context.
app.module.ts
import { Module } from '#nestjs/common';
import { ModuleRef } from '#nestjs/core';
import { SequelizeModule } from '#nestjs/sequelize';
import { join } from 'path';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TweetsController } from './tweets/tweets.controller';
import { TweetsModule } from './tweets/tweets.module';
import { TweetsService } from './tweets/tweets.service';
#Module({
imports: [
SequelizeModule.forRoot({
dialect: 'sqlite',
autoLoadModels: true,
synchronize: true,
host: join(__dirname, 'database.sqlite'),
}),
TweetsModule,
],
controllers: [AppController, TweetsController],
providers: [AppService, TweetsService],
})
export class AppModule {}
this happens when you have multiple nodejs modules loaded for the same #nestjs/core package. See them by running npm ls #nestjs/core. You can solve that by getting ride of those packages somehow and keeping only the one that your app depends on directly. Read the docs: https://docs.nestjs.com/faq/common-errors#cannot-resolve-dependency-error

how to load a nestjs module only if network is available

I'm working on a telegram bot (using nestjs-telegraf). I noticed that my app fails to start loading telegraf module if network connection is absent.
[Nest] 544032 - 08/06/2022, 10:01:43 LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
[Nest] 544032 - 08/06/2022, 10:01:43 ERROR [ExceptionHandler] request to https://api.telegram.org/bot5386725551:[REDACTED]/getMe failed, reason: getaddrinfo EAI_AGAIN api.telegram.org
FetchError: request to https://api.telegram.org/bot5386725551:[REDACTED]/getMe failed, reason: getaddrinfo EAI_AGAIN api.telegram.org
When this error occur I have to manually kill the process (CTRL-C) check the net and restart the nest's app.
How can I check if net is available before import nestjs's module or manage/intercept the EAI_AGAIN error?
this is the module that should run nestjs-telegraf that fails on net absence
import { EventModule } from './../event/event.module';
import { UsersModule } from 'src/users/users.module';
import { TowerModule } from './../tower/tower.module';
import { Module } from '#nestjs/common';
import { ConfigModule } from '#nestjs/config';
import { TelegrafModule } from 'nestjs-telegraf';
import { BotService } from './bot.service';
#Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TelegrafModule.forRoot({ token: process.env.BOT_TOKEN }),
TowerModule,
UsersModule,
EventModule,
],
providers: [BotService],
exports: [BotService],
})
export class BotModule {}
Thanks

nest js this.instance.use is not a function

I studying serverless nest.js with aws lambda
When I run serverless offline and send the request, an error occurred.
[Nest] 11048 - 2021. 07. 14. 오후 7:02:11 [NestFactory] Starting Nest application...
[Nest] 11048 - 2021. 07. 14. 오후 7:02:11 [InstanceLoader] AppModule dependencies initialized +16ms
[Nest] 11048 - 2021. 07. 14. 오후 7:02:11 [ExceptionHandler] this.instance.use is not a function +3ms
TypeError: this.instance.use is not a function
at ExpressAdapter.use (C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\adapters\http-adapter.js:20:30)
at NestApplication.use (C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\nest-application.js:140:26)
at C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\nest-factory.js:127:40
at Function.run (C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\errors\exceptions-zone.js:9:13)
at Proxy.<anonymous> (C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\nest-factory.js:126:46)
at Proxy.<anonymous> (C:\study\nestjs-practice\serverless-nestjs\node_modules\#nestjs\core\nest-factory.js:168:54)
at bootstrapServer (C:\study\nestjs-practice\serverless-nestjs\.build\src\lambda.js:16:17)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async handler (C:\study\nestjs-practice\serverless-nestjs\.build\src\lambda.js:23:20)
at async InProcessRunner.run (C:\study\nestjs-practice\serverless-nestjs\node_modules\serverless-offline\dist\lambda\handler-runner\in-process-runner\InProcessRunner.js:211:24)
at async LambdaFunction.runHandler (C:\study\nestjs-practice\serverless-nestjs\node_modules\serverless-offline\dist\lambda\LambdaFunction.js:355:20)
at async hapiHandler (C:\study\nestjs-practice\serverless-nestjs\node_modules\serverless-offline\dist\events\http\HttpServer.js:601:18)
at async module.exports.internals.Manager.execute (C:\study\nestjs-practice\serverless-nestjs\node_modules\#hapi\hapi\lib\toolkit.js:45:28)
at async Object.internals.handler (C:\study\nestjs-practice\serverless-nestjs\node_modules\#hapi\hapi\lib\handler.js:46:20)
at async exports.execute (C:\study\nestjs-practice\serverless-nestjs\node_modules\#hapi\hapi\lib\handler.js:31:20)
at async Request._lifecycle (C:\study\nestjs-practice\serverless-nestjs\node_modules\#hapi\hapi\lib\request.js:312:32)
at async Request._execute (C:\study\nestjs-practice\serverless-nestjs\node_modules\#hapi\hapi\lib\request.js:221:9)
How can I fix it?
Except for the lambda.ts and serverless.yml files, the settings are the same as when the nest.js project was created.
I'll post the code, please let me know if you know a solution
lambda.ts
import { NestFactory } from '#nestjs/core';
import { Handler, Context } from 'aws-lambda';
import { ExpressAdapter } from '#nestjs/platform-express';
import * as express from 'express';
import { Server } from 'http';
import { AppModule } from './app.module';
import { eventContext } from 'aws-serverless-express/middleware';
import { createServer, proxy } from 'aws-serverless-express';
const binaryMimeTypes: string[] = [];
let cachedServer: Server;
async function bootstrapServer(): Promise<Server> {
if (!cachedServer) {
const expressApp = express();
const nestApp = await NestFactory.create(
AppModule,
new ExpressAdapter(express),
);
nestApp.use(eventContext);
await nestApp.init();
cachedServer = createServer(expressApp, undefined, binaryMimeTypes);
}
return cachedServer;
}
export const handler: Handler = async (event: any, context: Context) => {
cachedServer = await bootstrapServer();
return proxy(cachedServer, event, context, 'PROMISE').promise;
};
serverless.yml
service:
name: serverless-nestjs
plugins:
- serverless-plugin-typescript
- serverless-plugin-optimize
- serverless-offline
provider:
name: aws
runtime: nodejs12.x
functions:
main: # The name of the lambda function
# The module 'handler' is exported in the file 'src/lambda'
handler: src/lambda.handler
events:
- http:
method: any
path: /{any+}

Nest can't resolve dependencies of the searchService (?). Please make sure that the argument at index

I am using Nestjs framework to develop my Elastic Service application.
I am using '#nestjs/elasticsearch' library inside my code and i am simply trying to establish database connection and use inside all other module. Please find my code example here.
My App Module looks below
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from './config/config.module';
import { DatabaseModule } from './database/database.module';
import { LayoutmgmtModule } from './layoutmgmt/layoutmgmt.module';
#Module({
imports: [ConfigModule,DatabaseModule, LayoutmgmtModule],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
My Database Module is,
import { Module } from '#nestjs/common';
import { ElasticsearchModule } from '#nestjs/elasticsearch';
import {ConfigModule} from '../config/config.module';
import {ConfigService} from '../config/config.service';
import {DatabaseService} from './database.service';
#Module({
imports:[ElasticsearchModule.registerAsync({
imports:[ConfigModule],
useFactory: async (configService: ConfigService) => ({
host: configService.get('ELASTIC_URL'),
log: 'trace',
requestTimeout: 3000
}),
inject:[ConfigService]
})],
providers:[DatabaseService],
})
export class DatabaseModule {}
My Database Service is,
import { Injectable,HttpException } from '#nestjs/common';
import { ElasticsearchService } from '#nestjs/elasticsearch';
import { Client } from 'elasticsearch';
#Injectable()
export class DatabaseService {
private readonly esClient:Client;
constructor(private readonly elasticsearchService: ElasticsearchService) {
try {
this.esClient = elasticsearchService.getClient();
this.esClient.ping({ requestTimeout: 3000 },function(err,res,status){
if (err || !(res)) {
console.log('Unable to connect to the server. Please start the server. Error:', err);
throw new HttpException({
status: 'error',
message: 'Unable to connect to the server. Please start the server. Error:'
}, 500);
} else {
console.log('Connected to Server successfully!',res, status);
}
});
}
catch(err) {
console.log('Error in connection' + err);
throw new HttpException({
status: 'error',
message: 'Unable to reach Elasticsearch cluster'
}, 500);
}
}
}
Now Above i had initialized the connection and its getting connected to the database without issues, But i am trying to re-use ElasticsearchService in another module/service called layout module
Layout Module looks below
import { Module } from '#nestjs/common';
import { LayoutmgmtController } from './layoutmgmt.controller';
import { LayoutmgmtService } from './layoutmgmt.service';
#Module({
controllers: [LayoutmgmtController],
providers: [LayoutmgmtService],
})
export class LayoutmgmtModule {}
Layout Service Looks below
import { Inject, Injectable, Dependencies } from '#nestjs/common';
import { ElasticsearchService } from '#nestjs/elasticsearch';
import { Client } from 'elasticsearch';
#Injectable()
export class LayoutmgmtService {
private readonly esClient:Client;
constructor(#Inject(ElasticsearchService) private readonly elasticsearchService: ElasticsearchService) {
this.esClient = elasticsearchService.getClient();
if (!this.esClient){
console.log("Elastic alreayd connected")
}
}
}
If i use the ElasticSErachService in above service inside the constructor i am getting the below error, I wanted to reuse the existing connection ..
[Nest] 10724 - 10/14/2019, 4:50:41 PM [ExceptionHandler] Nest can't resolve dependencies of the LayoutmgmtService (?). Please make sure that the argument at index [0] is available in the LayoutmgmtModule context. +40ms
Error: Nest can't resolve dependencies of the LayoutmgmtService (?). Please make sure that the argument at index [0] is available in the LayoutmgmtModule context.
at Injector.lookupComponentInExports (C:\Subu\Elastic\elastic-nest-js\node_modules#nestjs\core\injector\injector.js:183:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:744:11)
at Object. (C:\Subu\Elastic\elastic-nest-js\node_modules\ts-node\src\bin.ts:158:12)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
LayoutmgmtModule and DatabaseModule are not related anyway in your code.
You have registered the ElasticsearchModule in DatabaseModule but not in LayoutmgmtModule so it is unable to find the service.
Solution 1
You can get rid of the LayoutmgmtModule by just adding LayoutmgmtController and LayoutmgmtService in DataBaseModule and it should start working
Solution 2
You can make DataBaseModule as global by just adding #Global() before #Module decorator as mentioned here
You are not exporting ElasticsearchService anywhere. Perhaps your DatabaseModule should export it together with DatabaseService (LayoutmgmtService should use either of those).
On top of that, you should add given Service to providers of LayoutmgmtModule

Resources