diff --git a/bin/migration/make.js b/bin/migration/make.js index b2845477..f0cc7f2d 100644 --- a/bin/migration/make.js +++ b/bin/migration/make.js @@ -2,11 +2,15 @@ import { createRequire } from 'module'; import prettier from 'prettier'; import { pathConfig } from '../../lib/helpers.js'; import { migrate, updateMigrationState, writeMigration } from '../../lib/migration.js'; +import { setLogLevel, log } from '../../lib/functions.js'; const require = createRequire(import.meta.url); const make = async (argv) => { + setLogLevel(argv.logLevel); + const configOptions = pathConfig(argv); + log(1, `configOptions:${JSON.stringify(configOptions, null, 2)}`); let migrationResult; try { diff --git a/bin/migration/sync.js b/bin/migration/sync.js index 7b20bb4d..8fa011b0 100644 --- a/bin/migration/sync.js +++ b/bin/migration/sync.js @@ -1,10 +1,14 @@ import prettier from 'prettier'; import { pathConfig } from '../../lib/helpers.js'; import { migrate, updateMigrationState } from '../../lib/migration.js'; +import { setLogLevel, log } from '../../lib/functions.js'; const sync = async (argv) => { + setLogLevel(argv.logLevel); const configOptions = pathConfig(argv); + log(1, `configOptions:${JSON.stringify(configOptions, null, 2)}`); + let migrationResult; try { migrationResult = await migrate(configOptions); @@ -20,7 +24,9 @@ const sync = async (argv) => { } // log migration actions - migration.consoles.forEach((action, index) => console.log(`[Action #${index}] ${action}`)); + migration.consoles.forEach((action, index) => + console.log(`[Action #${(index + 1).toString().padStart(2, '0')}] ${action}`), + ); if (argv.preview) { console.log('Migration result:'); diff --git a/bin/migration/undo.js b/bin/migration/undo.js index 2275f4e9..4fbd64db 100644 --- a/bin/migration/undo.js +++ b/bin/migration/undo.js @@ -4,12 +4,18 @@ import fs from 'fs'; import path from 'path'; import { pathConfig } from '../../lib/helpers.js'; -import { getFileName } from '../../lib/functions.js'; +import { getFileName, setLogLevel, log } from '../../lib/functions.js'; const require = createRequire(import.meta.url); const undo = async (argv) => { - const { migrationsDir, stateDir } = pathConfig(argv); + setLogLevel(argv.logLevel); + + const configOptions = pathConfig(argv); + + const { migrationsDir, stateDir } = configOptions; + + log(1, `configOptions:${JSON.stringify(configOptions, null, 2)}`); const curStatePath = path.join(stateDir, '_current.json'); const curStateName = getFileName(curStatePath); diff --git a/bin/sequelize-mig.js b/bin/sequelize-mig.js index c4107ff3..6e5e0813 100644 --- a/bin/sequelize-mig.js +++ b/bin/sequelize-mig.js @@ -16,24 +16,24 @@ yargs(hideBin(process.argv)) (yargsA) => yargsA .positional('name', { - describe: 'Set migration name (default: "noname")', - type: 'string', alias: 'n', + type: 'string', + describe: 'Set migration name (default: "noname")', }) .positional('preview', { - describe: 'Preview migration actions without writing migration file', - type: 'boolean', alias: 'p', + type: 'boolean', + describe: 'Preview migration actions without writing migration file', }) .positional('es6', { - describe: 'Force .cjs file extension', - type: 'boolean', alias: 'cjs', + type: 'boolean', + describe: 'Force .cjs file extension', }) .positional('comment', { - describe: 'Set migration comment', - type: 'string', alias: 'c', + type: 'string', + describe: 'Set migration comment', }) .example('sequelize-mig migration:make -n InitDb -p').argv, (argv) => make(argv), @@ -44,9 +44,9 @@ yargs(hideBin(process.argv)) (yargsA) => yargsA .positional('preview', { - describe: 'Preview sync actions without updating state', - type: 'boolean', alias: 'p', + type: 'boolean', + describe: 'Preview sync actions without updating state', }) .example('sequelize-mig migration:sync -p').argv, (argv) => sync(argv), @@ -57,65 +57,71 @@ yargs(hideBin(process.argv)) (yargsA) => yargsA .positional('force', { - describe: 'force undo even if revisions not equal', - type: 'boolean', alias: 'f', + type: 'boolean', + describe: 'force undo even if revisions not equal', }) .positional('delete-current-state', { - describe: 'delete current state (default: true)', - type: 'boolean', alias: 'del-cur-stt', + type: 'boolean', default: true, + describe: 'delete current state (default: true)', }) .positional('delete-current-migration', { - describe: 'delete current migration (default: true)', - type: 'boolean', alias: 'del-cur-mig', + type: 'boolean', default: true, + describe: 'delete current migration (default: true)', }) .positional('rename-backup-state', { - describe: 'rename backup state (default: true)', - type: 'boolean', alias: 'ren-bak-stt', + type: 'boolean', default: true, + describe: 'rename backup state (default: true)', }) .example('sequelize-mig migration:undo').argv, (argv) => undo(argv), ) .option('pwd-path', { - describe: 'Override PWD (or just navigate to specified folder in it) (default to ./)', - type: 'string', alias: 'pwdp', + type: 'string', + describe: 'Override PWD (or just navigate to specified folder in it) (default to ./)', }) .option('ignore-sequelizerc', { - describe: 'force pwd even on sequelizerc (default to false)', - type: 'boolean', alias: 'ignrc', + type: 'boolean', + describe: 'force pwd even on sequelizerc (default to false)', }) .option('sequelizerc-path', { - describe: 'The path to the .sequelizerc file (default to ./.sequelizerc)', - type: 'string', alias: 'seqrcp', + type: 'string', + describe: 'The path to the .sequelizerc file (default to ./.sequelizerc)', }) .option('migrations-path', { - describe: 'The path to the migrations folder (default to ./migrations)', - type: 'string', alias: 'migp', + type: 'string', + describe: 'The path to the migrations folder (default to ./migrations)', }) .option('models-path', { - describe: 'The path to the models folder (default to ./models)', - type: 'string', alias: 'modp', + type: 'string', + describe: 'The path to the models folder (default to ./models)', }) .option('state-path', { - describe: 'The path to the state folder where schema is saved (default to migrations-path)', - type: 'string', alias: 'statp', + type: 'string', + describe: 'The path to the state folder where schema is saved (default to migrations-path)', }) .option('index-file-path', { - describe: 'The path to the index file (default to models-path/index.js)', - type: 'string', alias: 'indxp', + type: 'string', + describe: 'The path to the index file (default to models-path/index.js)', + }) + .option('log-level', { + alias: 'll', + type: 'number', + default: 3, + describe: 'The less, The more you see, default: 3...', }) .alias('help', 'h') .alias('version', 'v') diff --git a/lib/functions.js b/lib/functions.js index a5c2aa51..820d3552 100644 --- a/lib/functions.js +++ b/lib/functions.js @@ -1,3 +1,5 @@ +let logLevel = 3; + export const getYYYYMMDDHHMMSS = (date = new Date()) => { return [ date.getUTCFullYear(), @@ -30,3 +32,11 @@ export const template = (text, params) => { export const getFileName = (path) => { return path.replace(/^.*(\\|\/|:)/, ''); }; + +export const log = (logLvl, message) => { + if (logLvl >= logLevel) console.log(message); +} + +export const setLogLevel = (logLvl) => { + logLevel = logLvl; +}; diff --git a/lib/helpers.js b/lib/helpers.js index 9d7807a7..d27f20ae 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -5,6 +5,8 @@ import { fileURLToPath } from 'url'; import Sequelize from 'sequelize'; +import {log} from './functions.js' + const { dirname: _dirname, join } = path; const dirname = _dirname(fileURLToPath(import.meta.url)); const require = createRequire(import.meta.url); @@ -206,6 +208,8 @@ export const pathConfig = (options) => { if (options.indexFilePath) indexDir = join(PWD, options.indexFilePath); if (options.statePath) stateDir = join(PWD, options.statePath); + log(1, `pathConfig options:${JSON.stringify(options, null, 2)}`); + return { modelsDir, migrationsDir, diff --git a/lib/migration.js b/lib/migration.js index 80714d8a..446d6404 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -1,12 +1,10 @@ import fs, { writeFileSync } from 'fs'; import path, { join } from 'path'; import prettier from 'prettier'; -import { getYYYYMMDDHHMMSS, template } from './functions.js'; +import { getYYYYMMDDHHMMSS, template, log } from './functions.js'; import { readAsset, sortActions } from './helpers.js'; import { parseDifference, reverseModels } from './models.js'; -const { log } = console; - export const getPartialMigration = (actions) => { const stringifyModel = (obj) => { const vals = []; @@ -120,7 +118,7 @@ export const getPartialMigration = (actions) => { default: action = null; - log('Error: action not specified'); + log(4, 'Error: action not specified'); } if (action) { @@ -151,6 +149,8 @@ export const getMigration = (upActions, downActions) => { export const migrate = async (options) => { const { modelsDir, migrationsDir, indexDir, stateDir } = options; + log(1, `migrate options:${JSON.stringify(options, null, 2)}`); + if (!fs.existsSync(modelsDir)) throw new Error("Can't find models directory. Use `sequelize init` to create it"); @@ -184,16 +184,20 @@ export const migrate = async (options) => { try { previousState = JSON.parse(fs.readFileSync(currentState.path)); } catch (e) { - console.log('_current.json syntax not valid'); + console.log('_current.json syntax is not valid, overriding it'); } } else { console.log('_current.json not found. first time running this tool'); } - const { sequelize } = (await import(`file:////${indexDir}`)).default; - const { models } = sequelize; + try { + const { sequelize } = (await import(`file:////${indexDir}`)).default; + const { models } = sequelize; - currentState.tables = reverseModels(sequelize, models); + currentState.tables = reverseModels(sequelize, models); + } catch (e) { + throw new Error(`sequelize index file is not valid probably. solve it and try again: ${e}`); + } const upActions = parseDifference(previousState.tables, currentState.tables); const downActions = parseDifference(currentState.tables, previousState.tables); diff --git a/test/helpers.test.js b/test/helpers.test.js index 0dedf43c..d4f3ce29 100644 --- a/test/helpers.test.js +++ b/test/helpers.test.js @@ -14,6 +14,7 @@ test('pathConfig', async () => { const options = { pwdPath: 'example/example', ignoreSequelizerc: true, + debug: false, }; const Config = pathConfig(options); Object.entries(Config).forEach(([key, val]) => {