Today I Learned

12 posts about #nodejs

Typeorm - running migrations in separate transactions

IMPORTANT! Be careful when applying this technique using MySQL database, because some operations there have implicit commit, for example CREATE TABLE or ALTER TABLE. This means schema changes won’t be rolled back even if something later in transaction fails. Read more about implicit commits and transactional DDL in different database engines.
Example below uses PostgreSQL database where DDL changes do not cause auto-commiting.

Let’s say we have a project with hundreds of migrations, and for some reason you have to rebuild the whole schema from ground-up.

By default TypeORM runs all migrations in a single transaction so if something near the end fails, the whole progress is lost and you have to rerun all of them again.

Fortunately, there is a way to instruct TypeORM to run each migration in a separate transaction:

typeorm migration:run -t each

What’s interesting, typing typeorm migration:run -t in terminal won’t give us a list of options, and documentation also doesn’t specify them (at least I couldn’t find it).

We can inspect list of available options in node_modules/typeorm/commands/MigrationGenerateCommand.js

switch (args.t) {
  case "all":
    options.transaction = "all";
  case "none":
  case "false":
    options.transaction = "none";
  case "each":
    options.transaction = "each";
    // noop

Let’s try it out:

First, we generate a migration that adds a Customer table, notice we have unique index on name:

 export class addCustomer1657889795075 implements MigrationInterface {
  name = 'addCustomer1657889795075';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `CREATE TABLE "customer" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_a7a13f4cacb744524e44dfdad32" PRIMARY KEY ("id"))`,
    await queryRunner.query(
      `CREATE UNIQUE INDEX "IDX_ac1455877a69957f7466d5dc78" ON "customer" ("name") `,

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `DROP INDEX "public"."IDX_ac1455877a69957f7466d5dc78"`,
    await queryRunner.query(`DROP TABLE "customer"`);

Next, let’s define a migration that fails - let’s say we insert duplicate name to customer table:

 export class addDefaultsToCustomer1657889827769 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`INSERT INTO "customer" ("name") VALUES ('Selleo')`);
    await queryRunner.query(`INSERT INTO "customer" ("name") VALUES ('Selleo')`);

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DELETE FROM "customer"`);

Let’s run it in normal mode with typeorm migration:run and inspect the output:

Migration "addDefaultsToCustomer1657889827769" failed, error: duplicate key value violates unique constraint "IDX_ac1455877a69957f7466d5dc78"

We were smart enough to know it will fail, inspecting the database schema in pgAdmin also tells us that much: no-changes

But if we run it with typeorm migration:run -t each we can see the first migration was applied, event though the second one failed:

The table was correctly added: changed-schema

And no data was inserted: no-data-inserted-proof

This way we can save ourselves some time when running a lot of migrations.

Remove/change modifiers of an existing regexp

The following regexp has a couple of modifier:

const regexp = /my-project-id/gi
// -> /my-project-id/gi

to reuse the existing regexp and remove the modifier, create a new instance of the regexp with a blank modifier:

const regexp2 = new RegExp(regexp, '')
// -> /my-project-id/

You can also omit modifiers from existing ones specified in the regexp:

const regexp3 = new RegExp(regexp, regexp.flags.replace('g', ''))
// -> /my-project-id/i

Faster E2E tests & stable DB setup in NestJS

Link to earlier post on E2E tests in NestJS

The following setup allowed to cut down the duration of E2E tests by 2/3 (from 356s to 111s). The app uses TypeORM.

A single app instance for the whole E2E run.

File: test/utils/create-testing-module.ts

// Single app instance
let app: INestApplication

export async function createTestingModule() {
  const moduleBuilder = Test.createTestingModule({
    imports: [AppModule],

  const module = await moduleBuilder.compile()

  app = module.createNestApplication(undefined, {
    logger: false,

  await app.init()

export async function closeTestingModule() {
  await getConnection().dropDatabase()

  if (app) await app.close()

export function getTestingModule() {
  if (!app) throw 'No app was initialized!!!'

  return app

Functions to drop & clean up the DB:

File test/utils/clean-up-db.ts - a collection of functions to drop/clean up the DB:

const tableNames = [

export async function cleanUpDb() {
  const connection = getConnection()

  for (const tableName of tableNames) {
    await connection.query(`DELETE FROM ${tableName};`)

export async function dropTables() {
  const connection = await createConnection({
    type: 'mysql',
    username: process.env.TYPEORM_USERNAME,
    password: process.env.TYPEORM_PASSWORD,
    database: process.env.TYPEORM_DATABASE,

  await connection.query('SET FOREIGN_KEY_CHECKS=0;')
  for (const tableName of tableNames) {
    await connection.query(`DROP TABLE IF EXISTS ${tableName};`)

  await connection.close()

Hooks to bootstrap the app and clean up the DB between executions:

File jest.e2e-setup.ts - to be included to the jest configuration:

beforeAll(async () => {
  await dropTables()
  await createTestingModule()

afterAll(async () => {
  await closeTestingModule()

beforeEach(async () => {
  await cleanUpDb()

SQL migrations in TypeORM before a test suite

The setting is via migrationsRun. In this way, TypeORM runs SQL migrations.

App instance for test cases

describe('TagResolver (E2E)', () => {
  let app: INestApplication
  let userModel: UserModel

  beforeEach(async () => {
    app = getTestingModule()

    tagModel = app.get<TagModel>(TagModel)

  it('verifies the app', () => {
    // ...

Accessing request in the validate of JWT strategy

The default definition for the JwtStrategy offers to pass the payload parameter to the validate function:

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { jwtConstants } from './constants';

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };

There are sometimes cases where the validate fn should receive the request object. To have this possibility, specify the passReqToCallback to true:

      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,
      passReqToCallback: true // <-----

In that way, the validate function will firstly receive request and secondly jwtPayload:

  async validate(request: Request, payload: any) {
    // do something with the request
    return { userId: payload.sub, username: payload.username };

Creating a type that requires alternative fields

In order to create a type that should require one of the alternative fields be required, use the union with alternative. For instance, the following type requires a person to have either socialSecurityNumber or dateOfBirth present:

type Person = {
  name: string
} & (
  | { socialSecurityNumber: string }
  | { dateOfBirth: string}

The first part contains a standard set of fields:

type Person = {
  name: string

that is combined with two alternative types using the union (&) and alternative (|) signs:

& (
  | { socialSecurityNumber: string}
  | { dateOfBirth: string}

Then these examples are valid:

const simon: Person = {
  name: 'simon',
  socialSecurityNumber: 'ssn'

const peter: Person = {
  name: 'peter',
  dateOfBirth: '01.01.1901'

const pete: Person = {
  name: 'peter',
  dateOfBirth: '01.01.1901',
  socialSecurityNumber: 'ssn'

But an object containing just name will generate an error:

const invalidPerson: Person = {
  name: 'peter',

Type '{ name: string; }' is not assignable to type 'Person'.
  Type '{ name: string; }' is not assignable to type '{ name: string; } & { dateOfBirth: string; }'.
    Property 'dateOfBirth' is missing in type '{ name: string; }' but required in type '{ dateOfBirth: string; }'.

Dynamically accessing static properties of an instance

Use Object.getPrototypeOf(<instance>).constructor.<static-property-name> to access static-property-name of instance. Example:

class Person {
  name = 'person'

  static names = ['simon', 'nomis']

class Dog {
  name = 'dog'

  static names = ['kajtek', 'maniek']

const person = new Person()
const dog = new Dog()

function displayNames(named: Person | Dog) {
  console.log(`${} - names: ${Object.getPrototypeOf(named).constructor.names}`)


Results in:

[LOG]: "person - names: simon,nomis" 
[LOG]: "dog - names: kajtek,maniek" 

Breaking change in NestJS mailer's API - pug templates

With this commit - ver. 1.6.0, it is required to specify leading characters: ./ in the template’s name. Otherwise, the mailer complains about the missing template:

Error: ENOENT: no such file or directory, open 'sendDocument.pug'
    at Object.openSync (fs.js:465:3)
    at Object.readFileSync (fs.js:368:35)
    at handleTemplateCache (/api/node_modules/pug/lib/index.js:245:37)
    at Object.exports.renderFile (/api/node_modules/pug/lib/index.js:458:10)
    at Object.exports.renderFile (/api/node_modules/pug/lib/index.js:448:21)

A sample correct name:

await this.mailer.sendMail({
  template: './sendDocument',
  // ...

Bull board for NestJS

Install packages

  • @bull-board/api
  • @bull-board/express
  • express-basic-auth

Setup the board in the main file

In the main.ts file:

const app = await NestFactory.create(AppModule, {
  // ...

const serverAdapter = new ExpressAdapter()

const aQueue = app.get<Queue>(

  queues: [
    new BullAdapter(aQueue),

    users: {
      user: 'password',
    challenge: true,

Bull board will be protected with basic HTTP authentication.

Impact of TYPEORM_CONNECTION on ormconfig in TypeOrm

When TypeOrm detects that either TYPEORM_CONNECTION or TYPEORM_URL env variables are set up, it will read the config from the env variables and ignore the one that is given by the ormconfig.js file:

// try to find connection options from any of available sources of configuration
if (PlatformTools.getEnvVariable("TYPEORM_CONNECTION") || PlatformTools.getEnvVariable("TYPEORM_URL")) {
   connectionOptions = await new ConnectionOptionsEnvReader().read();

From their docs:

Sometimes, you may want to use multiple configurations using different formats. When calling getConnectionOptions() or attempting to use createConnection() without the connection options, Typeorm will attempt to load the configurations, in this order:

  • From the environment variables. Typeorm will attempt to load the .env file using dotEnv if it exists. If the environment variables TYPEORM_CONNECTION or TYPEORM_URL are set, Typeorm will use this method.
  • From the ormconfig.env.
  • From the other ormconfig.[format] files, in this order: [js, ts, json, yml, yaml, xml].

Tip for the future: to use the ormconfig.js file, do not set up the TYPEORM_CONNECTION and TYPEORM_URL env vars.

Resolving "Nest can't resolve dependencies of the X"

From time to time you can see the error:

Nest can’t resolve dependencies of the X. Please make sure that the “Y” property is available in the current context.

In case of services:

  • Ensure the service is exposed in the module
  • Ensure the module exposing the service is included in the module
  • In tests: ensure the service is provided in the createTestingModule function
  • Check for circular dependencies; if you think there is one, use forwardRef in the place where the service is injected: @Inject(forwardRef(() => UserService)) private readonly userService: UserService