draig-car
Version:
Database REST API interactive generator CLI and REPL OpenAPI3 based JS generator with interactive ORM/ODM REPL
166 lines (162 loc) • 4.89 kB
JavaScript
const fs = require('fs')
const path = require('path')
const util = require('util')
const chalk = require('chalk')
const clearModule = require('clear-module')
const u = require('../util')
const c = require('./util/container')
function resultCount(r) {
return r.reduce
? r.reduce(
(i, e) =>
!e
? { ...i }
: e.constructor
? e.constructor.name in i
? { ...i, [e.constructor.name]: i[e.constructor.name] + 1 }
: { ...i, [e.constructor.name]: 1 }
: Object.keys(e).length
? { ...i, executed: i.executed ? i.executed + 1 : 1 }
: { ...i },
{}
)
: { [r.constructor.name]: 1 }
}
module.exports = {
desc: {
help: 'Describe (show column info) a table in the Database',
runnable: true,
async action(name) {
if (!name) {
console.error('syntax: .desc <tableName>')
return u.exitOrContinue(this)
}
const p = (t, s) => (s + Array(t + 1).join(' ')).substring(0, t)
const s = [30, 15, 9, 9, 40]
const h = ['column', 'type', 'size', 'nullable', 'default']
let info = await this.context.knex(name).columnInfo()
if (Object.keys(info).length) {
console.log(s.map((e, i) => p(e, h[i])).join(' '))
console.log(s.map(e => Array(e + 1).join('-')).join(' '))
for (let c in info) {
const li = [
c,
info[c].type,
info[c].maxLength == null ? '' : info[c].maxLength,
info[c].nullable,
info[c].defaultValue == null ? '' : info[c].defaultValue
]
console.log(s.map((e, i) => p(e, li[i])).join(' '))
}
} else console.log(chalk`Table or view {green ${name}} does not exist`)
u.exitOrContinue(this)
}
},
debug: {
help: 'Toggle knex global debug mode for this session',
action(name) {
if(this.context.knex) {
let c = this.context.knex.connection().client.config
c.debug = !c.debug
console.log(chalk`Debug is now {yellow ${c.debug}}`)
} else console.log(
chalk`Knex connection not available - Is the project generated?`)
this.displayPrompt()
}
},
migrate: {
help: 'Migrate up or down the database using a file from migrations/ dir',
runnable: true,
async action(name) {
let args = util.isArray(name) ? name : name.split(' ')
if (args.length !== 2 || !['up', 'down'].includes(args[0])) {
console.error('syntax: .migrate <up|down> <filename>')
return u.exitOrContinue(this)
}
let project = this.context.argv.projectDir
let fname = fs.existsSync(args[1])
? path.resolve('.', args[1])
: path.resolve('.', project, 'migrations', args[1])
try {
clearModule(fname)
let r = await require(fname)[args[0]](this.context.knex)
console.log(
chalk`Migration {green ${args[0]}} with {green ${args[1]}} succeded:`,
resultCount(r)
)
} catch (e) {
console.error(chalk`Migration file {yellow ${args[1]}} failed:`, e)
}
u.exitOrContinue(this)
}
},
seed: {
help: 'Seed the database using a file from seeds/ dir',
runnable: true,
async action(name) {
let args = util.isArray(name) ? name : name.split(' ')
if (args.length !== 1 || args[0] === '') {
console.error('syntax: .seed <filename>')
return u.exitOrContinue(this)
}
let project = this.context.argv.projectDir
let fname = fs.existsSync(args[0])
? path.resolve('.', args[0])
: path.resolve('.', project, 'seeds', args[0])
try {
clearModule(fname)
let r = await require(fname).seed(this.context.knex)
console.log(chalk`Seeding with {green ${args[0]}}:`, r)
} catch(e) {
console.error(chalk`Unable to feed the DB with file {yellow ${args[0]}}`, e)
}
u.exitOrContinue(this)
}
},
dbstop: {
help: 'Stop DB container for current configuration',
runnable: true,
async action(name) {
await c.contAction(this.context, 'exited', 'Stopping')
u.exitOrContinue(this)
}
},
dbstart: {
help: 'Start DB container for current configuration',
runnable: true,
async action(name) {
await c.contAction(this.context, 'running', 'Starting')
u.exitOrContinue(this)
}
},
dbreset: {
help: '(Re)create DB container and the project database/user/schema',
runnable: true,
async action(name) {
if (this.context.knex) this.context.knex.destroy()
const client = this.context.argv.dbclient
try {
await c.pullImage(client)
const mycont = await c.runContainer(this.context)
await c.execInContainer(mycont, this.context)
u.exitOrContinue(this)
} catch (e) {
console.error(e)
u.exitOrContinue(this)
}
}
},
genseed: {
help: 'Generate the seed-database.js file from current DB schema',
runnable: true,
async action(name) {
const ctx = this.context
const projPath = path.resolve(ctx.argv.projectDir)
const cfg = u.loadConfig() // Reload config
ctx.argv.seedGen = cfg.seedGen
await u.genSeed(this.context.knex, projPath, ctx.argv.seedGen,
ctx.api.components.schemas)
u.exitOrContinue(this)
}
}
}