DEV Community

Discussion on: Nx NestJs - Typeorm database connection with environment variables

 
ipreda profile image
Iulian Preda

I used @alexy4744/nx-mikro-orm-cli

I can actually provide some snippets for this., they might be useful for after you use the instructions from the package's page.

./mikro-orm.base.ts - at the root of the nx project I have a config that can be propagated for any number of projects

import { LoadStrategy, MikroORMOptions } from '@mikro-orm/core';
import { TSMigrationGenerator } from '@mikro-orm/migrations';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { SqlHighlighter } from '@mikro-orm/sql-highlighter';

export function mikroOrmConfigBase(path = __dirname): Partial<MikroORMOptions<PostgreSqlDriver>> {
  const undocumentedConfig: any = {
    ignoreSchema: ['columnar'], // schema generated by and for citus
  };
  return {
    entities: [path + '/src/**/*.entity{.ts,.js}'],
    entitiesTs: [path + '/src/**/*.entity.ts'],
    type: 'postgresql',
    persistOnCreate: false, // we have to manually call persistAndFlush


    allowGlobalContext: true,
    forceUtcTimezone: true,
    strict: true, // disable automatic type casting
    loadStrategy: LoadStrategy.JOINED,
    highlighter: new SqlHighlighter(), // default values:
    schemaGenerator: {
      disableForeignKeys: true, // wrap statements with `set foreign_key_checks = 0` or equivalent
      createForeignKeyConstraints: true, // whether to generate FK constraints
      ...undocumentedConfig,
    },

    migrations: {
      tableName: 'mikro_orm_migrations', // name of database table with log of executed transactions
      path: path + '/src/**/data-access/migrations', // path to the folder with migrations
      pathTs: path + '/src/**/data-access/migrations', // path to the folder with TS migrations (if used, we should put path to compiled files in `path`)
      glob: '!(*.d).{js,ts}', // how to match migration files (all .js and .ts files, but not .d.ts)
      transactional: true, // wrap each migration in a transaction
      disableForeignKeys: true, // wrap statements with `set foreign_key_checks = 0` or equivalent
      allOrNothing: true, // wrap all migrations in master transaction
      dropTables: true, // allow to disable table dropping
      safe: true, // allow to disable table and column dropping
      snapshot: true, // save snapshot when creating new migrations
      emit: 'ts', // migration generation mode
      generator: TSMigrationGenerator, // migration generator, e.g. to allow custom formatting
    },

    seeder: {
      path: path + '/src/**/data-access/seeder', // path to the folder with seeders
      pathTs: path + '/src/**/data-access/seeder', // path to the folder with TS seeders (if used, we should put path to compiled files in `path`)
      defaultSeeder: 'DatabaseSeeder', // default seeder class name
      glob: '!(*.d).{js,ts}', // how to match seeder files (all .js and .ts files, but not .d.ts)
      emit: 'ts', // seeder generation mode
      fileName: (className: string) => className, // seeder file naming convention
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

Please change any paths that might be different for your project.

Then in my backend project I have

/apps/backend/project.json -> under the "target" options

  "mikro-orm": {
      "executor": "@alexy4744/nx-mikro-orm-cli:run",
      "options": {
        "config": {
          "configPaths": ["./mikro-orm.config.ts"],
          "tsConfigPath": "./tsconfig.json",
          "useTsNode": true
        }
      }
    },
    "schema-create": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"schema:create --run\""
      }
    },
    "schema-fresh": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"schema:fresh --run --seed\""
      }
    },
    "schema-update": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"schema:update --safe --run\""
      }
    },
    "schema-drop": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"schema:drop --run\""
      }
    },
    "migration-initial": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"migration:create --initial\""
      }
    },
    "migration-create": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"migration:create\""
      }
    },
    "migration-fresh": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"migration:fresh --seed\""
      }
    },
    "seed": {
      "executor": "nx:run-commands",
      "options": {
        "command": "nx mikro-orm backend --args=\"seeder:run\""
      }
    }
Enter fullscreen mode Exit fullscreen mode

/apps/backend/mikro-orm.ts

import { mikroOrmConfigBase } from 'mikro-orm.config.base';

import { getEnvConfig } from './src/environments/env-config';
import { env } from './src/environments/environment';

const db = getEnvConfig(env).database;

const config = {
  ...mikroOrmConfigBase(__dirname),
  host: db.host,
  port: db.port,
  dbName: db.database,
  user: db.username,
  password: db.password,
};
export default Promise.resolve(config);
Enter fullscreen mode Exit fullscreen mode

As you can see I just reused the functions from the previous articles to get the env variables from the env file or from the environment.

Also in the data acces folder which for me hosts the entities i have a DatabaseSeeder.ts file that gets the repositories and populates the data.

I cannot post that one as it is 100% custom made for my project's needs and it wouldn't be useful at all, but I can post a small snippet

export class DatabaseSeeder extends Seeder {
  async run(em: EntityManager): Promise<void> {
    const repo = em.getRepository(Entity);
    const entity = repo.create(//customEntityData);


    em.persistAndFlush(entity);
  }
}

Enter fullscreen mode Exit fullscreen mode

I hope this helps!

Thread Thread
 
artifex profile image
Artifex

There must be something wrong with webpack i tried your approach it wont detect entities on runtime thats just sad, i just made another class to do my migrations i use this approach on runtime i use your previous service inject approach, but i manually override entity locations. Thank you!

Thread Thread
 
ipreda profile image
Iulian Preda

Yes. Webpack packs everything together in a single bundle and i suppose the paths are ruined in that case.
For that Nest has the "autoLoadEntories" option vut you need to import every entity in the ORM's module for it to work.