nestjs + typeorm0.3 版本数据库迁移
typeorm文档地址
开始前准备
$ npm install @nestjs/cli typeorm ts-node -g
创建迁移文件
nestjs中用的是@nestjs/typeorm
的typeormmodule.forroot()
,所以这里我们额外准备一个data-source.ts
文件
/** data-source.ts */
import { datasource } from 'typeorm';
const appdatasource = new datasource({
type: 'mysql',
/** 需要迁移的数据库主机地址,一般是线上的 */
host: '',
port: 3306,
username: '',
password: '',
database: '',
/** 根据自己的项目结构来 */
entities: ['./src/modules/**/entities/*.entity.{j,t}s'],
migrations: [`./src/migration/*.{j,t}s`],
synchronize: false,
});
export default appdatasource;
注意:在写*.entity.ts
文件时,注意模块的引入路径,需要改成相对路径,否则在执行迁移指令时会报错提醒找不到模块。
/** bad */
import config from 'src/constants/config';
/** good */
import config from '../../constants/config';
生成迁移文件
$ typeorm-ts-node-esm migration:generate ./src/migration/[迁移文件名随意填写] -d ./src/data-source.ts
创建迁移文件
$ typeorm-ts-node-esm migration:create ./src/migration/[迁移文件名随意填写]
执行迁移
$ typeorm-ts-node-esm migration:run -d ./src/data-source.ts
回滚
$ typeorm-ts-node-esm migration:revert -d ./src/data-source.ts
迁移环境区分
改造方案
在src/migration
文件夹下创建新的文件夹用于区分生成的迁移文件环境,我这边创建了prod
跟staging
两文件夹
安装cross-env控制环境信息
$ npm install cross-env -d
引入inquirer
实现一个交互式脚本丰富我们的迁移体验
$ npm install inquirer@8 chalk@4 -d
创建scripts/migration.ts
import { prompt } from 'inquirer';
import * as chalk from 'chalk';
import { exec } from 'child_process';
enum env_type_enum {
prod = 'prod',
staging = 'staging',
}
enum operation_type_enum {
generate = 'generate',
create = 'create',
run = 'run',
revert = 'revert',
}
async function run() {
const { env } = await prompt<{ env: env_type_enum }>({
type: 'list',
name: 'env',
message: '请选择迁移环境',
choices: [
{
name: '线上环境',
value: env_type_enum.prod,
},
{
name: '测试环境',
value: env_type_enum.staging,
},
],
});
const { type } = await prompt<{ type: operation_type_enum }>({
type: 'list',
name: 'type',
message: '请选择操作类型',
choices: [
{
name: '生成迁移文件',
value: operation_type_enum.generate,
},
{
name: '创建迁移文件',
value: operation_type_enum.create,
},
{
name: '执行迁移',
value: operation_type_enum.run,
},
{
name: '回滚',
value: operation_type_enum.revert,
},
],
});
const envcmd = `./node_modules/.bin/cross-env node_env=${env}`;
let migrationcmd = `typeorm-ts-node-esm migration:${type} `;
if (type === operation_type_enum.generate) {
migrationcmd += `./src/migration/${env}/update -d ./src/data-source.ts`;
} else if (type === operation_type_enum.create) {
migrationcmd += `./src/migration/${env}/create`;
} else {
migrationcmd += `-d ./src/data-source.ts`;
}
exec(`${envcmd} ${migrationcmd}`, (err, stdout, stderr) => {
if (err) {
console.log(chalk.red(err.message));
process.exit(1);
}
if (stderr) {
console.log(chalk.yellow(stderr));
process.exit(0);
}
console.log(chalk.green(stdout));
});
}
console.log(chalk.cyan('开始执行迁移指令\n'));
run();
改写一下data-source.ts
/** data-source.ts */
import { datasource } from 'typeorm';
const isprod = process.env.node_env === 'prod';
const database = isprod ? '正式数据库' : '测试数据库';
const migrations = [`./src/migration/${process.env.node_env}/*.{j,t}s`];
const appdatasource = new datasource({
type: 'mysql',
/** 需要迁移的数据库主机地址,一般是线上的 */
host: '',
port: 3306,
username: '',
password: '',
database,
/** 根据自己的项目结构来 */
entities: ['./src/modules/**/entities/*.entity.{j,t}s'],
migrations,
synchronize: false,
});
export default appdatasource;
package.json
{
"scripts": {
"migration": "ts-node ./scripts/migration.ts"
}
}
运行
$ npm run migration
✅创建迁移文件
✅执行迁移
✅执行回滚
优化思考
- 脚本一次性创建并同步迁移
- 通过
.env
文件控制环境变量
发表评论