update.js 4.95 KB
const path = require('path');
const shelljs = require('shelljs');
const chalk = require('chalk');
const _ = require('lodash');
const fs = require('fs');
const config = require('../../config/common');
const argv = require('optimist').argv

require('yoho-node-lib').global(config);

const logger = global.yoho.logger;
const {SqlHelper} = require('../../utils');
const migrations = require('../../migrations');
const migrationPath = path.join(__dirname, '../../migrations');
const migrationTablName = '__migrations';
const scriptPath = path.join(__dirname, '../../scripts');
const env_script = process.env.npm_config_script || argv.script;
const env_verbose = process.env.npm_config_verbose || argv.verbose;
const mysqlCli = new SqlHelper();
let script_file = '';
if (env_script) {
    script_file = process.env.npm_config_file || argv.file;

    if (!script_file) {
        console.error('请输入保存的文件名');
        return;
    }
}

const initMargration = () => {
    return mysqlCli.execute(`create database if not exists ${config.mysql.database};`).then(dbRes => {
        if (dbRes.warningCount === 0) {
            console.log(chalk.green(`数据库创建成功:${config.mysql.database}`));
        }
        return mysqlCli.changeDatabase(config.mysql.database).then(() => {
            return mysqlCli.execute(`create table if not exists ${migrationTablName} (
                id int(10) unsigned not null auto_increment,
                migration_name varchar(50) not null,
                migration_time timestamp not null DEFAULT CURRENT_TIMESTAMP,
                primary key (id)
            ) DEFAULT CHARSET=utf8;`).then(tbRes => {
                if (tbRes.warningCount === 0) {
                    console.log(chalk.green(`迁移记录表创建成功:${migrationTablName}`));
                }
            });
        });
    });
};
const removeComment = (scripts) => {
    const regComment1 = /\/\*(\n|.)*?\*\//g;
    const regComment2 = /#.*?(\n|$)/g;
    const regComment3 = /--.*?(\n|$)/g;

    return scripts
        .replace(regComment1, '')
        .replace(regComment2, '')
        .replace(regComment3, '');
};
const getSql = (migras) => {
    let scripts = '';
    let migrationsSqls = [];

    _.each(migras, m => {
        scripts += removeComment(fs.readFileSync(`${migrationPath}/${m}.sql`, 'utf8'));
    });
    migrationsSqls = _.filter(_.split(scripts, 'GO;'), script => _.trim(script));
    return migrationsSqls;
}
const getMigrationLogSql = (migras) => {
    return _.map(migras, m => {
        return `insert ${migrationTablName} (migration_name) values ('${m}');\r\n`;
    });
}
const script = (migras, sqls) => {
    let migrationsSqls = getSql(migras);
    let insertSqls = getMigrationLogSql(migras);
    let scripts = _.join(_.concat(migrationsSqls, insertSqls), '');

    shelljs.exec(`mkdir -p ${scriptPath}`); // 创建页面目录

    fs.writeFileSync(path.join(scriptPath, `${script_file}.sql`), scripts, {
        encoding: 'utf8'
    });

    console.log(chalk.green(`导出文件:${path.join(scriptPath, `${script_file}.sql`)}成功`))
    return Promise.resolve();
};
const sqlLog = (sql) => {
    env_verbose && console.log(chalk.gray(sql));
}
const update = (migras) => {
    let migrationsSqls = getSql(migras);

    console.log(chalk.gray(`--verbose:`))
    return mysqlCli.transaction(migrationsSqls, sql => sqlLog(sql)).then(() => {
        console.log(chalk.green(`脚本写入成功,准备写入迁移记录`))
        let insertSqls = getMigrationLogSql(migras);

        return mysqlCli.transaction(insertSqls, sql => sqlLog(sql)).then(() => {
            console.log(chalk.green(`迁移完成!`))
        });
    }, () => {
        return Promise.reject();
    });
}
const migration = (migras) => {
    if (migras.length) {
        console.log(chalk.green(`共计:${migras.length}条迁移记录!`));
        return env_script ? script(migras) : update(migras)
    }
    console.log(chalk.yellow('无更新记录'));
    return Promise.resolve();
};
const round = (times) => {
    return Math.round((times[0] * 1e9 + times[1]) / 10000) / 100;
}

let timeStart = process.hrtime();
initMargration().then(() => {
    let sqlIn = _.join(_.map(migrations, m => {
        return `'${m}'`;
    }), ',');

    mysqlCli
        .query(`select * from ${migrationTablName} where migration_name in (${sqlIn})`)
        .then(result => {
            let migras = _.filter(migrations,
                m => _.every(result,
                    r => m.indexOf(r.migration_name) < 0));

            migration(migras).then(() => {
                let timeEnd = process.hrtime(timeStart);
                console.log(chalk.yellow(`运行时间:${round(timeEnd)}ms`));
                process.exit();
            }, () => {
                console.log(chalk.red('迁移失败,脚本已回滚!'));
                let timeEnd = process.hrtime(timeStart);
                console.log(chalk.yellow(`运行时间:${round(timeEnd)}ms`));
                process.exit();
            });
        });
});