如何实现 NestJs 配置文件、.env (DOTENV)、TypeOrm 数据库配置和迁移
How to implement NestJs Configuration Files, .env (DOTENV), TypeOrm Database Configuration, AND Migrations
我一直在尝试让我的 TypeOrm 配置与 Migrations 和 .env 一起很好地工作,而无需在两个地方指定它。
困难在于 - 我的迁移脚本需要读取立即返回的 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
}
但是当我使用 NestJs 建议的配置同时还使用 .env (DOTENV) 文件时,解决方案如下所示:
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(),
};
}
}
我已经告诉 TypeOrm 在我的 package.json
中哪里可以找到配置文件(非常重要),就像这样(参见 --config
标签):
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/database.configuration.js"
这意味着我的迁移需要调用
(new DatabaseConfiguration()).createTypeOrmOptions()
得到 object。否则它将隐藏在 DatabaseConfiguration
class 中,createTypeOrmOptions
函数中。
这造成了 TypeOrm 错误:
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"
因为正如您在 node_modules/typeorm/driver/DriverFactory.js
文件中看到的那样,它正在寻找作为 object connection.options
的连接,它可以在其中获取 type
创建正确的 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);
...
}
}
};
我的 type
没有定义。
因此,对于那些不想花几个小时调试它的人,请查看下面我的详细设置...如果有帮助,请为我的问题和答案投票,因为我无法在任何地方找到全面的答案.
这是我的设置开始到结束。
首先,让我们解决一个基本设置,仅 运行 使用 NestJs、dotenv 和配置文件连接数据库。显然我们已经远离了不支持 .env
.
的 ormconfig.json
app.module.ts
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRootAsync({
useClass: DatabaseConfiguration,
}),
...
]
database.configuration.ts
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(),
};
}
}
.env
POSTGRES_TYPE="postgres"
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USERNAME="postgres"
POSTGRES_PASSWORD="takeMyPassword123"
POSTGRES_DATABASE=postgres
TYPEORM_ENTITIES="dist/**/*.entity.js"
TYPEORM_MIGRATIONS="dist/database/migrations/*.js"
TYPEORM_MIGRATIONS_DIR="src/database/migrations"
这样,您的应用程序应该连接到 postgres 数据库和 运行 TypeOrm 查询。
但是如果你想支持迁移呢?
我们需要在 database.configuration.ts
文件的顶部添加一个小的附加层来提取需要为迁移返回的对象。
所以这是一个新的配置文件:
migration.configuration.ts
import {DatabaseConfiguration} from "./database.configuration";
export default (new DatabaseConfiguration()).createTypeOrmOptions()
然后剩下要做的就是更新我们的 package.json
以查看正在调用我们的 databaseConfig 文件并返回渲染对象的 migration.configuration.ts
文件。
package.json
"scripts": {
...
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/migration.configuration.js",
"make:migration-initial": "npm run build && npm run typeorm migration:generate -- -n initial",
"migrate": "npm run build && npm run typeorm migration:run",
"migrate:rollback": "npm run build && npm run typeorm migration:revert",
"migrate:destroy": "npm run build && npm run typeorm migration:revert && rimraf src/app/database/migrations"
...
},
我把我的其他一些脚本留在了那里...但重要的是 typeorm
,请再次参阅 --config
,它定义了返回 TypeOrm 配置对象的位置。
我一直在尝试让我的 TypeOrm 配置与 Migrations 和 .env 一起很好地工作,而无需在两个地方指定它。
困难在于 - 我的迁移脚本需要读取立即返回的 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
}
但是当我使用 NestJs 建议的配置同时还使用 .env (DOTENV) 文件时,解决方案如下所示:
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(),
};
}
}
我已经告诉 TypeOrm 在我的 package.json
中哪里可以找到配置文件(非常重要),就像这样(参见 --config
标签):
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/database.configuration.js"
这意味着我的迁移需要调用
(new DatabaseConfiguration()).createTypeOrmOptions()
得到 object。否则它将隐藏在 DatabaseConfiguration
class 中,createTypeOrmOptions
函数中。
这造成了 TypeOrm 错误:
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"
因为正如您在 node_modules/typeorm/driver/DriverFactory.js
文件中看到的那样,它正在寻找作为 object connection.options
的连接,它可以在其中获取 type
创建正确的 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);
...
}
}
};
我的 type
没有定义。
因此,对于那些不想花几个小时调试它的人,请查看下面我的详细设置...如果有帮助,请为我的问题和答案投票,因为我无法在任何地方找到全面的答案.
这是我的设置开始到结束。
首先,让我们解决一个基本设置,仅 运行 使用 NestJs、dotenv 和配置文件连接数据库。显然我们已经远离了不支持 .env
.
app.module.ts
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRootAsync({
useClass: DatabaseConfiguration,
}),
...
]
database.configuration.ts
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(),
};
}
}
.env
POSTGRES_TYPE="postgres"
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USERNAME="postgres"
POSTGRES_PASSWORD="takeMyPassword123"
POSTGRES_DATABASE=postgres
TYPEORM_ENTITIES="dist/**/*.entity.js"
TYPEORM_MIGRATIONS="dist/database/migrations/*.js"
TYPEORM_MIGRATIONS_DIR="src/database/migrations"
这样,您的应用程序应该连接到 postgres 数据库和 运行 TypeOrm 查询。 但是如果你想支持迁移呢?
我们需要在 database.configuration.ts
文件的顶部添加一个小的附加层来提取需要为迁移返回的对象。
所以这是一个新的配置文件:
migration.configuration.ts
import {DatabaseConfiguration} from "./database.configuration";
export default (new DatabaseConfiguration()).createTypeOrmOptions()
然后剩下要做的就是更新我们的 package.json
以查看正在调用我们的 databaseConfig 文件并返回渲染对象的 migration.configuration.ts
文件。
package.json
"scripts": {
...
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/migration.configuration.js",
"make:migration-initial": "npm run build && npm run typeorm migration:generate -- -n initial",
"migrate": "npm run build && npm run typeorm migration:run",
"migrate:rollback": "npm run build && npm run typeorm migration:revert",
"migrate:destroy": "npm run build && npm run typeorm migration:revert && rimraf src/app/database/migrations"
...
},
我把我的其他一些脚本留在了那里...但重要的是 typeorm
,请再次参阅 --config
,它定义了返回 TypeOrm 配置对象的位置。