如何实现 NestJs 配置文件、.env (DOTENV)、TypeOrm 数据库配置和迁移
我一直在尝试让我的 TypeOrm Config 与 Migrations 和 .env 很好地配合工作,而不需要在两个地方指定它。
困难在于 - 我的迁移脚本需要读取立即返回的对象 -
{
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/登记./node_modules/typeorm/cli.js --config dist/app/config/database.configuration.js"
这意味着我的迁移需要调用 (new DatabaseConfiguration()).createTypeOrmOptions()
来获取对象。否则,它将隐藏在 DatabaseConfiguration
类的 createTypeOrmOptions
函数内。
这导致了 TypeOrm 错误: MissingDriverError:错误的驱动程序:给出“未定义”。支持的驱动程序有:“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
文件中看到的,它正在寻找作为对象 connection.options< 的连接/code> 可以获取
type
来创建正确的驱动程序)-
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
未定义。
因此,对于那些不想花几个小时调试这个的人,请参阅下面我的详细设置...如果有帮助的话,请投票我的问题和答案,因为我在任何地方都找不到全面的答案。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我的设置从开始到结束。
首先,让我们解决使用 NestJs、dotenv 和配置文件运行数据库的基本设置。显然,我们已经放弃了不支持
.env
的 ormconfig.json。app.module.ts
database.configuration.ts
.env
这样,您的应用程序应该连接到 postgres 数据库并运行 TypeOrm 查询。
但是如果您想支持迁移怎么办?
我们需要在database.configuration.ts文件之上添加一个小的附加层来提取需要返回的迁移对象。
所以这是一个新的配置文件:
migration.configuration.ts
然后剩下要做的就是更新我们的
package.json
以查看migration.configuration。 ts
文件调用我们的databaseConfig 文件并返回渲染的对象。package.json
我在那里留下了一些其他脚本...但重要的是
typeorm
脚本,再次参见--config
它定义了 TypeOrm 配置对象将返回的位置。Here's my set up start to finish.
First lets address a basic set up for just running the DB with NestJs, dotenv, and config files. Obviously we've moved away from ormconfig.json which doesn't support
.env
.app.module.ts
database.configuration.ts
.env
With that, your app should connect to a postgres DB and run TypeOrm queries.
But what if you want to support migrations?
We need to add a small additional layer on top of the
database.configuration.ts
file to extract the object that needs to get returned for migrations.So here's a new config file:
migration.configuration.ts
Then all that's left to do, is update our
package.json
to look to themigration.configuration.ts
file which is calling our databaseConfig file and returning the rendered object.package.json
I left in some of my other scripts in there... but it's the
typeorm
one that matters, again see--config
which defines the location where the TypeOrm config object will be returned.@Jay 提出的解决方案对我有用,但迁移除外。我通过稍微修改 migration.configuration.ts 来修复它,如下所示:
技巧是实例化
ConfigModule
以读取.env
文件存在于项目的根目录中。为了利用不同的
*.env
文件,人们可能希望将其作为参数传递给forRoot()
方法(如 文档),例如:Solution presented by @Jay worked for me, except migrations. I have managed to fix it by slightly modifying the migration.configuration.ts as follows:
The trick was to instantiate
ConfigModule
in order to read.env
file present in the project's root directory.In order to utilize different
*.env
file, one might want to pass it as an argument toforRoot()
method (as described in documentation), e.g.: