bajo 0.3.10 → 1.0.1

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.
Files changed (162) hide show
  1. package/README.md +127 -26
  2. package/bajoI18N/resource/id.json +31 -0
  3. package/boot/class/app.js +69 -0
  4. package/boot/class/bajo-core/helper/attach-method.js +30 -0
  5. package/boot/{boot-order.js → class/bajo-core/helper/boot-order.js} +10 -10
  6. package/boot/class/bajo-core/helper/boot-plugins.js +19 -0
  7. package/boot/class/bajo-core/helper/build-config.js +61 -0
  8. package/boot/class/bajo-core/helper/build-plugins.js +26 -0
  9. package/boot/class/bajo-core/helper/collect-config-handlers.js +21 -0
  10. package/boot/{exit-handler.js → class/bajo-core/helper/exit-handler.js} +10 -16
  11. package/boot/class/bajo-core/helper/run-as-applet.js +26 -0
  12. package/boot/class/bajo-core/method/arrange-array.js +18 -0
  13. package/boot/class/bajo-core/method/break-ns-path-from-file.js +24 -0
  14. package/boot/class/bajo-core/method/break-ns-path.js +29 -0
  15. package/boot/class/bajo-core/method/build-collections.js +46 -0
  16. package/boot/class/bajo-core/method/call-handler.js +29 -0
  17. package/boot/{helper → class/bajo-core/method}/defaults-deep.js +1 -1
  18. package/boot/class/bajo-core/method/each-plugins.js +55 -0
  19. package/boot/class/bajo-core/method/envs.js +7 -0
  20. package/boot/{helper → class/bajo-core/method}/generate-id.js +4 -0
  21. package/boot/{helper → class/bajo-core/method}/get-global-module-dir.js +3 -4
  22. package/boot/class/bajo-core/method/get-method.js +10 -0
  23. package/boot/{helper → class/bajo-core/method}/get-module-dir.js +3 -4
  24. package/boot/{helper → class/bajo-core/method}/get-plugin-data-dir.js +2 -3
  25. package/boot/class/bajo-core/method/get-plugin-file.js +18 -0
  26. package/boot/class/bajo-core/method/get-plugin.js +23 -0
  27. package/boot/{helper → class/bajo-core/method}/import-module.js +4 -10
  28. package/boot/{helper → class/bajo-core/method}/import-pkg.js +9 -3
  29. package/boot/class/bajo-core/method/includes.js +13 -0
  30. package/boot/class/bajo-core/method/is-class.js +7 -0
  31. package/boot/{helper → class/bajo-core/method}/is-log-in-range.js +1 -1
  32. package/boot/{helper → class/bajo-core/method}/is-valid-app.js +2 -2
  33. package/boot/class/bajo-core/method/join.js +15 -0
  34. package/boot/class/bajo-core/method/log-levels.js +9 -0
  35. package/boot/class/bajo-core/method/num-unit.js +9 -0
  36. package/boot/{helper → class/bajo-core/method}/parse-object.js +24 -8
  37. package/boot/class/bajo-core/method/read-config.js +48 -0
  38. package/boot/{helper → class/bajo-core/method}/read-json.js +2 -2
  39. package/boot/class/bajo-core/method/run-hook.js +26 -0
  40. package/boot/{helper → class/bajo-core/method}/save-as-download.js +2 -2
  41. package/boot/class/bajo-core/method/slice-string.js +13 -0
  42. package/boot/class/bajo-core/method/titleize.js +23 -0
  43. package/boot/class/bajo-core.js +30 -0
  44. package/boot/class/bajo-plugin/helper/attach-method.js +14 -0
  45. package/boot/class/bajo-plugin/helper/build-config.js +10 -0
  46. package/boot/class/bajo-plugin/helper/check-clash.js +16 -0
  47. package/boot/class/bajo-plugin/helper/check-dependency.js +37 -0
  48. package/boot/class/bajo-plugin/helper/collect-exit-handlers.js +14 -0
  49. package/boot/class/bajo-plugin/helper/collect-hooks.js +29 -0
  50. package/boot/class/bajo-plugin/helper/run.js +20 -0
  51. package/boot/class/bajo-plugin.js +78 -0
  52. package/boot/class/error.js +59 -0
  53. package/boot/class/log.js +67 -0
  54. package/boot/class/plugin.js +51 -0
  55. package/boot/class/print.js +103 -0
  56. package/boot/index.js +4 -51
  57. package/boot/lib/create-method.js +30 -0
  58. package/boot/{helper → lib}/current-loc.js +1 -1
  59. package/boot/lib/omitted-plugin-keys.js +1 -1
  60. package/boot/lib/parse-args-argv.js +8 -11
  61. package/boot/lib/parse-env.js +7 -6
  62. package/boot/lib/read-all-configs.js +36 -0
  63. package/boot/lib/translate.js +18 -0
  64. package/docs/ecosystem.md +55 -0
  65. package/docs/hook.md +11 -0
  66. package/package.json +55 -56
  67. package/test/{helper-isSet.js → method/isSet.js} +6 -4
  68. package/waibuStatic/virtual.json +7 -0
  69. package/boot/attach-helper.js +0 -40
  70. package/boot/build-config.js +0 -99
  71. package/boot/create-scope.js +0 -36
  72. package/boot/helper/break-ns-path.js +0 -20
  73. package/boot/helper/build-collections.js +0 -43
  74. package/boot/helper/build-name.js +0 -17
  75. package/boot/helper/call-helper-or-handler.js +0 -15
  76. package/boot/helper/dump.js +0 -14
  77. package/boot/helper/each-plugins.js +0 -106
  78. package/boot/helper/envs.js +0 -14
  79. package/boot/helper/error.js +0 -77
  80. package/boot/helper/fatal.js +0 -13
  81. package/boot/helper/get-config.js +0 -19
  82. package/boot/helper/get-helper.js +0 -12
  83. package/boot/helper/get-item-by-name.js +0 -26
  84. package/boot/helper/get-plugin-file.js +0 -16
  85. package/boot/helper/get-plugin-name.js +0 -39
  86. package/boot/helper/get-plugin.js +0 -14
  87. package/boot/helper/join.js +0 -11
  88. package/boot/helper/log-levels.js +0 -19
  89. package/boot/helper/read-config.js +0 -48
  90. package/boot/helper/resolve-tpl-path.js +0 -15
  91. package/boot/helper/run-hook.js +0 -49
  92. package/boot/helper/spinner.js +0 -9
  93. package/boot/helper/start-plugin.js +0 -7
  94. package/boot/helper/titleize.js +0 -14
  95. package/boot/lib/build-helper.js +0 -60
  96. package/boot/lib/logger.js +0 -76
  97. package/boot/lib/print.js +0 -138
  98. package/boot/plugins/attach-helper.js +0 -20
  99. package/boot/plugins/build-config.js +0 -68
  100. package/boot/plugins/check-clash.js +0 -18
  101. package/boot/plugins/check-dependency.js +0 -37
  102. package/boot/plugins/collect-config-handlers.js +0 -22
  103. package/boot/plugins/collect-exit-handlers.js +0 -18
  104. package/boot/plugins/collect-hooks.js +0 -34
  105. package/boot/plugins/extend-config.js +0 -21
  106. package/boot/plugins/index.js +0 -27
  107. package/boot/plugins/run.js +0 -26
  108. package/boot/run-tool.js +0 -41
  109. package/docs/boot_build-config.js.html +0 -75
  110. package/docs/boot_create-scope.js.html +0 -25
  111. package/docs/boot_index.js.html +0 -43
  112. package/docs/data/search.json +0 -1
  113. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  114. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  115. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  116. package/docs/helper_emit.js.html +0 -18
  117. package/docs/helper_envs.js.html +0 -16
  118. package/docs/helper_error.js.html +0 -25
  119. package/docs/helper_get-bajo.js.html +0 -42
  120. package/docs/helper_index.js.html +0 -39
  121. package/docs/helper_log-levels.js.html +0 -20
  122. package/docs/helper_set-hook.js.html +0 -38
  123. package/docs/helper_walk-bajos.js.html +0 -51
  124. package/docs/index.html +0 -16
  125. package/docs/module-boot.html +0 -3
  126. package/docs/module-boot_buildConfig.html +0 -3
  127. package/docs/module-boot_createScope.html +0 -3
  128. package/docs/module-helper.html +0 -7
  129. package/docs/module-helper_setHook.html +0 -4
  130. package/docs/module-helper_walkBajos.html +0 -6
  131. package/docs/scripts/core.js +0 -655
  132. package/docs/scripts/core.min.js +0 -23
  133. package/docs/scripts/resize.js +0 -90
  134. package/docs/scripts/search.js +0 -265
  135. package/docs/scripts/search.min.js +0 -6
  136. package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
  137. package/docs/scripts/third-party/fuse.js +0 -9
  138. package/docs/scripts/third-party/hljs-line-num-original.js +0 -369
  139. package/docs/scripts/third-party/hljs-line-num.js +0 -1
  140. package/docs/scripts/third-party/hljs-original.js +0 -5171
  141. package/docs/scripts/third-party/hljs.js +0 -1
  142. package/docs/scripts/third-party/popper.js +0 -5
  143. package/docs/scripts/third-party/tippy.js +0 -1
  144. package/docs/scripts/third-party/tocbot.js +0 -672
  145. package/docs/scripts/third-party/tocbot.min.js +0 -1
  146. package/docs/styles/clean-jsdoc-theme-base.css +0 -975
  147. package/docs/styles/clean-jsdoc-theme-dark.css +0 -407
  148. package/docs/styles/clean-jsdoc-theme-light.css +0 -388
  149. package/docs/styles/clean-jsdoc-theme.min.css +0 -1
  150. package/test/helper-error.js +0 -25
  151. package/test/helper-pathResolve.js +0 -28
  152. /package/boot/{helper → class/bajo-core/method}/get-key-by-value.js +0 -0
  153. /package/boot/{helper → class/bajo-core/method}/is-empty-dir.js +0 -0
  154. /package/boot/{helper → class/bajo-core/method}/is-set.js +0 -0
  155. /package/boot/{helper → class/bajo-core/method}/is-valid-plugin.js +0 -0
  156. /package/boot/{helper → class/bajo-core/method}/paginate.js +0 -0
  157. /package/boot/{helper → class/bajo-core/method}/pascal-case.js +0 -0
  158. /package/boot/{helper → class/bajo-core/method}/pick.js +0 -0
  159. /package/boot/{helper → class/bajo-core/method}/resolve-path.js +0 -0
  160. /package/boot/{helper → class/bajo-core/method}/round.js +0 -0
  161. /package/boot/{helper → class/bajo-core/method}/sec-to-hms.js +0 -0
  162. /package/boot/{helper → class/bajo-core/method}/white-space.js +0 -0
@@ -0,0 +1,46 @@
1
+ import { filter, isArray, pullAt, camelCase, has, find, set, get, isFunction } from 'lodash-es'
2
+
3
+ async function buildCollections (options = {}) {
4
+ const { runHook, join } = this.app.bajo
5
+ let { ns, handler, dupChecks = [], container, useDefaultName } = options
6
+ useDefaultName = useDefaultName ?? true
7
+ if (!ns) ns = this.name
8
+ const cfg = this.app[ns].getConfig()
9
+ let items = get(cfg, container, [])
10
+ if (!isArray(items)) items = [items]
11
+ this.app[ns].log.trace('Collecting %s', this.app[ns].print.write(container))
12
+ await runHook(`${ns}:${camelCase('beforeBuildCollection')}`, container)
13
+ const deleted = []
14
+ for (const index in items) {
15
+ const item = items[index]
16
+ if (useDefaultName) {
17
+ if (!has(item, 'name')) {
18
+ if (find(items, { name: 'default' })) throw this.app[ns].error('Collection \'default\' already exists')
19
+ else item.name = 'default'
20
+ }
21
+ }
22
+ this.app[ns].log.trace('- %s', item.name)
23
+ const result = await handler.call(this.app[ns], { item, index, cfg })
24
+ if (result) items[index] = result
25
+ else if (result === false) deleted.push(index)
26
+ if (this.app.bajo.applet && item.skipOnTool && !deleted.includes(index)) deleted.push(index)
27
+ }
28
+ if (deleted.length > 0) pullAt(items, deleted)
29
+
30
+ // check for duplicity
31
+ for (const c of items) {
32
+ for (const d of dupChecks) {
33
+ if (isFunction(d)) await d.call(this.app[ns], c, items)
34
+ else {
35
+ const checker = set({}, d, c[d])
36
+ const match = filter(items, checker)
37
+ if (match.length > 1) this.app[ns].fatal('One or more %s shared the same \'%s\'', container, join(dupChecks.filter(i => !isFunction(i))))
38
+ }
39
+ }
40
+ }
41
+ await runHook(`${ns}:${camelCase('afterBuildCollection')}`, container)
42
+ this.app[ns].log.debug('%s collected: %d', this.app[ns].print.write(container), items.length)
43
+ return items
44
+ }
45
+
46
+ export default buildCollections
@@ -0,0 +1,29 @@
1
+ import { isString, isFunction, isPlainObject, find } from 'lodash-es'
2
+ import BajoPlugin from '../../bajo-plugin.js'
3
+
4
+ async function callHandler (item, ...args) {
5
+ let result
6
+ let scope = this
7
+ if (item instanceof BajoPlugin) {
8
+ scope = item
9
+ item = args.shift()
10
+ }
11
+ const bajo = scope.app.bajo
12
+ if (isString(item)) {
13
+ if (item.startsWith('applet:') && bajo.applets.length > 0) {
14
+ const [, ns, path] = item.split(':')
15
+ const applet = find(bajo.applets, a => (a.ns === ns || a.alias === ns))
16
+ if (applet) result = await bajo.runApplet(applet, path, ...args)
17
+ } else {
18
+ const method = bajo.getMethod(item)
19
+ if (method) result = await method(...args)
20
+ }
21
+ } else if (isFunction(item)) {
22
+ result = await item.call(scope, ...args)
23
+ } else if (isPlainObject(item) && item.handler) {
24
+ result = await item.handler.call(scope, ...args)
25
+ }
26
+ return result
27
+ }
28
+
29
+ export default callHandler
@@ -1,5 +1,5 @@
1
1
  import { mergeWith, isArray } from 'lodash-es'
2
- // taken from https://github.com/nodeutils/defaults-deep/blob/master/lib/index.js
2
+ // based on https://github.com/nodeutils/defaults-deep/blob/master/lib/index.js
3
3
 
4
4
  const defaultsDeep = (...args) => {
5
5
  const output = {}
@@ -0,0 +1,55 @@
1
+ import { camelCase, isString, omit, cloneDeep } from 'lodash-es'
2
+ import fastGlob from 'fast-glob'
3
+ import path from 'path'
4
+
5
+ async function eachPlugins (handler, options = {}) {
6
+ if (typeof options === 'string') options = { glob: options }
7
+ const result = {}
8
+ const pluginPkgs = cloneDeep(this.app.bajo.pluginPkgs) ?? []
9
+ const { glob, useBajo, prefix = '', noUnderscore = true, returnItems } = options
10
+ if (useBajo) pluginPkgs.unshift('bajo')
11
+ for (const pkgName of pluginPkgs) {
12
+ const ns = camelCase(pkgName)
13
+ const config = this.app[ns].config
14
+ const alias = this.app[ns].alias
15
+ let r
16
+ if (glob) {
17
+ const base = prefix === '' ? this.app[ns].dir.pkg : `${this.app[ns].dir.pkg}/${prefix}`
18
+ let opts = isString(glob) ? { pattern: [glob] } : glob
19
+ let pattern = opts.pattern ?? []
20
+ if (isString(pattern)) pattern = [pattern]
21
+ opts = omit(opts, ['pattern'])
22
+ for (const i in pattern) {
23
+ if (!path.isAbsolute(pattern[i])) pattern[i] = `${base}/${pattern[i]}`
24
+ }
25
+ const files = await fastGlob(pattern, opts)
26
+ for (const f of files) {
27
+ if (path.basename(f)[0] === '_' && noUnderscore) continue
28
+ const resp = await handler.call(this.app[ns], { ns, pkgName, config, alias, file: f, dir: base })
29
+ if (resp === false) break
30
+ else if (resp === undefined) continue
31
+ else {
32
+ result[ns] = result[ns] ?? {}
33
+ result[ns][f] = resp
34
+ }
35
+ }
36
+ } else {
37
+ r = await handler.call(this.app[ns], { ns, pkgName, config, dir: this.app[ns].dir.pkg, alias })
38
+ if (r === false) break
39
+ else if (r === undefined) continue
40
+ else result[ns] = r
41
+ }
42
+ }
43
+ if (returnItems) {
44
+ const data = []
45
+ for (const r in result) {
46
+ for (const f in result[r]) {
47
+ data.push(result[r][f])
48
+ }
49
+ }
50
+ return data
51
+ }
52
+ return result
53
+ }
54
+
55
+ export default eachPlugins
@@ -0,0 +1,7 @@
1
+ const envs = {
2
+ dev: 'development',
3
+ staging: 'Staging',
4
+ prod: 'production'
5
+ }
6
+
7
+ export default envs
@@ -2,9 +2,13 @@ import { customAlphabet } from 'nanoid'
2
2
 
3
3
  const generateId = (options = {}) => {
4
4
  let type
5
+ if (options === true) options = 'alpha'
5
6
  if (options === 'int') {
6
7
  type = options
7
8
  options = { pattern: '0123456789', length: 15 }
9
+ } else if (options === 'alpha') {
10
+ type = options
11
+ options = { pattern: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', length: 15 }
8
12
  }
9
13
  let { pattern, length = 13, returnInstance } = options
10
14
  pattern = pattern ?? 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
@@ -1,16 +1,15 @@
1
1
  import globalModulesPath from 'global-modules-path'
2
2
  import resolvePath from './resolve-path.js'
3
- import error from './error.js'
4
3
  import { dropRight } from 'lodash-es'
5
4
  import fs from 'fs-extra'
6
5
 
7
- const getGlobalModuleDir = (pkgName, silent = true) => {
6
+ function getGlobalModuleDir (pkgName, silent = true) {
8
7
  let nodeModulesDir = process.env.BAJO_GLOBAL_MODULE_DIR
9
8
  if (!nodeModulesDir) {
10
9
  const npmPath = globalModulesPath.getPath('npm')
11
10
  if (!npmPath) {
12
11
  if (silent) return
13
- throw error('Can\'t locate npm global module directory', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
12
+ throw this.error('Can\'t locate npm global module directory', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
14
13
  }
15
14
  nodeModulesDir = dropRight(resolvePath(npmPath).split('/'), 1).join('/')
16
15
  process.env.BAJO_GLOBAL_MODULE_DIR = nodeModulesDir
@@ -19,7 +18,7 @@ const getGlobalModuleDir = (pkgName, silent = true) => {
19
18
  const dir = `${nodeModulesDir}/${pkgName}`
20
19
  if (!fs.existsSync(dir)) {
21
20
  if (silent) return
22
- throw error('Can\'t locate \'%s\' global module directory', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
21
+ throw this.error('Can\'t locate \'%s\' global module directory', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
23
22
  }
24
23
  return dir
25
24
  }
@@ -0,0 +1,10 @@
1
+ import { get, isFunction } from 'lodash-es'
2
+
3
+ function getMethod (name = '', thrown = true) {
4
+ const { ns, path } = this.breakNsPath(name)
5
+ const method = get(this.app, `${ns}.${path}`)
6
+ if (method && isFunction(method)) return method
7
+ if (thrown) throw this.error('Can\'t find method named \'%s\'', name)
8
+ }
9
+
10
+ export default getMethod
@@ -1,6 +1,5 @@
1
1
  import path from 'path'
2
2
  import fs from 'fs-extra'
3
- import { get } from 'lodash-es'
4
3
  import getGlobalModuleDir from './get-global-module-dir.js'
5
4
  import resolvePath from './resolve-path.js'
6
5
  import { createRequire } from 'module'
@@ -19,9 +18,9 @@ function findDeep (item, paths) {
19
18
  }
20
19
 
21
20
  function getModuleDir (pkgName, base) {
22
- if (pkgName === 'app') return resolvePath(process.env.BAJOCWD)
23
- if (base === 'app') base = process.env.BAJOCWD
24
- else if (this && this[base]) base = get(this[base], 'config.pkg.name')
21
+ if (pkgName === 'main') return resolvePath(process.env.BAJOCWD)
22
+ if (base === 'main') base = process.env.BAJOCWD
23
+ else if (this && this.app && this.app[base]) base = this.app[base].pkgName
25
24
  const pkgPath = pkgName + '/package.json'
26
25
  const paths = require.resolve.paths(pkgPath)
27
26
  const gdir = getGlobalModuleDir()
@@ -1,10 +1,9 @@
1
1
  import fs from 'fs-extra'
2
2
 
3
3
  function getPluginDataDir (name, ensureDir = true) {
4
- const { getPlugin, getConfig } = this.bajo.helper
4
+ const { getPlugin } = this.app.bajo
5
5
  const plugin = getPlugin(name)
6
- const cfg = getConfig()
7
- const dir = `${cfg.dir.data}/plugins/${plugin.config.name}`
6
+ const dir = `${this.app.bajo.dir.data}/plugins/${plugin.name}`
8
7
  if (ensureDir) fs.ensureDirSync(dir)
9
8
  return dir
10
9
  }
@@ -0,0 +1,18 @@
1
+ import breakNsPath from './break-ns-path.js'
2
+ import currentLoc from '../../../lib/current-loc.js'
3
+ import { trim } from 'lodash-es'
4
+
5
+ function getPluginFile (file) {
6
+ if (file[0] === '.') file = `${currentLoc(import.meta).dir}/${trim(file.slice(1), '/')}`
7
+ if (!this) return file
8
+ if (file.includes(':')) {
9
+ if (file.slice(1, 2) === ':') return file // windows fs
10
+ const { ns, path } = breakNsPath.call(this, file)
11
+ if (ns !== 'file' && this && this.app && this.app[ns] && ns.length > 1) {
12
+ file = `${this.app[ns].dir.pkg}${path}`
13
+ }
14
+ }
15
+ return file
16
+ }
17
+
18
+ export default getPluginFile
@@ -0,0 +1,23 @@
1
+ import BajoPlugin from '../../bajo-plugin.js'
2
+
3
+ function getPlugin (name, silent) {
4
+ if (!this.app[name]) {
5
+ // alias?
6
+ let plugin
7
+ for (const key in this.app) {
8
+ const item = this.app[key]
9
+ if (item instanceof BajoPlugin && (item.alias === name || item.pkgName === name)) {
10
+ plugin = item
11
+ break
12
+ }
13
+ }
14
+ if (!plugin) {
15
+ if (silent) return false
16
+ throw this.error('Plugin with alias \'%s\' is not loaded', name)
17
+ }
18
+ name = plugin.name
19
+ }
20
+ return this.app[name]
21
+ }
22
+
23
+ export default getPlugin
@@ -1,10 +1,9 @@
1
1
  import resolvePath from './resolve-path.js'
2
2
  import getPluginFile from './get-plugin-file.js'
3
3
  import { isFunction, isPlainObject } from 'lodash-es'
4
- import error from './error.js'
5
4
  import fs from 'fs-extra'
6
5
 
7
- async function load (file, asDefaultImport = true, noCache = true) {
6
+ async function load (file, asDefaultImport = true, noCache = false) {
8
7
  file = resolvePath(file, true)
9
8
  if (noCache) file += `?_=${Date.now()}`
10
9
  const imported = await import(file)
@@ -13,18 +12,13 @@ async function load (file, asDefaultImport = true, noCache = true) {
13
12
  }
14
13
 
15
14
  async function importModule (file, { asDefaultImport, asHandler, noCache } = {}) {
16
- file = getPluginFile.call(this, file)
15
+ const me = this
16
+ file = getPluginFile.call(me, file)
17
17
  if (!fs.existsSync(file)) return
18
18
  let mod = await load(file, asDefaultImport, noCache)
19
19
  if (!asHandler) return mod
20
20
  if (isFunction(mod)) mod = { level: 999, handler: mod }
21
- if (!isPlainObject(mod)) throw error.call(this, 'File \'%s\' is NOT a handler module', file)
22
- if (mod.forceAsync && mod.handler.constructor.name !== 'AsyncFunction') {
23
- const oldHandler = mod.handler
24
- mod.handler = async function (...args) {
25
- oldHandler.call(this, ...args)
26
- }
27
- }
21
+ if (!isPlainObject(mod)) throw this.error.call(me.app, 'File \'%s\' is NOT a handler module', file)
28
22
  return mod
29
23
  }
30
24
 
@@ -10,13 +10,18 @@ import fs from 'fs-extra'
10
10
 
11
11
  async function importPkg (...pkgs) {
12
12
  const result = {}
13
- let opts = { returnDefault: true, thrownNotFound: false, noCache: false }
13
+ const notFound = []
14
+ let opts = { returnDefault: true, thrownNotFound: false }
14
15
  if (isPlainObject(last(pkgs))) {
15
16
  opts = defaultsDeep(pkgs.pop(), opts)
16
17
  }
17
18
  for (const pkg of pkgs) {
18
- const [plugin, name] = breakNsPath.call(this, pkg)
19
- const dir = getModuleDir.call(this, name, plugin)
19
+ const { ns, path: name } = breakNsPath.call(this, pkg)
20
+ const dir = getModuleDir.call(this, name, ns)
21
+ if (!dir) {
22
+ notFound.push(pkg)
23
+ continue
24
+ }
20
25
  const p = readJson(`${dir}/package.json`, opts.thrownNotFound)
21
26
  const mainFileOrg = dir + '/' + (p.main ?? get(p, 'exports.default', 'index.js'))
22
27
  let mainFile = resolvePath(mainFileOrg, os.platform() === 'win32')
@@ -32,6 +37,7 @@ async function importPkg (...pkgs) {
32
37
  }
33
38
  result[name] = mod
34
39
  }
40
+ if (notFound.length > 0) throw this.error('Can\'t find %s', this.join(notFound))
35
41
  if (pkgs.length === 1) return result[keys(result)[0]]
36
42
  if (opts.asObject) return result
37
43
  return values(result)
@@ -0,0 +1,13 @@
1
+ import { isString } from 'lodash-es'
2
+
3
+ function includes (matcher = [], array = []) {
4
+ if (isString(matcher)) matcher = [matcher]
5
+ let found = false
6
+ for (const m of matcher) {
7
+ found = array.includes(m)
8
+ if (found) break
9
+ }
10
+ return found
11
+ }
12
+
13
+ export default includes
@@ -0,0 +1,7 @@
1
+ function isClass (item) {
2
+ return typeof item === 'function' &&
3
+ Object.prototype.hasOwnProperty.call(item, 'prototype') &&
4
+ !Object.prototype.hasOwnProperty.call(item, 'arguments')
5
+ }
6
+
7
+ export default isClass
@@ -3,7 +3,7 @@ import { keys, indexOf } from 'lodash-es'
3
3
 
4
4
  function isLogInRange (level) {
5
5
  const levels = keys(logLevels)
6
- const logLevel = indexOf(levels, this.bajo.config.log.level)
6
+ const logLevel = indexOf(levels, this.app.bajo.config.log.level)
7
7
  return indexOf(levels, level) >= logLevel
8
8
  }
9
9
 
@@ -4,9 +4,9 @@ import resolvePath from './resolve-path.js'
4
4
  const isValidApp = (dir) => {
5
5
  if (!dir) dir = process.env.BAJOCWD
6
6
  dir = resolvePath(dir)
7
- const hasAppDir = fs.existsSync(`${dir}/app/bajo`)
7
+ const hasMainDir = fs.existsSync(`${dir}/main/bajo`)
8
8
  const hasPackageJson = fs.existsSync(`${dir}/package.json`)
9
- return hasAppDir && hasPackageJson
9
+ return hasMainDir && hasPackageJson
10
10
  }
11
11
 
12
12
  export default isValidApp
@@ -0,0 +1,15 @@
1
+ import { isPlainObject } from 'lodash-es'
2
+ import isSet from './is-set.js'
3
+
4
+ function join (array, sep) {
5
+ const isI18n = this && this.app && this.app.bajoI18N
6
+ if (array.length === 0) return isI18n ? this.app.bajoI18N.t('none') : 'none'
7
+ if (array.length === 1) return array[0]
8
+ if (isSet(sep) && !isPlainObject(sep)) return array.join(sep)
9
+ let { separator = ', ', joiner = 'and' } = sep ?? {}
10
+ if (isI18n && this.app.bajoI18N.t) joiner = this.app.bajoI18N.t(joiner)
11
+ const last = (array.pop() ?? '').trim()
12
+ return array.map(a => (a + '').trim()).join(separator) + ` ${joiner} ${last}`
13
+ }
14
+
15
+ export default join
@@ -0,0 +1,9 @@
1
+ export default {
2
+ trace: 10,
3
+ debug: 20,
4
+ info: 30,
5
+ warn: 40,
6
+ error: 50,
7
+ fatal: 60,
8
+ silent: 99
9
+ }
@@ -0,0 +1,9 @@
1
+ import { isEmpty } from 'lodash-es'
2
+
3
+ function numUnit (value = '', defUnit = '') {
4
+ const num = value.match(/\d+/g)
5
+ const unit = value.match(/[a-zA-Z]+/g)
6
+ return `${num[0]}${isEmpty(unit) ? defUnit : unit[0]}`
7
+ }
8
+
9
+ export default numUnit
@@ -1,8 +1,9 @@
1
- import { isPlainObject, isArray, isNumber, set, cloneDeep } from 'lodash-es'
1
+ import { isPlainObject, isArray, isNumber, set, cloneDeep, isString, omit } from 'lodash-es'
2
2
  import dotenvParseVariables from 'dotenv-parse-variables'
3
3
  import ms from 'ms'
4
- import dayjs from '../lib/dayjs.js'
4
+ import dayjs from '../../../lib/dayjs.js'
5
5
  import isSet from './is-set.js'
6
+ import translate from '../../../lib/translate.js'
6
7
 
7
8
  const statics = ['*']
8
9
 
@@ -12,13 +13,15 @@ function parseDur (val) {
12
13
 
13
14
  function parseDt (val) {
14
15
  const dt = dayjs(val)
15
- if (!dt.isValid()) throw Error(`Unparsed date/time '${val}'`)
16
+ if (!dt.isValid()) throw this.error('Unparsed date/time \'%s\'', val)
16
17
  return dt.toDate()
17
18
  }
18
19
 
19
- function parseObject (input, silent = true, parseValue = false) {
20
- const obj = cloneDeep(input)
20
+ function parseObject (input, { silent = true, parseValue = false, i18n, ns } = {}) {
21
+ let obj = cloneDeep(input)
21
22
  const keys = Object.keys(obj)
23
+ const me = this
24
+ const mutated = []
22
25
  keys.forEach(k => {
23
26
  const v = obj[k]
24
27
  if (isPlainObject(v)) obj[k] = parseObject(v)
@@ -32,18 +35,31 @@ function parseObject (input, silent = true, parseValue = false) {
32
35
  } else if (isSet(v)) {
33
36
  try {
34
37
  if (statics.includes(v)) obj[k] = v
35
- else if (parseValue) {
38
+ else if (k.startsWith('t:') && isString(v)) {
39
+ const newK = k.slice(2)
40
+ if (i18n) {
41
+ const scope = ns ? me.app[ns] : me
42
+ let [text, ...args] = v.split('|')
43
+ args = args.map(a => {
44
+ if (a.slice(0, 2) === 't:') a = translate.call(scope, i18n, a.slice(2))
45
+ return a
46
+ })
47
+ obj[newK] = translate.call(scope, i18n, text, ...args)
48
+ } else obj[newK] = v
49
+ mutated.push(k)
50
+ } else if (parseValue) {
36
51
  obj[k] = dotenvParseVariables(set({}, 'item', v), { assignToProcessEnv: false }).item
37
52
  if (isArray(obj[k])) obj[k] = obj[k].map(item => typeof item === 'string' ? item.trim() : item)
38
53
  }
39
- if (k.slice(-3) === 'Dur') obj[k] = parseDur(v)
40
- if (k.slice(-2) === 'Dt') obj[k] = parseDt(v)
54
+ if (k.slice(-3) === 'Dur') obj[k] = parseDur.call(me, v)
55
+ if (k.slice(-2) === 'Dt') obj[k] = parseDt.call(me, v)
41
56
  } catch (err) {
42
57
  obj[k] = undefined
43
58
  if (!silent) throw err
44
59
  }
45
60
  }
46
61
  })
62
+ if (mutated.length > 0) obj = omit(obj, mutated)
47
63
  return obj
48
64
  }
49
65
 
@@ -0,0 +1,48 @@
1
+ import path from 'path'
2
+ import resolvePath from './resolve-path.js'
3
+ import getPluginFile from './get-plugin-file.js'
4
+ import readJson from './read-json.js'
5
+ import parseObject from './parse-object.js'
6
+ import { find, map, isEmpty } from 'lodash-es'
7
+ import fg from 'fast-glob'
8
+
9
+ async function readConfig (file, { ns, pattern, globOptions = {}, ignoreError, defValue = {}, opts = {} } = {}) {
10
+ if (!ns) ns = this.name
11
+ file = resolvePath(getPluginFile.call(this, file))
12
+ let ext = path.extname(file)
13
+ const fname = path.dirname(file) + '/' + path.basename(file, ext)
14
+ ext = ext.toLowerCase()
15
+ if (['.mjs', '.js'].includes(ext)) {
16
+ const { readHandler } = find(this.app.bajo.configHandlers, { ext })
17
+ return parseObject(await readHandler.call(this.app[ns], file, opts))
18
+ }
19
+ if (ext === '.json') return await readJson(file)
20
+ if (!['', '.*'].includes(ext)) {
21
+ const item = find(this.app.bajo.configHandlers, { ext })
22
+ if (!item) {
23
+ if (!ignoreError) throw this.error('Can\'t parse \'%s\'', file, { code: 'BAJO_CONFIG_NO_PARSER' })
24
+ return parseObject(defValue)
25
+ }
26
+ return parseObject(await item.readHandler.call(this.app[ns], file, opts))
27
+ }
28
+ const item = pattern ?? `${fname}.{${map(map(this.app.bajo.configHandlers, 'ext'), k => k.slice(1)).join(',')}}`
29
+ const files = await fg(item, globOptions)
30
+ if (files.length === 0) {
31
+ if (!ignoreError) throw this.error('No config file found', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
32
+ return parseObject(defValue)
33
+ }
34
+ let config = defValue
35
+ for (const f of files) {
36
+ const ext = path.extname(f).toLowerCase()
37
+ const item = find(this.app.bajo.configHandlers, { ext })
38
+ if (!item) {
39
+ if (!ignoreError) throw this.error('Can\'t parse \'%s\'', f, { code: 'BAJO_CONFIG_NO_PARSER' })
40
+ continue
41
+ }
42
+ config = await item.readHandler.call(this.app[ns], f, opts)
43
+ if (!isEmpty(config)) break
44
+ }
45
+ return parseObject(config)
46
+ }
47
+
48
+ export default readConfig
@@ -2,8 +2,8 @@ import fs from 'fs-extra'
2
2
  import { isEmpty } from 'lodash-es'
3
3
  import parseObject from './parse-object.js'
4
4
 
5
- const readJson = (file, thrownNotFound) => {
6
- if (!fs.existsSync(file) && thrownNotFound) throw new Error('File \'%s\' not found', file)
5
+ function readJson (file, thrownNotFound) {
6
+ if (!fs.existsSync(file) && thrownNotFound) throw this.error('File \'%s\' not found', file)
7
7
  let resp = fs.readFileSync(file, 'utf8')
8
8
  if (isEmpty(resp)) resp = '{}'
9
9
  return parseObject(JSON.parse(resp))
@@ -0,0 +1,26 @@
1
+ import { filter, isEmpty, orderBy, pullAt } from 'lodash-es'
2
+
3
+ async function runHook (hookName, ...args) {
4
+ const [ns, path] = (hookName ?? '').split(':')
5
+ let fns = filter(this.app.bajo.hooks, { ns, path })
6
+ if (isEmpty(fns)) return
7
+ fns = orderBy(fns, ['level'])
8
+ const results = []
9
+ const removed = []
10
+ for (const i in fns) {
11
+ const fn = fns[i]
12
+ const scope = this.app[fn.src]
13
+ const res = await fn.handler.call(scope, ...args)
14
+ results.push({
15
+ hook: hookName,
16
+ resp: res
17
+ })
18
+ if (path.startsWith('once')) removed.push(i)
19
+ if (this.config.log.traceHook) scope.log.trace('Hook \'%s\' executed', hookName)
20
+ }
21
+ if (removed.length > 0) pullAt(this.app.bajo.hooks, removed)
22
+
23
+ return results
24
+ }
25
+
26
+ export default runHook
@@ -4,8 +4,8 @@ import { trim } from 'lodash-es'
4
4
  import increment from 'add-filename-increment'
5
5
 
6
6
  async function saveAsDownload (file, obj, printSaved = true) {
7
- const { print, getPluginName, getPluginDataDir } = this.bajo.helper
8
- const plugin = getPluginName(4)
7
+ const { print, getPluginDataDir } = this.app.bajo
8
+ const plugin = this.name
9
9
  const fname = increment(`${getPluginDataDir(plugin)}/${trim(file, '/')}`, { fs: true })
10
10
  const dir = path.dirname(fname)
11
11
  if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
@@ -0,0 +1,13 @@
1
+ function sliceString (content, start, end) {
2
+ const idx1 = content.indexOf(start)
3
+ if (idx1 === -1) return false
4
+ let idx2 = content.indexOf(end)
5
+ if (idx2 === -1) return false
6
+ if (idx2 < idx1) {
7
+ const tmp = content.slice(idx1)
8
+ idx2 = tmp.indexOf(end) + idx1
9
+ }
10
+ return content.slice(idx1, idx2 + end.length)
11
+ }
12
+
13
+ export default sliceString
@@ -0,0 +1,23 @@
1
+ import { words, upperFirst, map, concat, uniq, forOwn } from 'lodash-es'
2
+ import generateId from './generate-id.js'
3
+
4
+ const defIgnores = ['or', 'and', 'of', 'with']
5
+
6
+ const titleize = (text, { ignores = [], replacement = {} } = {}) => {
7
+ const replacer = {}
8
+ forOwn(replacement, (v, k) => {
9
+ const id = generateId('int')
10
+ replacer[id] = k
11
+ text = text.replace(k, ` ${id} `)
12
+ })
13
+ return map(words(text), t => {
14
+ forOwn(replacer, (v, k) => {
15
+ if (k === t) t = replacement[replacer[k]]
16
+ })
17
+ ignores = uniq(concat(ignores, defIgnores))
18
+ if (ignores.includes(t)) return t
19
+ return upperFirst(t)
20
+ }).join(' ')
21
+ }
22
+
23
+ export default titleize