Add command line interface and allow rolling back migrations
This commit is contained in:
parent
91b9e51a7d
commit
499c66240b
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wms-core",
|
||||
"version": "0.6.0",
|
||||
"version": "0.6.8",
|
||||
"description": "Node web framework",
|
||||
"repository": "git@gitlab.com:ArisuOngaku/wms-core.git",
|
||||
"author": "Alice Gaudon <alice@gaudon.pro>",
|
||||
|
@ -48,6 +48,12 @@ export default abstract class Application {
|
||||
// Register migrations
|
||||
MysqlConnectionManager.registerMigrations(this.getMigrations());
|
||||
|
||||
// Process command line
|
||||
if (await this.processCommandLine()) {
|
||||
await this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Register all components and alike
|
||||
await this.init();
|
||||
|
||||
@ -118,6 +124,24 @@ export default abstract class Application {
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
protected async processCommandLine(): Promise<boolean> {
|
||||
const args = process.argv;
|
||||
for (let i = 2; i < args.length; i++) {
|
||||
switch (args[i]) {
|
||||
case '--verbose':
|
||||
Logger.verbose();
|
||||
break;
|
||||
case 'migration':
|
||||
await MysqlConnectionManager.migrationCommand(args.slice(i + 1));
|
||||
return true;
|
||||
default:
|
||||
Logger.warn('Unrecognized argument', args[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
Logger.info('Stopping application...');
|
||||
|
||||
|
@ -2,10 +2,15 @@ import config from "config";
|
||||
import {v4 as uuid} from "uuid";
|
||||
import Log from "./models/Log";
|
||||
|
||||
const LOG_LEVEL: LogLevelKeys = <LogLevelKeys>config.get<string>('log_level');
|
||||
const DB_LOG_LEVEL: LogLevelKeys = <LogLevelKeys>config.get<string>('db_log_level');
|
||||
|
||||
export default class Logger {
|
||||
private static logLevel: LogLevelKeys = <LogLevelKeys>config.get<string>('log_level');
|
||||
private static dbLogLevel: LogLevelKeys = <LogLevelKeys>config.get<string>('db_log_level');
|
||||
|
||||
public static verbose() {
|
||||
this.logLevel = <LogLevelKeys>LogLevel[LogLevel[this.logLevel] + 1] || this.logLevel;
|
||||
this.dbLogLevel = <LogLevelKeys>LogLevel[LogLevel[this.dbLogLevel] + 1] || this.dbLogLevel;
|
||||
}
|
||||
|
||||
public static silentError(error: Error, ...message: any[]): string {
|
||||
return this.log('ERROR', message, error, true) || '';
|
||||
}
|
||||
@ -32,7 +37,7 @@ export default class Logger {
|
||||
|
||||
private static log(level: LogLevelKeys, message: any[], error?: Error, silent: boolean = false): string | null {
|
||||
const levelIndex = LogLevel[level];
|
||||
if (levelIndex <= LogLevel[LOG_LEVEL]) {
|
||||
if (levelIndex <= LogLevel[this.logLevel]) {
|
||||
if (error) {
|
||||
if (levelIndex > LogLevel.ERROR) this.warn(`Wrong log level ${level} with attached error.`);
|
||||
} else {
|
||||
@ -71,7 +76,7 @@ export default class Logger {
|
||||
|
||||
let output = `[${level}] `;
|
||||
let pad = output.length;
|
||||
if (levelIndex <= LogLevel[DB_LOG_LEVEL]) output += `${log.getLogID()} - `;
|
||||
if (levelIndex <= LogLevel[this.dbLogLevel]) output += `${log.getLogID()} - `;
|
||||
output += computedMsg.replace(/\n/g, '\n' + ' '.repeat(pad));
|
||||
|
||||
switch (level) {
|
||||
@ -94,7 +99,7 @@ export default class Logger {
|
||||
break;
|
||||
}
|
||||
|
||||
if (levelIndex <= LogLevel[DB_LOG_LEVEL]) {
|
||||
if (levelIndex <= LogLevel[this.dbLogLevel]) {
|
||||
log.save().catch(err => {
|
||||
if (!silent && err.message.indexOf('ECONNREFUSED') < 0) {
|
||||
console.error({save_err: err, error});
|
||||
|
@ -45,7 +45,7 @@ export default class Mail {
|
||||
}
|
||||
|
||||
public static end() {
|
||||
this.transporter.close();
|
||||
if (this.transporter) this.transporter.close();
|
||||
}
|
||||
|
||||
public static parse(template: string, data: any, textOnly: boolean): string {
|
||||
|
@ -32,7 +32,7 @@ export default class MysqlConnectionManager {
|
||||
this.migrations.push(migration(this.migrations.length + 1));
|
||||
}
|
||||
|
||||
public static async prepare() {
|
||||
public static async prepare(runMigrations: boolean = true) {
|
||||
if (config.get('mysql.create_database_automatically') === true) {
|
||||
const dbName = config.get('mysql.database');
|
||||
Logger.info(`Creating database ${dbName}...`);
|
||||
@ -55,7 +55,7 @@ export default class MysqlConnectionManager {
|
||||
}
|
||||
this.databaseReady = true;
|
||||
|
||||
await this.handleMigrations();
|
||||
if (runMigrations) await this.handleMigrations();
|
||||
}
|
||||
|
||||
public static get pool(): Pool {
|
||||
@ -152,7 +152,7 @@ export default class MysqlConnectionManager {
|
||||
});
|
||||
}
|
||||
|
||||
private static async handleMigrations() {
|
||||
public static async getCurrentMigrationVersion(): Promise<number> {
|
||||
let currentVersion = 0;
|
||||
|
||||
try {
|
||||
@ -164,6 +164,11 @@ export default class MysqlConnectionManager {
|
||||
}
|
||||
}
|
||||
|
||||
return currentVersion;
|
||||
}
|
||||
|
||||
private static async handleMigrations() {
|
||||
const currentVersion = await this.getCurrentMigrationVersion();
|
||||
for (const migration of this.migrations) {
|
||||
if (await migration.shouldRun(currentVersion)) {
|
||||
Logger.info('Running migration ', migration.version, migration.constructor.name);
|
||||
@ -177,4 +182,37 @@ export default class MysqlConnectionManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param migrationID what migration to rollback. Use with caution. default=0 is for last registered migration.
|
||||
*/
|
||||
public static async rollbackMigration(migrationID: number = 0): Promise<void> {
|
||||
migrationID--;
|
||||
const migration = this.migrations[migrationID];
|
||||
Logger.info('Rolling back migration ', migration.version, migration.constructor.name);
|
||||
await MysqlConnectionManager.wrapTransaction<void>(async c => {
|
||||
await migration.rollback(c);
|
||||
await query('DELETE FROM migrations WHERE id=?', [migration.version]);
|
||||
});
|
||||
}
|
||||
|
||||
public static async migrationCommand(args: string[]): Promise<void> {
|
||||
try {
|
||||
Logger.info('Current migration:', await this.getCurrentMigrationVersion());
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === 'rollback') {
|
||||
let migrationID = 0;
|
||||
if (args.length > i + 1) {
|
||||
migrationID = parseInt(args[i + 1]);
|
||||
}
|
||||
await this.prepare(false);
|
||||
await this.rollbackMigration(migrationID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await MysqlConnectionManager.endPool();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user