我在 NestJS 应用程序中使用 TypeORM。我app.module.ts有一个非常标准的设置并且可以工作:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigService } from './config/config.service';
import { ConfigModule } from './config/config.module';
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
// @ts-ignore issues with the type of the database
useFactory: async (configService: ConfigService) => ({
type: configService.getDBType(),
host: configService.getDBHost(),
port: configService.getDBPort(),
username: configService.getDBUser(),
password: configService.getDBPassword(),
database: configService.getDBName(),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
inject: [ConfigService],
}),
ConfigModule,
],
controllers: [],
providers: [],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
事情是这样的。如果我想在 CLI 上运行迁移,我需要有一个ormconfig.js. 我不希望ormconfig.js在我的config.service.js. 我创建了一个如下所示的.env文件:
TYPEORM_CONNECTION = mysql
TYPEORM_HOST = app-db
TYPEORM_USERNAME = user
TYPEORM_PASSWORD = password
TYPEORM_DATABASE = db-dev
TYPEORM_PORT = 3306
TYPEORM_SYNCHRONIZE = true
TYPEORM_LOGGING = true
TYPEORM_ENTITIES = src/**/*.ts
TYPEORM_MIGRATIONS = src/migrations/**/*.ts
TYPEORM_MIGRATIONS_TABLE_NAME = migrations
Run Code Online (Sandbox Code Playgroud)
由于 env vars 现在定义如下:TypeORM Documentation,我继续并重构app.module.ts为如下所示:
@Module({
imports: [TypeOrmModule.forRoot(), ConfigModule],
controllers: [],
providers: [],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
现在DATABASE_HOST,DATABASE_PORT当我使用typeorm cli.
这是我的 config.service.ts
import * as dotenv from 'dotenv';
import * as Joi from '@hapi/joi';
import * as fs from 'fs';
import { Injectable } from '@nestjs/common';
import { keys, pick } from 'lodash';
export type EnvConfig = Record<string, string>;
@Injectable()
export class ConfigService {
private readonly envConfig: Record<string, string>;
constructor(filePath: string) {
const envNames = keys(this.getJoiObject());
const envFromProcess = pick(process.env, envNames);
const envFromFile = fs.existsSync(filePath) ? dotenv.parse(fs.readFileSync(filePath)) : {};
const envConfig = Object.assign(envFromFile, envFromProcess);
this.envConfig = this.validateInput(envConfig);
}
private validateInput(envConfig: EnvConfig): EnvConfig {
const envVarsSchema: Joi.ObjectSchema = Joi.object(this.getJoiObject());
const { error, value: validatedEnvConfig } = envVarsSchema.validate(envConfig);
if (error) {
throw new Error(`Config validation error: ${error.message}`);
}
return validatedEnvConfig;
}
private getJoiObject(): object {
return {
NODE_ENV: Joi.string()
.valid('development', 'production', 'test', 'provision')
.default('development'),
PORT: Joi.number().default(3000),
DATABASE_TYPE: Joi.string()
.valid('mysql')
.default('mysql'),
DATABASE_HOST: Joi.string().required(),
DATABASE_PORT: Joi.number().required(),
DATABASE_NAME: Joi.string().required(),
DATABASE_USER: Joi.string().required(),
DATABASE_PASSWORD: Joi.string().required(),
};
}
get(key: string): string {
return this.envConfig[key];
}
getPort(): number {
return parseInt(this.envConfig.PORT, 10);
}
getDBType(): string {
return this.envConfig.DATABASE_TYPE;
}
getDBHost(): string {
return this.envConfig.DATABASE_HOST;
}
getDBPort(): number {
return parseInt(this.envConfig.DATABASE_PORT, 10);
}
getDBName(): string {
return this.envConfig.DATABASE_NAME;
}
getDBUser(): string {
return this.envConfig.DATABASE_USER;
}
getDBPassword(): string {
return this.envConfig.DATABASE_PASSWORD;
}
}
Run Code Online (Sandbox Code Playgroud)
环境TYPEORM_变量在这里是互斥的吗?DATABASE_为了让 TypeORM 在 CLI 和 NestJS 应用程序的上下文中工作,我们真的需要将环境变量复制到它们的表单中吗?这似乎非常错误。让 TypeORM 在 CLI(我希望它用于开发中的迁移)和 NestJS 应用程序中同时工作而不必复制这些变量的正确方法是什么?
Rob*_*ert 39
我的配置。
// src/config/db.config.ts
import {registerAs} from "@nestjs/config";
export default registerAs('database', () => {
return {
type: "postgres",
logging: true,
host: process.env.DB_MAIN_HOST,
port: parseInt(process.env.DB_MAIN_PORT),
username: process.env.DB_MAIN_USER,
password: process.env.DB_MAIN_PASSWORD,
database: process.env.DB_MAIN_DATABASE,
autoLoadEntities: true,
// synchronize: process.env.MODE === "dev",
entities: ["src/**/*.entity.ts"],
migrations: ['src/migrations/*{.ts,.js}'],
cli: {
migrationsDir: 'src/migrations'
},
}
})
Run Code Online (Sandbox Code Playgroud)
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import {ConfigModule, ConfigService} from '@nestjs/config';
import {TypeOrmModule} from "@nestjs/typeorm";
import dbConfiguration from "./config/db.config";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [dbConfiguration],
}),
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({...configService.get('database')})
})
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
// ormconfig.ts
import {ConfigModule} from "@nestjs/config";
import dbConfiguration from "./src/config/db.config";
ConfigModule.forRoot({
isGlobal: true,
load: [dbConfiguration],
})
export default dbConfiguration()
Run Code Online (Sandbox Code Playgroud)
它需要 ts-node
//package.json
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js",
"typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
"typeorm:migration:run": "npm run typeorm -- migration:run"
Run Code Online (Sandbox Code Playgroud)
Fin*_*tic 10
此解决方案允许您对 CLI 使用和应用程序使用使用相同的参数,而不会遇到代码重复。
使用 path.join():
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { join } from 'path';
// tslint:disable-next-line: no-var-requires
require('dotenv').config();
class ConfigService {
constructor(private env: { [k: string]: string | undefined }) {}
//...etc
public getTypeOrmConfig(): TypeOrmModuleOptions {
return {
// obviously, change these if you're using a different DB
type: 'postgres',
host: this.getValue('POSTGRES_HOST'),
port: Number(this.getValue('POSTGRES_PORT')),
username: this.getValue('POSTGRES_USER'),
password: this.getValue('POSTGRES_PASSWORD'),
database: this.getValue('POSTGRES_DB'),
entities: [join(__dirname, '**', '*.entity.{ts,js}')],
migrationsTableName: 'migration',
migrations: [join(__dirname, '..', 'migrations', '*.ts')],
cli: {
migrationsDir: '../migrations',
},
synchronize: true,
ssl: this.isProduction(),
};
}
}
const configService = new ConfigService(process.env);
export default configService;
Run Code Online (Sandbox Code Playgroud)
如果不TypeOrmModule.forRoot()带参数使用,默认情况下会ormconfig.json在项目的根目录中查找文件。您也可以为它提供 TypeOrmModuleOptions 参数,我会推荐它。我建议完全按照 Riajul Islam 和 Muhammad Zeeshan 的做法去做:
@Module({
imports: [
TypeOrmModule.forRoot(configService.getTypeOrmConfig()),
// add other modules here as well
]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的脚本,它允许您生成对 CLI 操作有用的 ormconfig.json 文件。
import configService from '../src/config.service';
import fs = require('fs');
fs.writeFileSync(
'ormconfig.json',
JSON.stringify(configService.getTypeOrmConfig(), null, 2), // last parameter can be changed based on how you want the file indented
);
Run Code Online (Sandbox Code Playgroud)
您可能希望根据您自己的文件结构以及您如何命名实体来更改您的entities和migrations属性的确切连接语句。
我的项目结构是:
.env // ALL environmental variables are stored here, both for Node and for other processes such as Docker
src
| config.service.ts
| app.module.ts // calls configService.getTypeOrmConfig()
| main.ts
scripts // for CLI only operations
| seed.ts // calls configService.getTypeOrmConfig() when creating a ConnectionOptions object for the database
| write-type-orm-config.ts // calls configService.getTypeOrmConfig() to create an ormconfig.json file at the root, which I use for some NPM scripts
migrations
| DB migrations go here...
Run Code Online (Sandbox Code Playgroud)
这很可能是您需要 ormconfig.json 文件的地方。
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",
"start:dev:db:seed": "ts-node -r tsconfig-paths/register scripts/seed.ts",
"start:debug": "nest start --debug --watch",
"start:dev:autoconfig": "yarn run typeorm:migration:run && yarn run start:dev:db:seed",
"start:prod": "node dist/src/main",
"pretypeorm": "(rm ormconfig.json || :) && ts-node -r tsconfig-paths/register scripts/write-type-orm-config.ts",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
"typeorm:migration:generate": "yarn run typeorm -- migration:generate -n",
"typeorm:migration:run": "yarn run typeorm -- migration:run"
},
Run Code Online (Sandbox Code Playgroud)
请注意,您必须在生成迁移时指定迁移名称: yarn run typeorm:migration:generate ${MIGRATION_NAME}
https://medium.com/better-programming/typeorm-migrations-explained-fdb4f27cb1b3(关于使用 NestJS 配置 TypeORM 环境的好文章)
https://github.com/GauSim/nestjs-typeorm(上述 Git 存储库)
我没有发现您的代码有任何问题,可能我无法做到,我提取了同样的问题,我可以为您提供我的代码示例,希望它对您有帮助。
.env:APP_PORT=
TYPEORM_CONNECTION = <mysql | mongodb | pg>
TYPEORM_HOST =
TYPEORM_USERNAME =
TYPEORM_PASSWORD =
TYPEORM_DATABASE =
TYPEORM_PORT =
TYPEORM_SYNCHRONIZE = <true | false>
TYPEORM_LOGGING = <true | false>
TYPEORM_ENTITIES=**/*.entities.ts,src/**/*.entities.ts,src/**/*.entity.ts
TYPEORM_MIGRATIONS=database/migration/*.ts
TYPEORM_MIGRATIONS_DIR=database/migration
Run Code Online (Sandbox Code Playgroud)
config.service.tsimport {TypeOrmModuleOptions} from '@nestjs/typeorm';
// tslint:disable-next-line: no-var-requires
require('dotenv').config();
class ConfigService {
constructor(private env: {[key: string]: string | undefined}) {}
private getValue(key: string, throwOnMissing = true): string {
const value = this.env[key];
if (!value && throwOnMissing) {
throw new Error(`config error - missing env.${key}`);
}
return value;
}
public ensureValues(keys: string[]) {
keys.forEach(key => this.getValue(key, true));
return this;
}
public getTypeOrmConfig(): TypeOrmModuleOptions {
return {
type: 'mysql',
keepConnectionAlive: true,
host: process.env.TYPEORM_HOST,
port: parseInt(process.env.TYPEORM_PORT) || 3306,
database: process.env.TYPEORM_DATABASE,
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
entities: [__dirname + '/../**/*.entities{.ts,.js}']
};
}
}
const configService = new ConfigService(process.env).ensureValues([
'TYPEORM_DATABASE',
'TYPEORM_USERNAME',
'TYPEORM_PASSWORD'
]);
export {configService};
Run Code Online (Sandbox Code Playgroud)
app.module.ts@Module({
imports: [
TypeOrmModule.forRoot(configService.getTypeOrmConfig()),
]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
请告诉我这个解决方案是否有效
| 归档时间: |
|
| 查看次数: |
10438 次 |
| 最近记录: |