admin管理员组

文章数量:1287786

I am trying to create a seeder file in nestjs, the problem is when I run the project using start:dev, somehow nestjs also start seed.ts file with main.ts file. How can I make nestjs not start seed file when I run the project either on prod/dev but seed must be called only when I run the seed script.

Here is the seed.ts code

import { NestFactory } from '@nestjs/core'
import { Logger } from '@nestjs/mon'
import { SeederModule } from './database/seeder.module'
import { Seeder } from './database/seeder'

async function bootstrap() {
  NestFactory.createApplicationContext(SeederModule)
    .then((appContext) => {
      const logger = appContext.get(Logger)
      const seeder = appContext.get(Seeder)
      seeder
        .seedRoles()
        .then(() => {
          logger.debug('Seeding Roles plete!')
        })
        .catch((error) => {
          logger.error('Seeding Roles failed!')
          throw error
        })

      seeder
        .seedAdmin()
        .then(() => {
          logger.debug('Seeding Admin plete!')
        })
        .catch((error) => {
          logger.error('Seeding Admin failed!')
          throw error
        })
        .finally(() => appContext.close())
    })
    .catch((error) => {
      throw error
    })
}
bootstrap()

I am trying to create a seeder file in nestjs, the problem is when I run the project using start:dev, somehow nestjs also start seed.ts file with main.ts file. How can I make nestjs not start seed file when I run the project either on prod/dev but seed must be called only when I run the seed script.

Here is the seed.ts code

import { NestFactory } from '@nestjs/core'
import { Logger } from '@nestjs/mon'
import { SeederModule } from './database/seeder.module'
import { Seeder } from './database/seeder'

async function bootstrap() {
  NestFactory.createApplicationContext(SeederModule)
    .then((appContext) => {
      const logger = appContext.get(Logger)
      const seeder = appContext.get(Seeder)
      seeder
        .seedRoles()
        .then(() => {
          logger.debug('Seeding Roles plete!')
        })
        .catch((error) => {
          logger.error('Seeding Roles failed!')
          throw error
        })

      seeder
        .seedAdmin()
        .then(() => {
          logger.debug('Seeding Admin plete!')
        })
        .catch((error) => {
          logger.error('Seeding Admin failed!')
          throw error
        })
        .finally(() => appContext.close())
    })
    .catch((error) => {
      throw error
    })
}
bootstrap()
Here is the main.ts file for nestJS

import { Logger, ValidationPipe } from '@nestjs/mon'
import { NestFactory } from '@nestjs/core'
import { AppModule } from './modules/app/app.module'

async function bootstrap() {
  const app = await NestFactory.create(AppModule)
  app.enableCors()
  const port = process.env.PORT || 3000
  app.useGlobalPipes(new ValidationPipe())
  await app
    .listen(port)
    .then(() => {
      Logger.log(`App listening on port ${port}`)
    })
    .catch((err) => {
      Logger.log(`Error while connecting to port ${port}`, err)
    })
}
bootstrap()

And here is the package.json file

{
  "name": "jugg-website",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "link-module-alias && nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json",
    "seed": "ts-node -r tsconfig-paths/register src/seed.ts"
  },
  "dependencies": {
    "@nestjs/mon": "^7.6.13",
    "@nestjs/core": "^7.6.13",
    "@nestjs/jwt": "^7.2.0",
    "@nestjs/passport": "^7.1.5",
    "@nestjs/platform-express": "^7.6.13",
    "@nestjs/typeorm": "^7.1.5",
    "class-transformer": "^0.4.0",
    "class-validator": "^0.13.1",
    "config": "^3.3.6",
    "link-module-alias": "^1.2.0",
    "passport": "^0.4.1",
    "pg": "^8.5.1",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.6.6",
    "typeorm": "^0.2.32"
  },
  "devDependencies": {
    "@nestjs/cli": "^7.5.6",
    "@nestjs/schematics": "^7.2.7",
    "@nestjs/testing": "^7.6.13",
    "@types/express": "^4.17.11",
    "@types/jest": "^26.0.20",
    "@types/node": "^14.14.31",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.15.2",
    "@typescript-eslint/parser": "^4.15.2",
    "eslint": "^7.20.0",
    "eslint-config-prettier": "^8.1.0",
    "eslint-plugin-prettier": "^3.3.1",
    "jest": "^26.6.3",
    "prettier": "^2.2.1",
    "supertest": "^6.1.3",
    "ts-jest": "^26.5.2",
    "ts-loader": "^8.0.17",
    "ts-node": "^9.1.1",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.1.5"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Share Improve this question asked Apr 22, 2021 at 12:39 Saram Zafar IqbalSaram Zafar Iqbal 911 gold badge1 silver badge3 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

you can try setting KeepConnectionAlive option to true in typeOrm configuration in the app.module file https://github./nestjs/typeorm/issues/61

I was getting this error when running e2e tests. I found that the default nestjs template sets up the e2e tests with a beforeEach like this:

beforeEach(async () => {
  const moduleFixture: TestingModule = await Test.createTestingModule({
    imports: [AppModule],
  }).pile();

  app = moduleFixture.createNestApplication();
  await app.init();   

});

But since I had more than one test in the spec file (I'm a newbie to node.js dev so not sure whether this is the right thing to do or not, but regardless...), what was happening was the app was being initialised once per test which meant it was attempting to create multiple connections to the database.

The solution was quite simple. Change the beforeEach to beforeAll

beforeAll(async () => {
  const moduleFixture: TestingModule = await Test.createTestingModule({
    imports: [AppModule],
  }).pile();

  app = moduleFixture.createNestApplication();
  await app.init();   

});

And don't forget to close the app when the tests are done

afterAll(async () => {
  await app.close();
});

In my case, the problem was in my main.ts file. I ran my module with the TypeORM twice without noticing, because I was trying access my ConfigService so that I could use environment variables for some other service than my TypeORM database connection.

main.ts that causes the error:

...

async function bootstrap(): Promise<void> {
  // the next line actually initiates a DB connection
  const appContext = await NestFactory.createApplicationContext(MailModule);
  const configService = appContext.get<ConfigService>(ConfigService);
  // by now, we already established a DB connection, so trying to
  // reinstantiate the connection will cause the error
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    MailModule,
    {
      transport: Transport.REDIS,
      options: {
        port: configService.get<number>('REDIS.PORT'),
        host: configService.get<string>('REDIS.HOST'),
      },
    },
  );
  await app.listen();
}
bootstrap();

The solution:

...

async function bootstrap(): Promise<void> {
  const appContext = await NestFactory.createApplicationContext(MailModule);
  // we close the redundant connection before we mount the app.
  await getConnection('default').close();
  const configService = appContext.get<ConfigService>(ConfigService);
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    MailModule,
    {
      transport: Transport.REDIS,
      options: {
        port: configService.get<number>('REDIS.PORT'),
        host: configService.get<string>('REDIS.HOST'),
      },
    },
  );
  await app.listen();
}
bootstrap();

本文标签: