bajo 0.0.1 → 0.2.0
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/.jsdoc.conf.json +38 -0
- package/README.md +57 -3
- package/bajoBook/book/doc/.metadata.json +28 -0
- package/bajoBook/book/doc/How-to-Make-a-Paper-Boat-564x400@2x.jpg +0 -0
- package/bajoBook/book/doc/pages/guides/definition.md +7 -0
- package/bajoBook/book/doc/pages/guides/intro.md +3 -0
- package/bajoBook/book/doc/pages/guides/setup.md +22 -0
- package/bajoBook/book/reference/.metadata.json +152 -0
- package/bajoBook/book/reference/concept-leadership-business-with-paper-boats.jpg +0 -0
- package/bajoBook/book/reference/pages/configuration/configuration-file.md +52 -0
- package/bajoBook/book/reference/pages/helper/break-ns-path.md +24 -0
- package/bajoBook/book/reference/pages/helper/build-collections.md +19 -0
- package/bajoBook/book/reference/pages/helper/call-helper-or-handler.md +35 -0
- package/bajoBook/book/reference/pages/helper/current-loc.md +28 -0
- package/bajoBook/book/reference/pages/helper/dayjs.md +13 -0
- package/bajoBook/book/reference/pages/helper/defaults-deep.md +29 -0
- package/bajoBook/book/reference/pages/helper/dump.md +32 -0
- package/bajoBook/book/reference/pages/helper/each-plugins.md +24 -0
- package/bajoBook/book/reference/pages/helper/envs.md +11 -0
- package/bajoBook/book/reference/pages/helper/error.md +29 -0
- package/bajoBook/book/reference/pages/helper/fatal.md +18 -0
- package/bajoBook/book/reference/pages/helper/freeze.md +13 -0
- package/bajoBook/book/reference/pages/helper/generate-id.md +36 -0
- package/bajoBook/book/reference/pages/helper/get-config.md +27 -0
- package/bajoBook/book/reference/pages/helper/get-global-module-dir.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-helper.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-item-by-name.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-key-by-value.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-module-dir.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-plugin-data-dir.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-plugin-name.md +13 -0
- package/bajoBook/book/reference/pages/helper/get-plugin.md +13 -0
- package/bajoBook/book/reference/pages/helper/import-module.md +13 -0
- package/bajoBook/book/reference/pages/helper/import-pkg.md +13 -0
- package/bajoBook/book/reference/pages/helper/is-empty-dir.md +13 -0
- package/bajoBook/book/reference/pages/helper/is-log-in-range.md +13 -0
- package/bajoBook/book/reference/pages/helper/is-set.md +13 -0
- package/bajoBook/book/reference/pages/helper/is-valid-app.md +13 -0
- package/bajoBook/book/reference/pages/helper/is-valid-plugin.md +13 -0
- package/bajoBook/book/reference/pages/helper/log-levels.md +13 -0
- package/bajoBook/book/reference/pages/helper/log.md +13 -0
- package/bajoBook/book/reference/pages/helper/paginate.md +13 -0
- package/bajoBook/book/reference/pages/helper/pascal-case.md +13 -0
- package/bajoBook/book/reference/pages/helper/print.md +13 -0
- package/bajoBook/book/reference/pages/helper/read-config.md +13 -0
- package/bajoBook/book/reference/pages/helper/read-json.md +13 -0
- package/bajoBook/book/reference/pages/helper/resolve-path.md +13 -0
- package/bajoBook/book/reference/pages/helper/resolve-tpl-path.md +13 -0
- package/bajoBook/book/reference/pages/helper/run-hook.md +13 -0
- package/bajoBook/book/reference/pages/helper/save-as-download.md +13 -0
- package/bajoBook/book/reference/pages/helper/titleize.md +13 -0
- package/bajoBook/book/reference/pages/helper/white-space.md +13 -0
- package/boot/attach-helper.js +34 -0
- package/boot/boot-order.js +34 -0
- package/boot/build-config.js +99 -0
- package/boot/create-scope.js +36 -0
- package/boot/exit-handler.js +60 -0
- package/boot/helper/break-ns-path.js +17 -0
- package/boot/helper/build-collections.js +34 -0
- package/boot/helper/call-helper-or-handler.js +15 -0
- package/boot/helper/current-loc.js +11 -0
- package/boot/helper/defaults-deep.js +14 -0
- package/boot/helper/dump.js +10 -0
- package/boot/helper/each-plugins.js +104 -0
- package/boot/helper/envs.js +14 -0
- package/boot/helper/error.js +67 -0
- package/boot/helper/fatal.js +12 -0
- package/boot/helper/generate-id.js +20 -0
- package/boot/helper/get-config.js +19 -0
- package/boot/helper/get-global-module-dir.js +27 -0
- package/boot/helper/get-helper.js +12 -0
- package/boot/helper/get-item-by-name.js +26 -0
- package/boot/helper/get-key-by-value.js +5 -0
- package/boot/helper/get-module-dir.js +22 -0
- package/boot/helper/get-plugin-data-dir.js +12 -0
- package/boot/helper/get-plugin-name.js +39 -0
- package/boot/helper/get-plugin.js +14 -0
- package/boot/helper/import-module.js +25 -0
- package/boot/helper/import-pkg.js +67 -0
- package/boot/helper/is-empty-dir.js +9 -0
- package/boot/helper/is-log-in-range.js +10 -0
- package/boot/helper/is-set.js +5 -0
- package/boot/helper/is-valid-app.js +12 -0
- package/boot/helper/is-valid-plugin.js +12 -0
- package/boot/helper/log-levels.js +19 -0
- package/boot/helper/paginate.js +26 -0
- package/boot/helper/pascal-case.js +7 -0
- package/boot/helper/print.js +99 -0
- package/boot/helper/read-config.js +46 -0
- package/boot/helper/read-json.js +10 -0
- package/boot/helper/resolve-path.js +15 -0
- package/boot/helper/resolve-tpl-path.js +15 -0
- package/boot/helper/run-hook.js +46 -0
- package/boot/helper/save-as-download.js +17 -0
- package/boot/helper/titleize.js +14 -0
- package/boot/helper/white-space.js +3 -0
- package/boot/index.js +60 -0
- package/boot/lib/bora.js +97 -0
- package/boot/lib/build-helper.js +57 -0
- package/boot/lib/logger.js +75 -0
- package/boot/lib/omitted-plugin-keys.js +3 -0
- package/boot/lib/parse-args-argv.js +75 -0
- package/boot/lib/parse-env.js +36 -0
- package/boot/lib/shim.js +14 -0
- package/boot/plugins/attach-helper.js +20 -0
- package/boot/plugins/build-config.js +82 -0
- package/boot/plugins/check-clash.js +18 -0
- package/boot/plugins/check-dependency.js +37 -0
- package/boot/plugins/collect-config-handlers.js +25 -0
- package/boot/plugins/collect-exit-handlers.js +23 -0
- package/boot/plugins/collect-hooks.js +34 -0
- package/boot/plugins/extend-config.js +21 -0
- package/boot/plugins/index.js +28 -0
- package/boot/plugins/run.js +31 -0
- package/boot/run-tool.js +34 -0
- package/docs/boot_build-config.js.html +75 -0
- package/docs/boot_create-scope.js.html +25 -0
- package/docs/boot_index.js.html +43 -0
- package/docs/data/search.json +1 -0
- 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 +18 -0
- package/docs/helper_envs.js.html +16 -0
- package/docs/helper_error.js.html +25 -0
- package/docs/helper_get-bajo.js.html +42 -0
- package/docs/helper_index.js.html +39 -0
- package/docs/helper_log-levels.js.html +20 -0
- package/docs/helper_set-hook.js.html +38 -0
- package/docs/helper_walk-bajos.js.html +51 -0
- package/docs/index.html +16 -0
- package/docs/module-boot.html +3 -0
- package/docs/module-boot_buildConfig.html +3 -0
- package/docs/module-boot_createScope.html +3 -0
- package/docs/module-helper.html +7 -0
- package/docs/module-helper_setHook.html +4 -0
- package/docs/module-helper_walkBajos.html +6 -0
- package/docs/scripts/core.js +655 -0
- package/docs/scripts/core.min.js +23 -0
- package/docs/scripts/resize.js +90 -0
- package/docs/scripts/search.js +265 -0
- package/docs/scripts/search.min.js +6 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/scripts/third-party/fuse.js +9 -0
- package/docs/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/scripts/third-party/hljs-original.js +5171 -0
- package/docs/scripts/third-party/hljs.js +1 -0
- package/docs/scripts/third-party/popper.js +5 -0
- package/docs/scripts/third-party/tippy.js +1 -0
- package/docs/scripts/third-party/tocbot.js +672 -0
- package/docs/scripts/third-party/tocbot.min.js +1 -0
- package/docs/styles/clean-jsdoc-theme-base.css +975 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +407 -0
- package/docs/styles/clean-jsdoc-theme-light.css +388 -0
- package/docs/styles/clean-jsdoc-theme.min.css +1 -0
- package/package.json +36 -4
- package/test/helper-error.js +25 -0
- package/test/helper-isSet.js +41 -0
- package/test/helper-pathResolve.js +28 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import logLevels from './log-levels.js'
|
|
2
|
+
import { keys, indexOf } from 'lodash-es'
|
|
3
|
+
|
|
4
|
+
function isLogInRange (level) {
|
|
5
|
+
const levels = keys(logLevels)
|
|
6
|
+
const logLevel = indexOf(levels, this.bajo.config.log.level)
|
|
7
|
+
return indexOf(levels, level) >= logLevel
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default isLogInRange
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import resolvePath from './resolve-path.js'
|
|
3
|
+
|
|
4
|
+
const isValidApp = (dir) => {
|
|
5
|
+
if (!dir) dir = process.env.BAJOCWD
|
|
6
|
+
dir = resolvePath(dir)
|
|
7
|
+
const hasAppDir = fs.existsSync(`${dir}/app/bajo`)
|
|
8
|
+
const hasPackageJson = fs.existsSync(`${dir}/package.json`)
|
|
9
|
+
return hasAppDir && hasPackageJson
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default isValidApp
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import resolvePath from './resolve-path.js'
|
|
3
|
+
|
|
4
|
+
const isValidPlugin = (dir) => {
|
|
5
|
+
if (!dir) dir = process.env.BAJOCWD
|
|
6
|
+
dir = resolvePath(dir)
|
|
7
|
+
const hasBajoDir = fs.existsSync(`${dir}/bajo`)
|
|
8
|
+
const hasPackageJson = fs.existsSync(`${dir}/package.json`)
|
|
9
|
+
return hasBajoDir && hasPackageJson
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default isValidPlugin
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported logger levels including its level priority
|
|
3
|
+
*
|
|
4
|
+
* @memberof module:helper
|
|
5
|
+
* @type Object
|
|
6
|
+
* @instance
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const logLevels = {
|
|
10
|
+
trace: 10,
|
|
11
|
+
debug: 20,
|
|
12
|
+
info: 30,
|
|
13
|
+
warn: 40,
|
|
14
|
+
error: 50,
|
|
15
|
+
fatal: 60,
|
|
16
|
+
silent: 99
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default logLevels
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isEmpty, isPlainObject, orderBy, forOwn } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
function paginate (collection, { page = 1, limit = 25, sort } = {}) {
|
|
4
|
+
const count = collection.length
|
|
5
|
+
const offset = (page - 1) * limit
|
|
6
|
+
const fields = []
|
|
7
|
+
const dirs = []
|
|
8
|
+
if (isPlainObject(sort)) {
|
|
9
|
+
forOwn(sort, (v, k) => {
|
|
10
|
+
fields.push(k)
|
|
11
|
+
dirs.push(v < 0 ? 'desc' : 'asc')
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
if (!isEmpty(fields)) collection = orderBy(collection, fields, dirs)
|
|
15
|
+
const data = collection.slice(offset, offset + limit)
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
data,
|
|
19
|
+
page,
|
|
20
|
+
limit,
|
|
21
|
+
count,
|
|
22
|
+
pages: Math.ceil(collection.length / limit)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default paginate
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import bora from '../lib/bora.js'
|
|
2
|
+
import Sprintf from 'sprintf-js'
|
|
3
|
+
import { last, isPlainObject, get, merge, upperFirst } from 'lodash-es'
|
|
4
|
+
import defaultsDeep from './defaults-deep.js'
|
|
5
|
+
import getPluginName from './get-plugin-name.js'
|
|
6
|
+
|
|
7
|
+
const { sprintf } = Sprintf
|
|
8
|
+
|
|
9
|
+
function prep (args) {
|
|
10
|
+
let opts = { type: 'bora', exit: false, skipSilent: false }
|
|
11
|
+
const l = last(args)
|
|
12
|
+
if (isPlainObject(l)) opts = defaultsDeep(args.pop(), opts)
|
|
13
|
+
const [pkg, msg, ...params] = args
|
|
14
|
+
opts.pkg = pkg
|
|
15
|
+
opts.ns = pkg === 'bajo' ? 'bajoI18N' : pkg
|
|
16
|
+
return { ns: opts.ns, pkg, msg, params, opts }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function format (...args) {
|
|
20
|
+
const { ns, msg, params, opts } = prep(args)
|
|
21
|
+
if (!msg) return ''
|
|
22
|
+
const i18n = get(this, 'bajoI18N.instance')
|
|
23
|
+
if (i18n) {
|
|
24
|
+
if (isPlainObject(params[0])) {
|
|
25
|
+
const ctx = merge({}, params[0] ?? {}, { ns })
|
|
26
|
+
if (msg.startsWith('validation') && ctx.message && !i18n.exists(msg, { ns })) {
|
|
27
|
+
const message = ctx.message
|
|
28
|
+
.replace(/".*?" /, '')
|
|
29
|
+
.replace(/^is /, '')
|
|
30
|
+
return upperFirst(message)
|
|
31
|
+
}
|
|
32
|
+
if (msg === 'field.username') console.log(ctx)
|
|
33
|
+
return i18n.t(msg, ctx)
|
|
34
|
+
}
|
|
35
|
+
return i18n.t(msg, { ns, pkg: opts.pkg, postProcess: 'sprintf', sprintf: params })
|
|
36
|
+
}
|
|
37
|
+
return sprintf(msg, ...params)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const print = {
|
|
41
|
+
__: function (...args) {
|
|
42
|
+
const [msg, ...params] = args
|
|
43
|
+
const pkg = getPluginName.call(this, 2)
|
|
44
|
+
return format.call(this, pkg, msg, ...params)
|
|
45
|
+
},
|
|
46
|
+
_format: format,
|
|
47
|
+
fail: function (...args) {
|
|
48
|
+
args.unshift(getPluginName.call(this, 2))
|
|
49
|
+
const { ns, opts, msg, params } = prep(args)
|
|
50
|
+
if (msg) {
|
|
51
|
+
if (opts.type === 'bora') bora.call(this, ns, opts).fail(msg, ...params)
|
|
52
|
+
else console.error(format.call(this, ns, msg, ...params))
|
|
53
|
+
}
|
|
54
|
+
if (opts.exit) process.exit(1)
|
|
55
|
+
},
|
|
56
|
+
succeed: function (...args) {
|
|
57
|
+
args.unshift(getPluginName.call(this, 2))
|
|
58
|
+
const { ns, opts, msg, params } = prep(args)
|
|
59
|
+
if (msg) {
|
|
60
|
+
if (opts.type === 'bora') bora.call(this, ns, opts).succeed(msg, ...params)
|
|
61
|
+
else console.log(format.call(this, ns, msg, ...params))
|
|
62
|
+
}
|
|
63
|
+
if (opts.exit) process.exit(0)
|
|
64
|
+
},
|
|
65
|
+
warn: function (...args) {
|
|
66
|
+
args.unshift(getPluginName.call(this, 2))
|
|
67
|
+
const { ns, opts, msg, params } = prep(args)
|
|
68
|
+
if (msg) {
|
|
69
|
+
if (opts.type === 'bora') bora.call(this, ns, opts).warn(msg, ...params)
|
|
70
|
+
else console.log(format.call(this, ns, msg, ...params))
|
|
71
|
+
}
|
|
72
|
+
if (opts.exit) process.exit(0)
|
|
73
|
+
},
|
|
74
|
+
info: function (...args) {
|
|
75
|
+
args.unshift(getPluginName.call(this, 2))
|
|
76
|
+
const { ns, opts, msg, params } = prep(args)
|
|
77
|
+
if (msg) {
|
|
78
|
+
if (opts.type === 'bora') bora.call(this, ns, opts).info(msg, ...params)
|
|
79
|
+
else console.log(format.call(this, ns, msg, ...params))
|
|
80
|
+
}
|
|
81
|
+
if (opts.exit) process.exit(0)
|
|
82
|
+
},
|
|
83
|
+
fatal: function (...args) {
|
|
84
|
+
args.unshift(getPluginName.call(this, 2))
|
|
85
|
+
const { ns, opts, msg, params } = prep(args)
|
|
86
|
+
if (msg) {
|
|
87
|
+
if (opts.type === 'bora') bora.call(this, ns, opts).fatal(msg, ...params)
|
|
88
|
+
else console.error(format.call(this, ns, msg, ...params))
|
|
89
|
+
}
|
|
90
|
+
process.exit(0)
|
|
91
|
+
},
|
|
92
|
+
bora: function (...args) {
|
|
93
|
+
let ns = getPluginName.call(this, 2)
|
|
94
|
+
if (ns === 'bajo') ns = 'bajoI18N'
|
|
95
|
+
return bora.call(this, ns, ...args)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export default print
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import resolvePath from './resolve-path.js'
|
|
3
|
+
import readJson from './read-json.js'
|
|
4
|
+
import { find, map, isEmpty } from 'lodash-es'
|
|
5
|
+
import error from './error.js'
|
|
6
|
+
import fg from 'fast-glob'
|
|
7
|
+
|
|
8
|
+
async function readConfig (file, { pattern, globOptions = {}, ignoreError, defValue = {} } = {}) {
|
|
9
|
+
file = resolvePath(file)
|
|
10
|
+
let ext = path.extname(file)
|
|
11
|
+
const fname = path.dirname(file) + '/' + path.basename(file, ext)
|
|
12
|
+
ext = ext.toLowerCase()
|
|
13
|
+
if (['.mjs', '.js'].includes(ext)) {
|
|
14
|
+
const { handler } = find(this.bajo.configHandlers, { ext })
|
|
15
|
+
return await handler.call(this, file)
|
|
16
|
+
}
|
|
17
|
+
if (ext === '.json') return await readJson(file)
|
|
18
|
+
if (!['', '.*'].includes(ext)) {
|
|
19
|
+
const item = find(this.bajo.configHandlers, { ext })
|
|
20
|
+
if (!item) {
|
|
21
|
+
if (!ignoreError) throw error.call(this, 'Can\'t parse \'%s\'', file, { code: 'BAJO_CONFIG_NO_PARSER' })
|
|
22
|
+
return defValue
|
|
23
|
+
}
|
|
24
|
+
return item.handler.call(this, file)
|
|
25
|
+
}
|
|
26
|
+
const item = pattern ?? `${fname}.{${map(map(this.bajo.configHandlers, 'ext'), k => k.slice(1)).join(',')}}`
|
|
27
|
+
const files = await fg(item, globOptions)
|
|
28
|
+
if (files.length === 0) {
|
|
29
|
+
if (!ignoreError) throw error.call(this, 'No config file found', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
|
|
30
|
+
return defValue
|
|
31
|
+
}
|
|
32
|
+
let config = defValue
|
|
33
|
+
for (const f of files) {
|
|
34
|
+
const ext = path.extname(f).toLowerCase()
|
|
35
|
+
const item = find(this.bajo.configHandlers, { ext })
|
|
36
|
+
if (!item) {
|
|
37
|
+
if (!ignoreError) throw error.call(this, 'Can\'t parse \'%s\'', f, { code: 'BAJO_CONFIG_NO_PARSER' })
|
|
38
|
+
continue
|
|
39
|
+
}
|
|
40
|
+
config = await item.handler.call(this, f)
|
|
41
|
+
if (!isEmpty(config)) break
|
|
42
|
+
}
|
|
43
|
+
return config
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default readConfig
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { fileURLToPath } from 'url'
|
|
3
|
+
import os from 'os'
|
|
4
|
+
|
|
5
|
+
const resolvePath = (item, asFileUrl) => {
|
|
6
|
+
if (item.startsWith('file://')) item = fileURLToPath(item)
|
|
7
|
+
item = path.resolve(item)
|
|
8
|
+
if (os.platform() === 'win32') {
|
|
9
|
+
item = item.replace(/\\/g, '/')
|
|
10
|
+
}
|
|
11
|
+
if (asFileUrl) item = `file:///${item}`
|
|
12
|
+
return item
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default resolvePath
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { trim } from 'lodash-es'
|
|
2
|
+
import fs from 'fs-extra'
|
|
3
|
+
|
|
4
|
+
function resolveTplPath (name, baseTpl, extTpl = '') {
|
|
5
|
+
const { getConfig, breakNsPath } = this.bajo.helper
|
|
6
|
+
const [ns, path] = breakNsPath(name)
|
|
7
|
+
const cfgNs = getConfig(ns, { full: true })
|
|
8
|
+
const cfgApp = getConfig('app', { full: true })
|
|
9
|
+
let file = `${cfgNs.dir.pkg}/${baseTpl}/${trim(path, '/')}${extTpl}`
|
|
10
|
+
const override = `${cfgApp.dir.pkg}/${baseTpl}/override/${ns}/${trim(path, '/')}${extTpl}`
|
|
11
|
+
if (fs.existsSync(override)) file = override
|
|
12
|
+
return file
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default resolveTplPath
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { filter, isEmpty, orderBy } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @module helper/runHook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Set hook defined by parameter ```hookName```. Hook name should be in this following format:
|
|
9
|
+
* ```<namespace>:<identifier>``` - where namespace is a valid Bajo name and
|
|
10
|
+
* identifier is a unique string set by Bajo developer to identify a hook inside a Bajo
|
|
11
|
+
*
|
|
12
|
+
* @instance
|
|
13
|
+
* @async
|
|
14
|
+
* @param {string} hookName - Hook's name
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const { runHook } = this.bajo.helper
|
|
18
|
+
* await runHook('myBajo:afterStartApp')
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
async function runHook (hookName, ...args) {
|
|
22
|
+
// const { log } = this.bajo.helper
|
|
23
|
+
// log.trace('Run hook: %s', hookName)
|
|
24
|
+
const [ns, path] = (hookName ?? '').split(':')
|
|
25
|
+
let fns = filter(this.bajo.hooks, { ns, path })
|
|
26
|
+
if (isEmpty(fns)) return
|
|
27
|
+
fns = orderBy(fns, ['level'])
|
|
28
|
+
const results = []
|
|
29
|
+
for (const i in fns) {
|
|
30
|
+
const fn = fns[i]
|
|
31
|
+
/*
|
|
32
|
+
if (config.log.report.includes(id)) {
|
|
33
|
+
log.trace({ args }, 'Call hook: %s', id)
|
|
34
|
+
}
|
|
35
|
+
*/
|
|
36
|
+
const res = await fn.handler.call(this, ...args)
|
|
37
|
+
results.push({
|
|
38
|
+
hook: hookName,
|
|
39
|
+
tag: fn.tag,
|
|
40
|
+
resp: res
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
return results
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default runHook
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { trim } from 'lodash-es'
|
|
4
|
+
import increment from 'add-filename-increment'
|
|
5
|
+
|
|
6
|
+
async function saveAsDownload (file, obj, printSaved = true) {
|
|
7
|
+
const { print, getPluginName, getPluginDataDir } = this.bajo.helper
|
|
8
|
+
const plugin = getPluginName(4)
|
|
9
|
+
const fname = increment(`${getPluginDataDir(plugin)}/${trim(file, '/')}`, { fs: true })
|
|
10
|
+
const dir = path.dirname(fname)
|
|
11
|
+
if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
|
|
12
|
+
await fs.writeFile(fname, obj, 'utf8')
|
|
13
|
+
if (printSaved) print.bora('Saved as \'%s\'', path.resolve(fname), { skipSilence: true }).succeed()
|
|
14
|
+
return fname
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default saveAsDownload
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { words, upperFirst, map, isFunction, concat, uniq } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
const defIgnores = ['or', 'and', 'of', 'with']
|
|
4
|
+
|
|
5
|
+
function titleize (text, { transformer, ignores = [] } = {}) {
|
|
6
|
+
return map(words(text), t => {
|
|
7
|
+
if (isFunction(transformer)) return transformer.call(this, t)
|
|
8
|
+
ignores = uniq(concat(ignores, defIgnores))
|
|
9
|
+
if (ignores.includes(t)) return t
|
|
10
|
+
return upperFirst(t)
|
|
11
|
+
}).join(' ')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default titleize
|
package/boot/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
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'
|
|
20
|
+
import shim from './lib/shim.js'
|
|
21
|
+
import { last } from 'lodash-es'
|
|
22
|
+
import path from 'path'
|
|
23
|
+
import resolvePath from './helper/resolve-path.js'
|
|
24
|
+
|
|
25
|
+
shim()
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The entry point to boot Bajo based application
|
|
29
|
+
*
|
|
30
|
+
* @instance
|
|
31
|
+
* @async
|
|
32
|
+
* @returns {Object} scope
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
async function boot (cwd) {
|
|
36
|
+
if (!cwd) cwd = path.dirname(process.argv[1])
|
|
37
|
+
const l = last(process.argv)
|
|
38
|
+
if (l.startsWith('--cwd')) {
|
|
39
|
+
const parts = l.split('=')
|
|
40
|
+
cwd = parts[1]
|
|
41
|
+
}
|
|
42
|
+
cwd = resolvePath(cwd)
|
|
43
|
+
process.env.BAJOCWD = cwd
|
|
44
|
+
const scope = createScope()
|
|
45
|
+
await buildConfig.call(scope, cwd)
|
|
46
|
+
await attachHelper.call(scope)
|
|
47
|
+
await bootOrder.call(scope)
|
|
48
|
+
await bootPlugins.call(scope)
|
|
49
|
+
await exitHandler.call(scope)
|
|
50
|
+
// boot complete
|
|
51
|
+
const { runHook, log } = scope.bajo.helper
|
|
52
|
+
await runHook('bajo:bootComplete')
|
|
53
|
+
const elapsed = (new Date() - scope.bajo.runAt).toLocaleString()
|
|
54
|
+
log.info('Boot process completed in %sms', elapsed)
|
|
55
|
+
// run tool
|
|
56
|
+
await runTool.call(scope)
|
|
57
|
+
return scope
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default boot
|
package/boot/lib/bora.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import Sprintf from 'sprintf-js'
|
|
2
|
+
import ora from 'ora'
|
|
3
|
+
import { last, isPlainObject, get, isString } from 'lodash-es'
|
|
4
|
+
|
|
5
|
+
const { sprintf } = Sprintf
|
|
6
|
+
|
|
7
|
+
class Bora {
|
|
8
|
+
constructor (ns, ...args) {
|
|
9
|
+
this.ns = ns
|
|
10
|
+
const l = last(args)
|
|
11
|
+
let opts = {}
|
|
12
|
+
if (isPlainObject(l)) opts = args.pop()
|
|
13
|
+
this.opts = opts
|
|
14
|
+
this.ora = ora(this.opts)
|
|
15
|
+
this.args = args
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setScope (scope) {
|
|
19
|
+
this.scope = scope
|
|
20
|
+
const { getConfig } = this.scope.bajo.helper
|
|
21
|
+
const config = getConfig()
|
|
22
|
+
let silent = !!config.silent
|
|
23
|
+
if (this.opts.skipSilent) silent = false
|
|
24
|
+
this.ora.isSilent = silent
|
|
25
|
+
const [text, ...params] = this.args
|
|
26
|
+
this.setText(text, ...params)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setText (text, ...args) {
|
|
30
|
+
if (isString(text)) {
|
|
31
|
+
const i18n = get(this, 'scope.bajoI18N.instance')
|
|
32
|
+
if (i18n) {
|
|
33
|
+
if (isPlainObject(args[0])) text = i18n.t(text, args[0])
|
|
34
|
+
else text = i18n.t(text, { ns: this.ns, postProcess: 'sprintf', sprintf: args })
|
|
35
|
+
} else text = sprintf(text, ...args)
|
|
36
|
+
this.ora.text = text
|
|
37
|
+
}
|
|
38
|
+
return this
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
start (text, ...args) {
|
|
42
|
+
this.setText(text, ...args)
|
|
43
|
+
this.ora.start()
|
|
44
|
+
return this
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
stop () {
|
|
48
|
+
this.ora.stop()
|
|
49
|
+
return this
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
succeed (text, ...args) {
|
|
53
|
+
this.setText(text, ...args)
|
|
54
|
+
this.ora.succeed()
|
|
55
|
+
return this
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fail (text, ...args) {
|
|
59
|
+
this.setText(text, ...args)
|
|
60
|
+
this.ora.fail()
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
warn (text, ...args) {
|
|
65
|
+
this.setText(text, ...args)
|
|
66
|
+
this.ora.warn()
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
info (text, ...args) {
|
|
71
|
+
this.setText(text, ...args)
|
|
72
|
+
this.ora.info()
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
clear () {
|
|
77
|
+
this.ora.clear()
|
|
78
|
+
return this
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
render () {
|
|
82
|
+
this.ora.render()
|
|
83
|
+
return this
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fatal (text, ...args) {
|
|
87
|
+
this.setText(text, ...args)
|
|
88
|
+
this.ora.fail()
|
|
89
|
+
process.exit(1)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default function (ns, ...args) {
|
|
94
|
+
const bora = new Bora(ns, ...args)
|
|
95
|
+
bora.setScope(this)
|
|
96
|
+
return bora
|
|
97
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fastGlob from 'fast-glob'
|
|
2
|
+
import { map, without, camelCase, isFunction, isPlainObject, forOwn } from 'lodash-es'
|
|
3
|
+
import resolvePath from '../helper/resolve-path.js'
|
|
4
|
+
import importModule from '../helper/import-module.js'
|
|
5
|
+
|
|
6
|
+
function stackInfo (name, ...args) {
|
|
7
|
+
const { log, callsites } = this.bajo.helper
|
|
8
|
+
const config = this.bajo.config
|
|
9
|
+
if (config.env === 'prod') return
|
|
10
|
+
if (!config.log.report.includes(`helper:${name}`)) return
|
|
11
|
+
const info = callsites()[2]
|
|
12
|
+
const file = info.getFileName()
|
|
13
|
+
const line = info.getLineNumber()
|
|
14
|
+
log.trace({ line, file, args }, 'Call helper: %s()', name)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const wrapFn = function (name, handler, bind) {
|
|
18
|
+
return (...args) => {
|
|
19
|
+
stackInfo.call(this, name, ...args)
|
|
20
|
+
if (bind) return handler.call(this, ...args)
|
|
21
|
+
return handler(...args)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const wrapAsyncFn = function (name, handler, bind) {
|
|
26
|
+
return async (...args) => {
|
|
27
|
+
stackInfo.call(this, name, ...args)
|
|
28
|
+
if (bind) return await handler.call(this, ...args)
|
|
29
|
+
return await handler(...args)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default async function (dir, { pkg = 'bajo', exclude = [] } = {}) {
|
|
34
|
+
dir = resolvePath(dir)
|
|
35
|
+
exclude = map(exclude, e => `${dir}/${e}`)
|
|
36
|
+
let files = await fastGlob(`${dir}/**/*.js`)
|
|
37
|
+
files = without(files, ...exclude)
|
|
38
|
+
const helper = {}
|
|
39
|
+
for (const f of files) {
|
|
40
|
+
const base = f.replace(dir, '').replace('.js', '')
|
|
41
|
+
const name = camelCase(base)
|
|
42
|
+
const fnName = pkg + '.' + name
|
|
43
|
+
let mod = await importModule(f)
|
|
44
|
+
if (isFunction(mod)) {
|
|
45
|
+
if (mod.constructor.name === 'AsyncFunction') mod = wrapAsyncFn.call(this, fnName, mod, true)
|
|
46
|
+
else mod = wrapFn.call(this, fnName, mod, true)
|
|
47
|
+
} else if (isPlainObject(mod)) {
|
|
48
|
+
if (!mod.exec) { // mod.exec offer unbind, nacked function people can band to anything else later
|
|
49
|
+
forOwn(mod, (v, k) => {
|
|
50
|
+
if (isFunction(v)) mod[k] = v.bind(this)
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
helper[name] = mod
|
|
55
|
+
}
|
|
56
|
+
return helper
|
|
57
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test test
|
|
3
|
+
*
|
|
4
|
+
* @kind function
|
|
5
|
+
* @name logger
|
|
6
|
+
* @returns {Object}
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import print from '../helper/print.js'
|
|
11
|
+
import os from 'os'
|
|
12
|
+
import { keys, each, isEmpty, without, merge, upperFirst, isString } from 'lodash-es'
|
|
13
|
+
// import pretty from 'prettyjson'
|
|
14
|
+
import getPluginName from '../helper/get-plugin-name.js'
|
|
15
|
+
import levels from '../helper/log-levels.js'
|
|
16
|
+
import isLogInRange from '../helper/is-log-in-range.js'
|
|
17
|
+
import dayjs from 'dayjs'
|
|
18
|
+
|
|
19
|
+
const levelList = keys(levels)
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
const prettyOpts = {
|
|
23
|
+
noAlign: true,
|
|
24
|
+
defaultIndentation: 2,
|
|
25
|
+
renderUndefined: true
|
|
26
|
+
}
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export default function logger () {
|
|
30
|
+
const config = this.bajo.config
|
|
31
|
+
// const format = config.log.dateFormat
|
|
32
|
+
const format = 'YYYY-MM-DDTHH:MM:ss.SSS[Z]'
|
|
33
|
+
const log = {}
|
|
34
|
+
const self = this
|
|
35
|
+
log.child = () => {
|
|
36
|
+
if (!config.log.logger) config.log.logger = 'bajoLogger'
|
|
37
|
+
if (self[config.log.logger] && self[config.log.logger].logger) return self[config.log.logger].logger.child()
|
|
38
|
+
return self
|
|
39
|
+
}
|
|
40
|
+
each(levelList, l => {
|
|
41
|
+
log[l] = (...params) => {
|
|
42
|
+
const config = this.bajo.config
|
|
43
|
+
if (config.log.level === 'silent') return
|
|
44
|
+
if (!isLogInRange.call(this, l)) return
|
|
45
|
+
let [data, msg, ...args] = params
|
|
46
|
+
if (isString(data)) {
|
|
47
|
+
args.unshift(msg)
|
|
48
|
+
msg = data
|
|
49
|
+
data = null
|
|
50
|
+
}
|
|
51
|
+
args = without(args, undefined)
|
|
52
|
+
const pkg = getPluginName.call(this)
|
|
53
|
+
msg = print._format(pkg, `[%s] ${msg}`, pkg, ...args)
|
|
54
|
+
const bajoLog = config.log.logger ?? 'bajoLogger'
|
|
55
|
+
if (this[bajoLog] && this[bajoLog].logger) {
|
|
56
|
+
this[bajoLog].logger[l](data, msg, ...args)
|
|
57
|
+
} else {
|
|
58
|
+
let text
|
|
59
|
+
const dt = new Date()
|
|
60
|
+
if (config.env === 'prod') {
|
|
61
|
+
const json = { level: levels[l], time: dt.valueOf(), pid: process.pid, hostname: os.hostname() }
|
|
62
|
+
if (!isEmpty(data)) merge(json, data)
|
|
63
|
+
merge(json, { msg })
|
|
64
|
+
text = JSON.stringify(json)
|
|
65
|
+
} else {
|
|
66
|
+
text = `[${dayjs(dt).utc(true).format(format)}] ${upperFirst(l)}: ${msg}`
|
|
67
|
+
// if (!isEmpty(data)) text += '\n ' + (pretty.render(data, prettyOpts).split('\n').join('\n '))
|
|
68
|
+
if (!isEmpty(data)) text += '\n' + JSON.stringify(data)
|
|
69
|
+
}
|
|
70
|
+
console.log(text)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
return log
|
|
75
|
+
}
|