#!/usr/bin/env node 'use strict' const path = require('path') const mygreat = require('../index') const program = require('commander') const ConflictError = require('../errors/conflict') const environment = process.env.NODE_ENV || 'development' const fallback = (value, defaultValue) => value || defaultValue const configFactory = (dir) => { return Object.assign( { shutdown: () => { } }, require(path.resolve(process.cwd(), dir))(environment) ) } const errorHandler = (err) => { console.log('│') console.log('│') if (err instanceof ConflictError) { console.error('│ ┌') console.error('│ │ [ error: conflict ]') console.error('│ │ unable to proceed due possible integrity break') console.error('│ │') console.error('│ │ any of the following scenarios could couse this error:') console.error('│ │ - a synced migration file has been renamed;') console.error('│ │ - a new migration has been named wrongly - all new') console.error('├──┤ migrations should be placed as last, considering') console.error('│ │ an ascending order;') console.error('│ │ - a synced migration file has been deleted before') console.error('│ │ been migrated-down;') console.error('│ │ - migrating down should alway revert the most recent') console.error('│ │ migration execution registry, otherwise the next') console.error('│ │ execution could trigger this error;') console.error('│ └') } else { console.error('│ ┌') console.error(`├──┤ [ error: ${err.name} ]`) console.error('│ │', err.message) console.error('│ └') } console.log('│') console.log('└─ [ » exit 1 ]') process.exit(1) } const action = async (file, direction) => { console.log([' ╔═════════', (direction === 'up') ? '═══╗' : '═════╗'].join('')) console.log(['┌─║ migrate ', (direction === 'up') ? 'up ║' : 'down ║'].join('')) console.log(['│ ╚═════════', (direction === 'up') ? '═══╝' : '═════╝'].join('')) console.log('│') console.log('├─ setting up...') const config = configFactory(file) const migrate = mygreat.from(config.local, config.remote) const setup = await config.setup() const fn = migrate[direction] console.log('├─ migrating...') const result = await fn(setup) if (!result || result.content.length === 0) { console.log('│ └─ nothing to migrate') console.log('│') console.log('└─ [ » exit 0 ]') config.shutdown() return } console.log('│ └─ migrated') console.log('│') console.log('│') console.log('│ ╔══════════════════════════════════════════════════════════════╗') console.log(`└─║ migration execution id #${result.name} ║─┐`) console.log(' ╚══════════════════════════════════════════════════════════════╝ │') console.log(' ┌──────────────────────────────────────────────────┐ │') console.log('┌───────┤ the following migration files have been executed │───────┘') console.log('│ └──────────────────────────────────────────────────┘') console.log('│') result.content.forEach(file => { console.log(`├─ file "${file}" / method "${direction}"`) }) console.log('│') console.log('└─ [ » exit 0 ]') return config.shutdown() } ;(async () => { program .version(process.env.npm_package_version) .option('-f, --file ', 'path to mygreat configuration file', fallback, './.mygreat.js') program .command('up') .action(options => action(options.parent.file, 'up').catch(errorHandler)) program .command('down') .action(options => action(options.parent.file, 'down').catch(errorHandler)) program.parse(process.argv) })()