bajo 0.3.10 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -26
- package/bajoI18N/resource/id.json +31 -0
- package/boot/class/app.js +69 -0
- package/boot/class/bajo-core/helper/attach-method.js +30 -0
- package/boot/{boot-order.js → class/bajo-core/helper/boot-order.js} +10 -10
- package/boot/class/bajo-core/helper/boot-plugins.js +19 -0
- package/boot/class/bajo-core/helper/build-config.js +61 -0
- package/boot/class/bajo-core/helper/build-plugins.js +26 -0
- package/boot/class/bajo-core/helper/collect-config-handlers.js +21 -0
- package/boot/{exit-handler.js → class/bajo-core/helper/exit-handler.js} +10 -16
- package/boot/class/bajo-core/helper/run-as-applet.js +26 -0
- package/boot/class/bajo-core/method/arrange-array.js +18 -0
- package/boot/class/bajo-core/method/break-ns-path-from-file.js +24 -0
- package/boot/class/bajo-core/method/break-ns-path.js +29 -0
- package/boot/class/bajo-core/method/build-collections.js +46 -0
- package/boot/class/bajo-core/method/call-handler.js +29 -0
- package/boot/{helper → class/bajo-core/method}/defaults-deep.js +1 -1
- package/boot/class/bajo-core/method/each-plugins.js +55 -0
- package/boot/class/bajo-core/method/envs.js +7 -0
- package/boot/{helper → class/bajo-core/method}/generate-id.js +4 -0
- package/boot/{helper → class/bajo-core/method}/get-global-module-dir.js +5 -6
- package/boot/class/bajo-core/method/get-method.js +10 -0
- package/boot/{helper → class/bajo-core/method}/get-module-dir.js +3 -4
- package/boot/{helper → class/bajo-core/method}/get-plugin-data-dir.js +2 -3
- package/boot/class/bajo-core/method/get-plugin-file.js +18 -0
- package/boot/class/bajo-core/method/get-plugin.js +23 -0
- package/boot/{helper → class/bajo-core/method}/import-module.js +4 -10
- package/boot/{helper → class/bajo-core/method}/import-pkg.js +9 -3
- package/boot/class/bajo-core/method/includes.js +13 -0
- package/boot/class/bajo-core/method/is-class.js +7 -0
- package/boot/{helper → class/bajo-core/method}/is-log-in-range.js +1 -1
- package/boot/{helper → class/bajo-core/method}/is-valid-app.js +2 -2
- package/boot/class/bajo-core/method/join.js +15 -0
- package/boot/class/bajo-core/method/log-levels.js +9 -0
- package/boot/class/bajo-core/method/num-unit.js +9 -0
- package/boot/{helper → class/bajo-core/method}/parse-object.js +24 -8
- package/boot/class/bajo-core/method/read-config.js +48 -0
- package/boot/{helper → class/bajo-core/method}/read-json.js +2 -2
- package/boot/class/bajo-core/method/run-hook.js +26 -0
- package/boot/{helper → class/bajo-core/method}/save-as-download.js +2 -2
- package/boot/class/bajo-core/method/slice-string.js +13 -0
- package/boot/class/bajo-core/method/titleize.js +23 -0
- package/boot/class/bajo-core.js +30 -0
- package/boot/class/bajo-plugin/helper/attach-method.js +14 -0
- package/boot/class/bajo-plugin/helper/build-config.js +10 -0
- package/boot/class/bajo-plugin/helper/check-clash.js +16 -0
- package/boot/class/bajo-plugin/helper/check-dependency.js +37 -0
- package/boot/class/bajo-plugin/helper/collect-exit-handlers.js +14 -0
- package/boot/class/bajo-plugin/helper/collect-hooks.js +29 -0
- package/boot/class/bajo-plugin/helper/run.js +20 -0
- package/boot/class/bajo-plugin.js +78 -0
- package/boot/class/error.js +59 -0
- package/boot/class/log.js +67 -0
- package/boot/class/plugin.js +51 -0
- package/boot/class/print.js +103 -0
- package/boot/index.js +4 -51
- package/boot/lib/create-method.js +30 -0
- package/boot/{helper → lib}/current-loc.js +1 -1
- package/boot/lib/get-global-module-path.js +189 -0
- package/boot/lib/omitted-plugin-keys.js +1 -1
- package/boot/lib/parse-args-argv.js +8 -11
- package/boot/lib/parse-env.js +7 -6
- package/boot/lib/read-all-configs.js +36 -0
- package/boot/lib/translate.js +18 -0
- package/docs/ecosystem.md +55 -0
- package/docs/hook.md +11 -0
- package/package.json +54 -56
- package/test/{helper-isSet.js → method/isSet.js} +6 -4
- package/waibuStatic/virtual.json +7 -0
- package/boot/attach-helper.js +0 -40
- package/boot/build-config.js +0 -99
- package/boot/create-scope.js +0 -36
- package/boot/helper/break-ns-path.js +0 -20
- package/boot/helper/build-collections.js +0 -43
- package/boot/helper/build-name.js +0 -17
- package/boot/helper/call-helper-or-handler.js +0 -15
- package/boot/helper/dump.js +0 -14
- package/boot/helper/each-plugins.js +0 -106
- package/boot/helper/envs.js +0 -14
- package/boot/helper/error.js +0 -77
- package/boot/helper/fatal.js +0 -13
- package/boot/helper/get-config.js +0 -19
- package/boot/helper/get-helper.js +0 -12
- package/boot/helper/get-item-by-name.js +0 -26
- package/boot/helper/get-plugin-file.js +0 -16
- package/boot/helper/get-plugin-name.js +0 -39
- package/boot/helper/get-plugin.js +0 -14
- package/boot/helper/join.js +0 -11
- package/boot/helper/log-levels.js +0 -19
- package/boot/helper/read-config.js +0 -48
- package/boot/helper/resolve-tpl-path.js +0 -15
- package/boot/helper/run-hook.js +0 -49
- package/boot/helper/spinner.js +0 -9
- package/boot/helper/start-plugin.js +0 -7
- package/boot/helper/titleize.js +0 -14
- package/boot/lib/build-helper.js +0 -60
- package/boot/lib/logger.js +0 -76
- package/boot/lib/print.js +0 -138
- package/boot/plugins/attach-helper.js +0 -20
- package/boot/plugins/build-config.js +0 -68
- package/boot/plugins/check-clash.js +0 -18
- package/boot/plugins/check-dependency.js +0 -37
- package/boot/plugins/collect-config-handlers.js +0 -22
- package/boot/plugins/collect-exit-handlers.js +0 -18
- package/boot/plugins/collect-hooks.js +0 -34
- package/boot/plugins/extend-config.js +0 -21
- package/boot/plugins/index.js +0 -27
- package/boot/plugins/run.js +0 -26
- package/boot/run-tool.js +0 -41
- package/docs/boot_build-config.js.html +0 -75
- package/docs/boot_create-scope.js.html +0 -25
- package/docs/boot_index.js.html +0 -43
- package/docs/data/search.json +0 -1
- package/docs/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/helper_emit.js.html +0 -18
- package/docs/helper_envs.js.html +0 -16
- package/docs/helper_error.js.html +0 -25
- package/docs/helper_get-bajo.js.html +0 -42
- package/docs/helper_index.js.html +0 -39
- package/docs/helper_log-levels.js.html +0 -20
- package/docs/helper_set-hook.js.html +0 -38
- package/docs/helper_walk-bajos.js.html +0 -51
- package/docs/index.html +0 -16
- package/docs/module-boot.html +0 -3
- package/docs/module-boot_buildConfig.html +0 -3
- package/docs/module-boot_createScope.html +0 -3
- package/docs/module-helper.html +0 -7
- package/docs/module-helper_setHook.html +0 -4
- package/docs/module-helper_walkBajos.html +0 -6
- package/docs/scripts/core.js +0 -655
- package/docs/scripts/core.min.js +0 -23
- package/docs/scripts/resize.js +0 -90
- package/docs/scripts/search.js +0 -265
- package/docs/scripts/search.min.js +0 -6
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
- package/docs/scripts/third-party/fuse.js +0 -9
- package/docs/scripts/third-party/hljs-line-num-original.js +0 -369
- package/docs/scripts/third-party/hljs-line-num.js +0 -1
- package/docs/scripts/third-party/hljs-original.js +0 -5171
- package/docs/scripts/third-party/hljs.js +0 -1
- package/docs/scripts/third-party/popper.js +0 -5
- package/docs/scripts/third-party/tippy.js +0 -1
- package/docs/scripts/third-party/tocbot.js +0 -672
- package/docs/scripts/third-party/tocbot.min.js +0 -1
- package/docs/styles/clean-jsdoc-theme-base.css +0 -975
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -407
- package/docs/styles/clean-jsdoc-theme-light.css +0 -388
- package/docs/styles/clean-jsdoc-theme.min.css +0 -1
- package/test/helper-error.js +0 -25
- package/test/helper-pathResolve.js +0 -28
- /package/boot/{helper → class/bajo-core/method}/get-key-by-value.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/is-empty-dir.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/is-set.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/is-valid-plugin.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/paginate.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/pascal-case.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/pick.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/resolve-path.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/round.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/sec-to-hms.js +0 -0
- /package/boot/{helper → class/bajo-core/method}/white-space.js +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Plugin from './plugin.js'
|
|
2
|
+
import dayjs from '../lib/dayjs.js'
|
|
3
|
+
import importModule from './bajo-core/method/import-module.js'
|
|
4
|
+
import readJson from './bajo-core/method/read-json.js'
|
|
5
|
+
|
|
6
|
+
import { isFunction } from 'lodash-es'
|
|
7
|
+
|
|
8
|
+
async function defConfigHandler (file, opts) {
|
|
9
|
+
let mod = await importModule(file)
|
|
10
|
+
if (isFunction(mod)) mod = await mod.call(this, opts)
|
|
11
|
+
return mod
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class BajoCore extends Plugin {
|
|
15
|
+
constructor (app) {
|
|
16
|
+
super('bajo', app)
|
|
17
|
+
this.runAt = new Date()
|
|
18
|
+
this.mainNs = 'main'
|
|
19
|
+
this.lib.dayjs = dayjs
|
|
20
|
+
this.applets = []
|
|
21
|
+
this.pluginPkgs = []
|
|
22
|
+
this.pluginNames = []
|
|
23
|
+
this.configHandlers = [
|
|
24
|
+
{ ext: '.js', readHandler: defConfigHandler },
|
|
25
|
+
{ ext: '.json', readHandler: readJson }
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default BajoCore
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import createMethod from '../../../lib/create-method.js'
|
|
2
|
+
|
|
3
|
+
async function attachMethod () {
|
|
4
|
+
const { eachPlugins } = this.bajo
|
|
5
|
+
const me = this
|
|
6
|
+
me.bajo.log.debug('Attach methods')
|
|
7
|
+
await eachPlugins(async function ({ ns, pkgName }) {
|
|
8
|
+
const dir = ns === me.bajo.mainNs ? (`${me.bajo.dir.base}/${me.bajo.mainNs}`) : me.bajo.getModuleDir(pkgName)
|
|
9
|
+
const num = await createMethod.call(me[ns], `${dir}/bajo/method`, pkgName)
|
|
10
|
+
me.bajo.log.trace('- %s (%d)', ns, num)
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default attachMethod
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { find } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
async function checkAlias () {
|
|
4
|
+
const { eachPlugins } = this.bajo
|
|
5
|
+
this.bajo.log.debug('Checking alias & name clashes')
|
|
6
|
+
const refs = []
|
|
7
|
+
await eachPlugins(async function ({ ns, pkgName, alias }) {
|
|
8
|
+
let item = find(refs, { ns })
|
|
9
|
+
if (item) throw this.error('Plugin name clash: \'%s (%s)\' with \'%s (%s)\'', ns, pkgName, item.ns, item.pkgName, { code: 'BAJO_NAME_CLASH' })
|
|
10
|
+
item = find(refs, { alias })
|
|
11
|
+
if (item) throw this.error('Plugin alias clash: \'%s (%s)\' with \'%s (%s)\'', alias, pkgName, item.alias, item.pkgName, { code: 'BAJO_ALIAS_CLASH' })
|
|
12
|
+
refs.push({ ns, alias, pkgName })
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default checkAlias
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { reduce, map, trim, keys, intersection, each, camelCase, get } from 'lodash-es'
|
|
2
|
+
import semver from 'semver'
|
|
3
|
+
|
|
4
|
+
async function runner ({ ns, pkgName }) {
|
|
5
|
+
const { join } = this.app.bajo
|
|
6
|
+
this.app.bajo.log.trace('- %s', ns)
|
|
7
|
+
const odep = reduce(this.dependencies, (o, k) => {
|
|
8
|
+
const item = map(k.split('@'), m => trim(m))
|
|
9
|
+
if (k[0] === '@') o['@' + item[1]] = item[2]
|
|
10
|
+
else o[item[0]] = item[1]
|
|
11
|
+
return o
|
|
12
|
+
}, {})
|
|
13
|
+
const deps = keys(odep)
|
|
14
|
+
if (deps.length > 0) {
|
|
15
|
+
if (intersection(this.app.bajo.pluginPkgs, deps).length !== deps.length) {
|
|
16
|
+
throw this.error('Dependency for \'%s\' unfulfilled: %s', pkgName, join(deps), { code: 'BAJO_DEPENDENCY' })
|
|
17
|
+
}
|
|
18
|
+
each(deps, d => {
|
|
19
|
+
if (!odep[d]) return
|
|
20
|
+
const ver = get(this.app[camelCase(d)], 'config.pkg.version')
|
|
21
|
+
if (!ver) return
|
|
22
|
+
if (!semver.satisfies(ver, odep[d])) {
|
|
23
|
+
throw this.error('Semver check \'%s\' against \'%s\' failed', pkgName, `${d}@${odep[d]}`, { code: 'BAJO_DEPENDENCY_SEMVER' })
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function checkDependency () {
|
|
30
|
+
const { eachPlugins } = this.bajo
|
|
31
|
+
this.bajo.log.debug('Checking dependencies')
|
|
32
|
+
await eachPlugins(async function ({ ns, pkgName, config }) {
|
|
33
|
+
await runner.call(this, { ns, pkgName, config })
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default checkDependency
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
async function collectExitHandlers () {
|
|
2
|
+
const { importModule, eachPlugins, print, join } = this.bajo
|
|
3
|
+
if (!this.bajo.config.exitHandler) return
|
|
4
|
+
const nss = []
|
|
5
|
+
await eachPlugins(async function ({ ns, dir }) {
|
|
6
|
+
const mod = await importModule(`${dir}/bajo/exit.js`)
|
|
7
|
+
if (!mod) return undefined
|
|
8
|
+
this.app[ns].exitHandler = mod
|
|
9
|
+
nss.push(ns)
|
|
10
|
+
})
|
|
11
|
+
this.bajo.log.trace('Exit handlers: %s', nss.length === 0 ? print.write('none') : join(nss))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default collectExitHandlers
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { merge, forOwn, groupBy } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
async function collectHooks () {
|
|
4
|
+
const { eachPlugins, runHook, isLogInRange, importModule, breakNsPathFromFile } = this.bajo
|
|
5
|
+
const me = this
|
|
6
|
+
me.bajo.hooks = this.bajo.hooks ?? []
|
|
7
|
+
me.bajo.log.debug('Collect hooks')
|
|
8
|
+
// collects
|
|
9
|
+
await eachPlugins(async function ({ ns, dir, file }) {
|
|
10
|
+
const { fullNs, path } = breakNsPathFromFile({ file, dir, baseNs: ns, suffix: '/hook/' })
|
|
11
|
+
const mod = await importModule(file, { asHandler: true })
|
|
12
|
+
if (!mod) return undefined
|
|
13
|
+
merge(mod, { ns: fullNs, path, src: ns })
|
|
14
|
+
me.bajo.hooks.push(mod)
|
|
15
|
+
}, { glob: 'hook/**/*.js', prefix: me.bajo.name })
|
|
16
|
+
// for log trace purpose only
|
|
17
|
+
if (!isLogInRange('trace')) return
|
|
18
|
+
const items = groupBy(me.bajo.hooks, 'ns')
|
|
19
|
+
forOwn(items, (v, k) => {
|
|
20
|
+
const hooks = groupBy(v, 'path')
|
|
21
|
+
forOwn(hooks, (v1, k1) => {
|
|
22
|
+
me.bajo.log.trace('- %s:%s (%d)', k, k1, v1.length)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
// run handler
|
|
26
|
+
await runHook('bajo:afterCollectHooks')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default collectHooks
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { camelCase, map } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
async function run () {
|
|
4
|
+
const me = this
|
|
5
|
+
const { runHook, eachPlugins, join } = me.bajo
|
|
6
|
+
const methods = ['init']
|
|
7
|
+
if (!me.bajo.applet) methods.push('start')
|
|
8
|
+
for (const method of methods) {
|
|
9
|
+
await runHook(`bajo:${camelCase(`before ${method} all plugins`)}`)
|
|
10
|
+
await eachPlugins(async function ({ ns }) {
|
|
11
|
+
await runHook(`${ns}:${camelCase(`before ${method}`)}`)
|
|
12
|
+
await me[ns][method]()
|
|
13
|
+
await runHook(`${ns}:${camelCase(`after ${method}`)}`)
|
|
14
|
+
})
|
|
15
|
+
await runHook(`bajo:${camelCase(`after ${method} all plugins`)}`)
|
|
16
|
+
}
|
|
17
|
+
me.bajo.log.debug('Loaded plugins: %s', join(map(me.bajo.pluginPkgs, b => camelCase(b))))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default run
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Plugin from './plugin.js'
|
|
2
|
+
import { pick, isString, omit, camelCase } from 'lodash-es'
|
|
3
|
+
import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
|
|
4
|
+
import readAllConfigs from '../lib/read-all-configs.js'
|
|
5
|
+
import titleize from './bajo-core/method/titleize.js'
|
|
6
|
+
import fs from 'fs-extra'
|
|
7
|
+
|
|
8
|
+
class BajoPlugin extends Plugin {
|
|
9
|
+
constructor (pkgName, app) {
|
|
10
|
+
super(pkgName, app)
|
|
11
|
+
this.state = {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async loadConfig () {
|
|
15
|
+
const { log, getModuleDir, readJson, defaultsDeep } = this.app.bajo
|
|
16
|
+
log.trace('- %s', this.name)
|
|
17
|
+
const dir = this.name === this.app.bajo.mainNs ? (`${this.app.bajo.dir.base}/${this.app.bajo.mainNs}`) : getModuleDir(this.pkgName)
|
|
18
|
+
let cfg = await readAllConfigs.call(this.app, `${dir}/bajo/config`)
|
|
19
|
+
this.alias = this.pkgName.slice(0, 5) === 'bajo-' ? this.pkgName.slice(5).toLowerCase() : this.name.toLowerCase()
|
|
20
|
+
const aliasFile = `${dir}/bajo/.alias`
|
|
21
|
+
if (fs.existsSync(aliasFile)) this.alias = fs.readFileSync(aliasFile, 'utf8')
|
|
22
|
+
this.alias = camelCase(this.alias)
|
|
23
|
+
|
|
24
|
+
this.dir = {
|
|
25
|
+
pkg: dir,
|
|
26
|
+
data: `${this.app.bajo.dir.data}/plugins/${this.name}`
|
|
27
|
+
}
|
|
28
|
+
const file = `${dir + (this.name === this.app.bajo.mainNs ? '/..' : '')}/package.json`
|
|
29
|
+
const pkgJson = await readJson(file)
|
|
30
|
+
this.pkg = pick(pkgJson,
|
|
31
|
+
['name', 'version', 'description', 'author', 'license', 'homepage'])
|
|
32
|
+
if (this.name === this.app.bajo.mainNs) {
|
|
33
|
+
this.alias = this.app.bajo.mainNs
|
|
34
|
+
this.title = 'Main'
|
|
35
|
+
}
|
|
36
|
+
// merge with config from datadir
|
|
37
|
+
try {
|
|
38
|
+
const altCfg = await readAllConfigs.call(this.app, `${this.app.bajo.dir.data}/config/${this.name}`)
|
|
39
|
+
cfg = defaultsDeep({}, omit(altCfg, omittedPluginKeys), cfg)
|
|
40
|
+
} catch (err) {}
|
|
41
|
+
const envArgv = defaultsDeep({}, omit(this.app.env[this.name] ?? {}, omittedPluginKeys) ?? {}, omit(this.app.argv[this.name] ?? {}, omittedPluginKeys) ?? {})
|
|
42
|
+
cfg = defaultsDeep({}, envArgv ?? {}, cfg ?? {})
|
|
43
|
+
this.title = this.title ?? cfg.title ?? titleize(this.alias)
|
|
44
|
+
this.dependencies = cfg.dependencies ?? []
|
|
45
|
+
if (isString(this.dependencies)) this.dependencies = [this.dependencies]
|
|
46
|
+
this.config = omit(cfg, ['title', 'dependencies'])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async _onoff (item, text, ...args) {
|
|
50
|
+
this.state[item] = false
|
|
51
|
+
const { runHook, importModule } = this.app.bajo
|
|
52
|
+
const { camelCase } = this.app.bajo.lib._
|
|
53
|
+
const mod = await importModule(`${this.dir.pkg}/bajo/${item}.js`)
|
|
54
|
+
if (mod) {
|
|
55
|
+
this.log.trace(text)
|
|
56
|
+
await runHook(`${this.name}:${camelCase(`before ${item}`)}`)
|
|
57
|
+
await mod.call(this, ...args)
|
|
58
|
+
await runHook(`${this.name}:${camelCase(`after ${item}`)}`)
|
|
59
|
+
}
|
|
60
|
+
this.state[item] = true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async init () {
|
|
64
|
+
await this._onoff('init', 'Init plugin...')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async start (...args) {
|
|
68
|
+
const { freeze } = this.app.bajo
|
|
69
|
+
freeze(this.config)
|
|
70
|
+
await this._onoff('start', 'Start plugin...', ...args)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async stop () {
|
|
74
|
+
await this._onoff('stop', 'Stop plugin...')
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default BajoPlugin
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { isPlainObject, each, isArray, get, isEmpty, merge } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
Error.stackTraceLimit = 15
|
|
4
|
+
|
|
5
|
+
class BajoError {
|
|
6
|
+
constructor (plugin, msg, ...args) {
|
|
7
|
+
this.plugin = plugin
|
|
8
|
+
this.payload = args.length > 0 && isPlainObject(args[args.length - 1]) ? args[args.length - 1] : {}
|
|
9
|
+
this.orgMessage = msg
|
|
10
|
+
this.message = this.plugin.print.write(msg, ...args)
|
|
11
|
+
this.write()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
write (fatal) {
|
|
15
|
+
let err
|
|
16
|
+
if (this.payload.class) err = this.payload.class(this.message)
|
|
17
|
+
else err = Error(this.message)
|
|
18
|
+
delete this.payload.class
|
|
19
|
+
const stacks = err.stack.split('\n')
|
|
20
|
+
stacks.splice(1, 1)
|
|
21
|
+
stacks.splice(1, 1)
|
|
22
|
+
err.stack = stacks.join('\n')
|
|
23
|
+
const values = {}
|
|
24
|
+
for (const key in this.payload) {
|
|
25
|
+
const value = this.payload[key]
|
|
26
|
+
if (key === 'details' && isArray(value)) {
|
|
27
|
+
const result = this.formatErrorDetails(value)
|
|
28
|
+
if (result) merge(values, result)
|
|
29
|
+
}
|
|
30
|
+
err[key] = value
|
|
31
|
+
}
|
|
32
|
+
if (!isEmpty(values)) err.values = values
|
|
33
|
+
return err
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
formatErrorDetails (value) {
|
|
37
|
+
const { isString } = this.plugin.app.bajo.lib._
|
|
38
|
+
const result = {}
|
|
39
|
+
const me = this
|
|
40
|
+
each(value, (v, i) => {
|
|
41
|
+
const print = me.plugin.print
|
|
42
|
+
if (isString(v)) v = { error: v }
|
|
43
|
+
if (!v.context) return undefined
|
|
44
|
+
v.context.message = v.message
|
|
45
|
+
if (v.type === 'any.only') v.context.ref = print.write(`field.${get(v, 'context.valids.0.key')}`)
|
|
46
|
+
const field = get(v, 'context.key')
|
|
47
|
+
const val = get(v, 'context.value')
|
|
48
|
+
value[i] = {
|
|
49
|
+
field,
|
|
50
|
+
error: print.write(`validation.${v.type}`, v.context),
|
|
51
|
+
value: val,
|
|
52
|
+
ext: { type: v.type, context: v.context }
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
return result
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default BajoError
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import { isEmpty, without, merge, upperFirst } from 'lodash-es'
|
|
3
|
+
import levels from './bajo-core/method/log-levels.js'
|
|
4
|
+
import isLogInRange from './bajo-core/method/is-log-in-range.js'
|
|
5
|
+
import translate from '../lib/translate.js'
|
|
6
|
+
import dayjs from 'dayjs'
|
|
7
|
+
|
|
8
|
+
class Log {
|
|
9
|
+
constructor (plugin) {
|
|
10
|
+
this.plugin = plugin
|
|
11
|
+
this.format = 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
init () {
|
|
15
|
+
this.bajoLog = this.plugin.app.bajo.config.log.logger ?? 'bajoLogger'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
write (text, ...args) {
|
|
19
|
+
return translate.call(this.plugin, null, text, ...args)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
isExtLogger () {
|
|
23
|
+
return this.plugin.app[this.bajoLog] && this.plugin.app[this.bajoLog].logger
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
child () {
|
|
27
|
+
if (this.isExtLogger()) return this.plugin.app[this.bajoLog].logger.child()
|
|
28
|
+
return this.plugin.app
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
formatMsg (level, ...params) {
|
|
32
|
+
if (this.plugin.app.bajo.config.log.level === 'silent') return
|
|
33
|
+
if (!isLogInRange.call(this.plugin.app.bajo, level)) return
|
|
34
|
+
let [data, msg, ...args] = params
|
|
35
|
+
if (typeof data === 'string') {
|
|
36
|
+
args.unshift(msg)
|
|
37
|
+
msg = data
|
|
38
|
+
data = null
|
|
39
|
+
}
|
|
40
|
+
args = without(args, undefined)
|
|
41
|
+
msg = this.write(`[%s] ${msg}`, this.plugin.name, ...args)
|
|
42
|
+
if (this.plugin.app[this.bajoLog] && this.plugin.app[this.bajoLog].logger) {
|
|
43
|
+
this.plugin.app[this.bajoLog].logger[level](data, msg, ...args)
|
|
44
|
+
} else {
|
|
45
|
+
let text
|
|
46
|
+
const dt = new Date()
|
|
47
|
+
if (this.plugin.app.bajo.config.env === 'prod') {
|
|
48
|
+
const json = { level: levels[level], time: dt.valueOf(), pid: process.pid, hostname: os.hostname() }
|
|
49
|
+
if (!isEmpty(data)) merge(json, data)
|
|
50
|
+
merge(json, { msg })
|
|
51
|
+
text = JSON.stringify(json)
|
|
52
|
+
} else {
|
|
53
|
+
text = `[${dayjs(dt).utc(true).format(this.format)}] ${upperFirst(level)}: ${msg}`
|
|
54
|
+
if (!isEmpty(data)) text += '\n' + JSON.stringify(data)
|
|
55
|
+
}
|
|
56
|
+
console.log(text)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Object.keys(levels).forEach(level => {
|
|
62
|
+
Log.prototype[level] = function (...params) {
|
|
63
|
+
this.formatMsg(level, ...params)
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export default Log
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { get, isEmpty, cloneDeep, omit, isPlainObject, camelCase } from 'lodash-es'
|
|
2
|
+
import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
|
|
3
|
+
import Log from './log.js'
|
|
4
|
+
import Print from './print.js'
|
|
5
|
+
import BajoError from './error.js'
|
|
6
|
+
|
|
7
|
+
class Plugin {
|
|
8
|
+
constructor (pkgName, app) {
|
|
9
|
+
this.pkgName = pkgName
|
|
10
|
+
this.name = camelCase(pkgName)
|
|
11
|
+
this.app = app
|
|
12
|
+
this.config = {}
|
|
13
|
+
this.lib = {}
|
|
14
|
+
this.exitHandler = undefined
|
|
15
|
+
this.initLog()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getConfig (path, options = {}) {
|
|
19
|
+
let obj = isEmpty(path) ? this.config : get(this.config, path, options.defValue)
|
|
20
|
+
options.omit = options.omit ?? omittedPluginKeys
|
|
21
|
+
if (isPlainObject(obj) && !isEmpty(options.omit)) obj = omit(obj, options.omit)
|
|
22
|
+
if (!options.noclone) obj = cloneDeep(obj)
|
|
23
|
+
return obj
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
initLog () {
|
|
27
|
+
this.log = new Log(this)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
initPrint (opts) {
|
|
31
|
+
this.print = new Print(this, opts)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
error (msg, ...args) {
|
|
35
|
+
if (!this.print) return new Error(msg, ...args)
|
|
36
|
+
const error = new BajoError(this, msg, ...args)
|
|
37
|
+
return error.write()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fatal (msg, ...args) {
|
|
41
|
+
let e
|
|
42
|
+
if (this.print) {
|
|
43
|
+
const error = new BajoError(this, msg, ...args)
|
|
44
|
+
e = error.write(true)
|
|
45
|
+
} else e = new Error(msg, ...args)
|
|
46
|
+
console.error(e)
|
|
47
|
+
process.kill(process.pid, 'SIGINT')
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default Plugin
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import ora from 'ora'
|
|
2
|
+
import { isPlainObject } from 'lodash-es'
|
|
3
|
+
import defaultsDeep from './bajo-core/method/defaults-deep.js'
|
|
4
|
+
import translate from '../lib/translate.js'
|
|
5
|
+
|
|
6
|
+
class Print {
|
|
7
|
+
constructor (plugin, opts = {}) {
|
|
8
|
+
this.opts = opts
|
|
9
|
+
this.plugin = plugin
|
|
10
|
+
this.startTime = this.plugin.app.bajo.lib.dayjs()
|
|
11
|
+
this.setOpts()
|
|
12
|
+
this.ora = ora(this.opts)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
setOpts (args = []) {
|
|
16
|
+
const config = this.plugin.app.bajo.config
|
|
17
|
+
let opts = {}
|
|
18
|
+
if (isPlainObject(args.slice(-1)[0])) opts = args.pop()
|
|
19
|
+
this.opts.isSilent = !!(config.silent || this.opts.isSilent)
|
|
20
|
+
this.opts = defaultsDeep(opts, this.opts)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setText (text, ...args) {
|
|
24
|
+
text = this.write(text, ...args)
|
|
25
|
+
this.setOpts(args)
|
|
26
|
+
const prefixes = []
|
|
27
|
+
const texts = []
|
|
28
|
+
if (this.opts.showDatetime) prefixes.push('[' + this.plugin.app.bajo.lib.dayjs().toISOString() + ']')
|
|
29
|
+
if (this.opts.showCounter) texts.push('[' + this.getElapsed() + ']')
|
|
30
|
+
if (prefixes.length > 0) this.ora.prefixText = this.ora.prefixText + prefixes.join(' ')
|
|
31
|
+
if (texts.length > 0) text = texts.join(' ') + ' ' + text
|
|
32
|
+
this.ora.text = text
|
|
33
|
+
return this
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
write (text, ...args) {
|
|
37
|
+
return translate.call(this.plugin, null, text, ...args)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getElapsed (unit = 'hms') {
|
|
41
|
+
const u = unit === 'hms' ? 'second' : unit
|
|
42
|
+
const elapsed = this.plugin.app.bajo.lib.dayjs().diff(this.startTime, u)
|
|
43
|
+
return unit === 'hms' ? this.plugin.app.bajo.secToHms(elapsed) : elapsed
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
start (text, ...args) {
|
|
47
|
+
this.setOpts(args)
|
|
48
|
+
this.setText(text, ...args)
|
|
49
|
+
this.ora.start()
|
|
50
|
+
return this
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
stop () {
|
|
54
|
+
this.ora.stop()
|
|
55
|
+
return this
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
succeed (text, ...args) {
|
|
59
|
+
this.setText(text, ...args)
|
|
60
|
+
this.ora.succeed()
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fail (text, ...args) {
|
|
65
|
+
this.setText(text, ...args)
|
|
66
|
+
this.ora.fail()
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
warn (text, ...args) {
|
|
71
|
+
this.setText(text, ...args)
|
|
72
|
+
this.ora.warn()
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
info (text, ...args) {
|
|
77
|
+
this.setText(text, ...args)
|
|
78
|
+
this.ora.info()
|
|
79
|
+
return this
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
clear () {
|
|
83
|
+
this.ora.clear()
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
render () {
|
|
88
|
+
this.ora.render()
|
|
89
|
+
return this
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fatal (text, ...args) {
|
|
93
|
+
this.setText(text, ...args)
|
|
94
|
+
this.ora.fail()
|
|
95
|
+
process.kill(process.pid, 'SIGINT')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
spinner () {
|
|
99
|
+
return new Print(this.plugin)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default Print
|
package/boot/index.js
CHANGED
|
@@ -1,59 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
* Boot process:
|
|
3
|
-
* 1. [Creating scope]{@link module:boot/createScope}
|
|
4
|
-
* 2. [Building config object]{@link module:boot/buildConfig}
|
|
5
|
-
* 3. Attaching helpers
|
|
6
|
-
* 4. Attaching system report
|
|
7
|
-
* 5. Determine boot orders
|
|
8
|
-
* 6. Register plugins
|
|
9
|
-
* 7. Attaching exit handlers
|
|
10
|
-
* @module boot
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import createScope from './create-scope.js'
|
|
14
|
-
import buildConfig from './build-config.js'
|
|
15
|
-
import attachHelper from './attach-helper.js'
|
|
16
|
-
import bootOrder from './boot-order.js'
|
|
17
|
-
import bootPlugins from './plugins/index.js'
|
|
18
|
-
import exitHandler from './exit-handler.js'
|
|
19
|
-
import runTool from './run-tool.js'
|
|
1
|
+
import App from './class/app.js'
|
|
20
2
|
import shim from './lib/shim.js'
|
|
21
|
-
import { last } from 'lodash-es'
|
|
22
|
-
import resolvePath from './helper/resolve-path.js'
|
|
23
3
|
|
|
24
4
|
shim()
|
|
25
5
|
|
|
26
|
-
/**
|
|
27
|
-
* The entry point to boot Bajo based application
|
|
28
|
-
*
|
|
29
|
-
* @instance
|
|
30
|
-
* @async
|
|
31
|
-
* @returns {Object} scope
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
6
|
async function boot (cwd) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const parts = l.split('=')
|
|
39
|
-
cwd = parts[1]
|
|
40
|
-
}
|
|
41
|
-
cwd = resolvePath(cwd)
|
|
42
|
-
process.env.BAJOCWD = cwd
|
|
43
|
-
const scope = createScope()
|
|
44
|
-
await buildConfig.call(scope, cwd)
|
|
45
|
-
await attachHelper.call(scope)
|
|
46
|
-
await bootOrder.call(scope)
|
|
47
|
-
await bootPlugins.call(scope)
|
|
48
|
-
await exitHandler.call(scope)
|
|
49
|
-
// boot complete
|
|
50
|
-
const { runHook, log } = scope.bajo.helper
|
|
51
|
-
await runHook('bajo:bootComplete')
|
|
52
|
-
const elapsed = new Date() - scope.bajo.runAt
|
|
53
|
-
log.info('Boot process completed in %s', scope.bajo.helper.secToHms(elapsed, true))
|
|
54
|
-
// run tool
|
|
55
|
-
await runTool.call(scope)
|
|
56
|
-
return scope
|
|
7
|
+
const app = new App(cwd)
|
|
8
|
+
await app.boot()
|
|
9
|
+
return app
|
|
57
10
|
}
|
|
58
11
|
|
|
59
12
|
export default boot
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fastGlob from 'fast-glob'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { camelCase, isFunction, isPlainObject, forOwn } from 'lodash-es'
|
|
4
|
+
import resolvePath from '../class/bajo-core/method/resolve-path.js'
|
|
5
|
+
import importModule from '../class/bajo-core/method/import-module.js'
|
|
6
|
+
import readJson from '../class/bajo-core/method/read-json.js'
|
|
7
|
+
|
|
8
|
+
export default async function (dir, pkg = 'bajo') {
|
|
9
|
+
dir = resolvePath(dir)
|
|
10
|
+
const files = await fastGlob([`!${dir}/**/_*.{js,json}`, `${dir}/**/*.{js,json}`])
|
|
11
|
+
for (const f of files) {
|
|
12
|
+
const ext = path.extname(f)
|
|
13
|
+
const base = f.replace(dir, '').replace(ext, '')
|
|
14
|
+
const name = camelCase(base)
|
|
15
|
+
let mod
|
|
16
|
+
if (ext === '.json') mod = readJson(f)
|
|
17
|
+
else mod = await importModule(f)
|
|
18
|
+
if (isFunction(mod)) {
|
|
19
|
+
mod = mod.bind(this)
|
|
20
|
+
} else if (isPlainObject(mod)) {
|
|
21
|
+
if (!mod.exec) { // mod.exec offer unbind, nacked function people can bind to anything else later
|
|
22
|
+
forOwn(mod, (v, k) => {
|
|
23
|
+
if (isFunction(v)) mod[k] = v.bind(this)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
this[name] = mod
|
|
28
|
+
}
|
|
29
|
+
return files.length
|
|
30
|
+
}
|