'How to implement NestJs Configuration Files, .env (DOTENV), TypeOrm Database Configuration, AND Migrations
I've been trying to get my TypeOrm Config to work nicely with Migrations and .env without needing to specify it in two places.
The struggle is this - My migration script needs to read an immediately returned object -
{
type: 'postgres',
host: '127.0.0.1',
port: 5432,
username: 'postgres',
password: 'myPassword',
database: 'postgres',
entities: [ 'dist/**/*.entity.js' ],
logging: [ 'query', 'error', 'schema' ],
synchronize: false,
migrations: [ 'dist/app/database/migrations/*.js' ],
cli: { migrationsDir: 'src/app/database/migrations' },
namingStrategy: SnakeNamingStrategy {
nestedSetColumnNames: { left: 'nsleft', right: 'nsright' },
materializedPathColumnName: 'mpath'
},
subscribers: [],
migrationsRun: false,
dropSchema: false
}
But when I use NestJs's proposed configuration while also utilizing a .env (DOTENV) file, the solution looks like this:
import {TypeOrmModuleOptions, TypeOrmOptionsFactory} from "@nestjs/typeorm";
import {SnakeNamingStrategy} from "typeorm-naming-strategies";
export class DatabaseConfiguration implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions | Promise<TypeOrmModuleOptions> {
return {
type: "postgres",
host: process.env.POSTGRES_HOST,
port: parseInt(process.env.POSTGRES_PORT, 10) || 5432,
username: process.env.POSTGRES_USERNAME,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DATABASE,
entities: [process.env.TYPEORM_ENTITIES],
logging: true,
synchronize: false,
migrations: [process.env.TYPEORM_MIGRATIONS],
cli: {
migrationsDir: process.env.TYPEORM_MIGRATIONS_DIR,
},
namingStrategy: new SnakeNamingStrategy(),
};
}
}
I've told TypeOrm where to find the config file (very important) in my package.json like so (see --config tag):
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/database.configuration.js"
Which means my migration would need to call
(new DatabaseConfiguration()).createTypeOrmOptions()
to get the object. Otherwise it would be hidden inside the DatabaseConfiguration class, inside the createTypeOrmOptions function.
This created the TypeOrm error:
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs"
Because as you can see in the node_modules/typeorm/driver/DriverFactory.js file, it's looking for the connection to come through as an object connection.options where it can pick up the type to create the correct driver)-
DriverFactory.prototype.create = function (connection) {
console.log(connection.options);
var type = connection.options.type;
switch (type) {
case "mysql":
return new MysqlDriver_1.MysqlDriver(connection);
case "postgres":
return new PostgresDriver_1.PostgresDriver(connection);
...
}
}
};
My type isn't getting defined.
So, for the people who don't want to spend hours debugging this, please see my detailed setup below... and upvote my question and answer if it helped, because I couldn't find a comprehensive answer anywhere.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
