skip to Main Content

the error I have is similar to this: Dependencies not being injected on NestJS with Serverless and AWS, but the solution they give is already configured in my project, when I run the normal app, with npm run start:.. it works correctly, but when running it with serverless, I have the failure of the undefined in the services in the constructor, here I leave a summary of the configuration and code:

libsutilsutils.module.ts

import { Module } from '@nestjs/common';
import { UtilsService } from './utils.service';
import { UtilsController } from './utils.controller';

@Module({
  providers: [UtilsService],
  exports: [UtilsService],
  controllers: [UtilsController]
})
export class UtilsModule {}

libsutilsutils.service.ts

import {
  Injectable,
} from '@nestjs/common';

@Injectable()
export class UtilsService {
  getHello(): string {
    return 'Hello World!';
  }
}

mcrseguros-estadosrcseguros-estado.module.ts

import { Module } from '@nestjs/common';
import { SegurosEstadoService } from './seguros-estado.service';
import { SegurosEstadoController } from './seguros-estado.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CitiesDane } from '../../../libs/entities/CitiesDane';
import { InsuranceConfigurations } from '../../../libs/entities/InsuranceConfigurations';
import { Fasecolda } from '../../../libs/entities/Fasecolda';
import { UtilsModule } from '../../../libs/utils/utils.module';
import { LoggerModule } from '../../../libs/logger/logger.module';
import { ErrorsService } from '../../../libs/errors/errors.service';
import * as dotenv from 'dotenv';

dotenv.config();
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql', // Tipo de base de datos, por ejemplo, 'mysql', 'mariadb', 'postgres', etc.
      host: process.env.DB_HOST, // Dirección del host
      port: parseInt(process.env.DB_PORT, 10), // Puerto de la base de datos
      username: process.env.DB_USER, // Usuario de la base de datos
      password: process.env.DB_PW, // Contraseña del usuario de la base de datos
      database: process.env.DB_NAME, // Nombre de la base de datos
      entities: [__dirname + '/../../../libs/entities/**/*{.ts,.js}'], // Ruta a las entidades
      synchronize: process.env.DB_SYNC === "true", // Solo en desarrollo; sincroniza la estructura de la base de datos con las entidades
      autoLoadEntities: true,
      logging: ['query', 'error'],
    }),
    TypeOrmModule.forFeature([CitiesDane]),
    TypeOrmModule.forFeature([InsuranceConfigurations]),
    TypeOrmModule.forFeature([Fasecolda]),
    UtilsModule,
    LoggerModule,
    ErrorsService,
  ],
  providers: [SegurosEstadoService],
  controllers: [SegurosEstadoController],
})
export class SegurosEstadoModule {}

mcrseguros-estadosrcseguros-estado.controller.ts

import { Body, Controller, Get, Inject, Post } from '@nestjs/common';
import { LoggerService } from '../../../libs/logger/logger.service';
import { UtilsService } from '../../../libs/utils/utils.service';
import * as path from 'path';
import { SegurosEstadoService } from './seguros-estado.service';
const pdf2base64 = require('pdf-to-base64');
const fse = require('fs-extra');

@Controller("seguros-estado")
export class SegurosEstadoController {
  constructor(
    private utilService: UtilsService,
    private estadoService: SegurosEstadoService,
    private loggerService: LoggerService,
  ) {
    console.log("🚀 ~ SegurosEstadoController ~ utilService:", utilService) // undefined
    console.log("🚀 ~ SegurosEstadoController ~ loggerService:", loggerService) // undefined
    console.log("🚀 ~ SegurosEstadoController ~ estadoService:", estadoService) // undefined
    }
  
  @Get('test-r') 
  async testR() {
    console.log(this.utilService.getHello()); // cannon read prop getHello to undefined
    return { succesfully: true}
  }

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    //"allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "paths": {
      "libs/*": ["libs/*"]
    }
  },
  "include": ["src/**/*.ts", "mcr/**/*.ts", "libs/**/*.ts"],
}

serverless.yml

service: nestjs-microservices

frameworkVersion: '4'

provider:
  name: aws
  runtime: nodejs18.x
  region: us-east-1
  memorySize: 128
  timeout: 240
  environment:
    NODE_ENV: production
    REDIS_HOST: <redis-host>
    REDIS_PORT: <redis-port>

functions:
  segurosEstado:
    handler: mcr/seguros-estado/src/main.handler
    events:
      - http:
          path: seguros-estado/{proxy+}
          method: ANY
          cors: true

  allianz:
    handler: mcr/allianz/src/main.handler
    events:
      - http:
          path: allianz/{proxy+}
          method: ANY
          cors: true

plugins:
  - serverless-offline

custom:
  serverless-offline:
    httpPort: 3001
    debug: true

mcrseguros-estadosrcmain.ts

import { NestFactory } from '@nestjs/core';
import serverlessExpress from '@vendia/serverless-express';
import { Handler } from 'aws-lambda';
import { SegurosEstadoModule } from './seguros-estado.module';

let cachedHandler: Handler;

export const handler: Handler = async (event, context) => {
  if (!cachedHandler) {
    const app = await NestFactory.create(SegurosEstadoModule);
    await app.init();

    // Obtén la instancia de Express para serverless-express
    const expressApp = app.getHttpAdapter().getInstance();

    // Configura el adaptador serverless-express
    cachedHandler = serverlessExpress({ app: expressApp });
  }

  return cachedHandler(event, context);
};

// Si no estás en un entorno de Lambda, puedes correrlo como un servidor HTTP local
if (process.env.IS_LOCAL === 'true') {
  const bootstrap = async () => {
    const app = await NestFactory.create(SegurosEstadoModule);
    const port = process.env.SEGUROS_ESTADO_PORT || 3001;  // Usar el puerto desde el .env
    await app.listen(port);
    console.log(`Microservicio Seguros Estado corriendo en http://localhost:${port}`);
  };

  bootstrap();
}

Now when I run the app with "ts-node-dev mcr/secure-state/src/main.ts" it works correctly, but with "npx serverless offline":

Server ready: http://localhost:3001 �


ANY /dev/seguros-estado/seguros-estado/test-r (λ: segurosEstado)
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [NestFactory] Starting Nest application...
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [NestFactory] Starting Nest application... +7ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] TypeOrmModule dependencies initialized +503ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] LoggerModule dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] ErrorsService dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] TypeOrmModule dependencies initialized +1ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] LoggerModule dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] ErrorsService dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] UtilsModule dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:25 p. m.     LOG [InstanceLoader] UtilsModule dependencies initialized +0ms
query: SELECT VERSION() AS `version`
query: SELECT VERSION() AS `version`
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +1656ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [InstanceLoader] TypeOrmModule dependencies initialized +1ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
� ~ SegurosEstadoController ~ utilService: undefined
� ~ SegurosEstadoController ~ loggerService: undefined
� ~ SegurosEstadoController ~ estadoService: undefined
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [InstanceLoader] SegurosEstadoModule dependencies initialized +1ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [RoutesResolver] SegurosEstadoController {/seguros-estado}: +15ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [RouterExplorer] Mapped {/seguros-estado/test-r, GET} route +9ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [RouterExplorer] Mapped {/seguros-estado/poliza-r, POST} route +1ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [RouterExplorer] Mapped {/seguros-estado/print-r, POST} route +1ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [RoutesResolver] UtilsController {/utils}: +1ms
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.     LOG [NestApplication] Nest application successfully started +5ms
Microservicio Seguros Estado corriendo en http://localhost:3001
[Nest] 6640  - 08/01/2025, 2:04:27 p. m.   ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'getHello')
(λ: segurosEstado) RequestId: 04af350e-244b-4dbf-9113-9c4c9476cda3  Duration: 17758.24 ms  Billed Duration: 17759 ms

2

Answers


  1. Chosen as BEST ANSWER

    Finally the solution was to add the decorators @Inject(--service_name--) in the injections in the constructor:

    @Inject(UtilsService) private readonly utilService: UtilsService,
        @Inject(SegurosEstadoService) private readonly estadoService: SegurosEstadoService,
        @Inject(LoggerService) private readonly loggerService: LoggerService,
    

  2. You can try adding "esModuleInterop": true to your tsconfig.json file and load your handlers in your serverless.yml configuration file from dist folder.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search