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.
Files changed (160) hide show
  1. package/.jsdoc.conf.json +38 -0
  2. package/README.md +57 -3
  3. package/bajoBook/book/doc/.metadata.json +28 -0
  4. package/bajoBook/book/doc/How-to-Make-a-Paper-Boat-564x400@2x.jpg +0 -0
  5. package/bajoBook/book/doc/pages/guides/definition.md +7 -0
  6. package/bajoBook/book/doc/pages/guides/intro.md +3 -0
  7. package/bajoBook/book/doc/pages/guides/setup.md +22 -0
  8. package/bajoBook/book/reference/.metadata.json +152 -0
  9. package/bajoBook/book/reference/concept-leadership-business-with-paper-boats.jpg +0 -0
  10. package/bajoBook/book/reference/pages/configuration/configuration-file.md +52 -0
  11. package/bajoBook/book/reference/pages/helper/break-ns-path.md +24 -0
  12. package/bajoBook/book/reference/pages/helper/build-collections.md +19 -0
  13. package/bajoBook/book/reference/pages/helper/call-helper-or-handler.md +35 -0
  14. package/bajoBook/book/reference/pages/helper/current-loc.md +28 -0
  15. package/bajoBook/book/reference/pages/helper/dayjs.md +13 -0
  16. package/bajoBook/book/reference/pages/helper/defaults-deep.md +29 -0
  17. package/bajoBook/book/reference/pages/helper/dump.md +32 -0
  18. package/bajoBook/book/reference/pages/helper/each-plugins.md +24 -0
  19. package/bajoBook/book/reference/pages/helper/envs.md +11 -0
  20. package/bajoBook/book/reference/pages/helper/error.md +29 -0
  21. package/bajoBook/book/reference/pages/helper/fatal.md +18 -0
  22. package/bajoBook/book/reference/pages/helper/freeze.md +13 -0
  23. package/bajoBook/book/reference/pages/helper/generate-id.md +36 -0
  24. package/bajoBook/book/reference/pages/helper/get-config.md +27 -0
  25. package/bajoBook/book/reference/pages/helper/get-global-module-dir.md +13 -0
  26. package/bajoBook/book/reference/pages/helper/get-helper.md +13 -0
  27. package/bajoBook/book/reference/pages/helper/get-item-by-name.md +13 -0
  28. package/bajoBook/book/reference/pages/helper/get-key-by-value.md +13 -0
  29. package/bajoBook/book/reference/pages/helper/get-module-dir.md +13 -0
  30. package/bajoBook/book/reference/pages/helper/get-plugin-data-dir.md +13 -0
  31. package/bajoBook/book/reference/pages/helper/get-plugin-name.md +13 -0
  32. package/bajoBook/book/reference/pages/helper/get-plugin.md +13 -0
  33. package/bajoBook/book/reference/pages/helper/import-module.md +13 -0
  34. package/bajoBook/book/reference/pages/helper/import-pkg.md +13 -0
  35. package/bajoBook/book/reference/pages/helper/is-empty-dir.md +13 -0
  36. package/bajoBook/book/reference/pages/helper/is-log-in-range.md +13 -0
  37. package/bajoBook/book/reference/pages/helper/is-set.md +13 -0
  38. package/bajoBook/book/reference/pages/helper/is-valid-app.md +13 -0
  39. package/bajoBook/book/reference/pages/helper/is-valid-plugin.md +13 -0
  40. package/bajoBook/book/reference/pages/helper/log-levels.md +13 -0
  41. package/bajoBook/book/reference/pages/helper/log.md +13 -0
  42. package/bajoBook/book/reference/pages/helper/paginate.md +13 -0
  43. package/bajoBook/book/reference/pages/helper/pascal-case.md +13 -0
  44. package/bajoBook/book/reference/pages/helper/print.md +13 -0
  45. package/bajoBook/book/reference/pages/helper/read-config.md +13 -0
  46. package/bajoBook/book/reference/pages/helper/read-json.md +13 -0
  47. package/bajoBook/book/reference/pages/helper/resolve-path.md +13 -0
  48. package/bajoBook/book/reference/pages/helper/resolve-tpl-path.md +13 -0
  49. package/bajoBook/book/reference/pages/helper/run-hook.md +13 -0
  50. package/bajoBook/book/reference/pages/helper/save-as-download.md +13 -0
  51. package/bajoBook/book/reference/pages/helper/titleize.md +13 -0
  52. package/bajoBook/book/reference/pages/helper/white-space.md +13 -0
  53. package/boot/attach-helper.js +34 -0
  54. package/boot/boot-order.js +34 -0
  55. package/boot/build-config.js +99 -0
  56. package/boot/create-scope.js +36 -0
  57. package/boot/exit-handler.js +60 -0
  58. package/boot/helper/break-ns-path.js +17 -0
  59. package/boot/helper/build-collections.js +34 -0
  60. package/boot/helper/call-helper-or-handler.js +15 -0
  61. package/boot/helper/current-loc.js +11 -0
  62. package/boot/helper/defaults-deep.js +14 -0
  63. package/boot/helper/dump.js +10 -0
  64. package/boot/helper/each-plugins.js +104 -0
  65. package/boot/helper/envs.js +14 -0
  66. package/boot/helper/error.js +67 -0
  67. package/boot/helper/fatal.js +12 -0
  68. package/boot/helper/generate-id.js +20 -0
  69. package/boot/helper/get-config.js +19 -0
  70. package/boot/helper/get-global-module-dir.js +27 -0
  71. package/boot/helper/get-helper.js +12 -0
  72. package/boot/helper/get-item-by-name.js +26 -0
  73. package/boot/helper/get-key-by-value.js +5 -0
  74. package/boot/helper/get-module-dir.js +22 -0
  75. package/boot/helper/get-plugin-data-dir.js +12 -0
  76. package/boot/helper/get-plugin-name.js +39 -0
  77. package/boot/helper/get-plugin.js +14 -0
  78. package/boot/helper/import-module.js +25 -0
  79. package/boot/helper/import-pkg.js +67 -0
  80. package/boot/helper/is-empty-dir.js +9 -0
  81. package/boot/helper/is-log-in-range.js +10 -0
  82. package/boot/helper/is-set.js +5 -0
  83. package/boot/helper/is-valid-app.js +12 -0
  84. package/boot/helper/is-valid-plugin.js +12 -0
  85. package/boot/helper/log-levels.js +19 -0
  86. package/boot/helper/paginate.js +26 -0
  87. package/boot/helper/pascal-case.js +7 -0
  88. package/boot/helper/print.js +99 -0
  89. package/boot/helper/read-config.js +46 -0
  90. package/boot/helper/read-json.js +10 -0
  91. package/boot/helper/resolve-path.js +15 -0
  92. package/boot/helper/resolve-tpl-path.js +15 -0
  93. package/boot/helper/run-hook.js +46 -0
  94. package/boot/helper/save-as-download.js +17 -0
  95. package/boot/helper/titleize.js +14 -0
  96. package/boot/helper/white-space.js +3 -0
  97. package/boot/index.js +60 -0
  98. package/boot/lib/bora.js +97 -0
  99. package/boot/lib/build-helper.js +57 -0
  100. package/boot/lib/logger.js +75 -0
  101. package/boot/lib/omitted-plugin-keys.js +3 -0
  102. package/boot/lib/parse-args-argv.js +75 -0
  103. package/boot/lib/parse-env.js +36 -0
  104. package/boot/lib/shim.js +14 -0
  105. package/boot/plugins/attach-helper.js +20 -0
  106. package/boot/plugins/build-config.js +82 -0
  107. package/boot/plugins/check-clash.js +18 -0
  108. package/boot/plugins/check-dependency.js +37 -0
  109. package/boot/plugins/collect-config-handlers.js +25 -0
  110. package/boot/plugins/collect-exit-handlers.js +23 -0
  111. package/boot/plugins/collect-hooks.js +34 -0
  112. package/boot/plugins/extend-config.js +21 -0
  113. package/boot/plugins/index.js +28 -0
  114. package/boot/plugins/run.js +31 -0
  115. package/boot/run-tool.js +34 -0
  116. package/docs/boot_build-config.js.html +75 -0
  117. package/docs/boot_create-scope.js.html +25 -0
  118. package/docs/boot_index.js.html +43 -0
  119. package/docs/data/search.json +1 -0
  120. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  121. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  122. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  123. package/docs/helper_emit.js.html +18 -0
  124. package/docs/helper_envs.js.html +16 -0
  125. package/docs/helper_error.js.html +25 -0
  126. package/docs/helper_get-bajo.js.html +42 -0
  127. package/docs/helper_index.js.html +39 -0
  128. package/docs/helper_log-levels.js.html +20 -0
  129. package/docs/helper_set-hook.js.html +38 -0
  130. package/docs/helper_walk-bajos.js.html +51 -0
  131. package/docs/index.html +16 -0
  132. package/docs/module-boot.html +3 -0
  133. package/docs/module-boot_buildConfig.html +3 -0
  134. package/docs/module-boot_createScope.html +3 -0
  135. package/docs/module-helper.html +7 -0
  136. package/docs/module-helper_setHook.html +4 -0
  137. package/docs/module-helper_walkBajos.html +6 -0
  138. package/docs/scripts/core.js +655 -0
  139. package/docs/scripts/core.min.js +23 -0
  140. package/docs/scripts/resize.js +90 -0
  141. package/docs/scripts/search.js +265 -0
  142. package/docs/scripts/search.min.js +6 -0
  143. package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
  144. package/docs/scripts/third-party/fuse.js +9 -0
  145. package/docs/scripts/third-party/hljs-line-num-original.js +369 -0
  146. package/docs/scripts/third-party/hljs-line-num.js +1 -0
  147. package/docs/scripts/third-party/hljs-original.js +5171 -0
  148. package/docs/scripts/third-party/hljs.js +1 -0
  149. package/docs/scripts/third-party/popper.js +5 -0
  150. package/docs/scripts/third-party/tippy.js +1 -0
  151. package/docs/scripts/third-party/tocbot.js +672 -0
  152. package/docs/scripts/third-party/tocbot.min.js +1 -0
  153. package/docs/styles/clean-jsdoc-theme-base.css +975 -0
  154. package/docs/styles/clean-jsdoc-theme-dark.css +407 -0
  155. package/docs/styles/clean-jsdoc-theme-light.css +388 -0
  156. package/docs/styles/clean-jsdoc-theme.min.css +1 -0
  157. package/package.json +36 -4
  158. package/test/helper-error.js +25 -0
  159. package/test/helper-isSet.js +41 -0
  160. package/test/helper-pathResolve.js +28 -0
@@ -0,0 +1,9 @@
1
+ import emptyDir from 'empty-dir'
2
+ import fs from 'fs-extra'
3
+
4
+ const isEmptyDir = async (dir) => {
5
+ await fs.exists(dir)
6
+ return await emptyDir(dir)
7
+ }
8
+
9
+ export default isEmptyDir
@@ -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,5 @@
1
+ const isSet = (input) => {
2
+ return ![null, undefined].includes(input)
3
+ }
4
+
5
+ export default isSet
@@ -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,7 @@
1
+ import { camelCase, upperFirst } from 'lodash-es'
2
+
3
+ const pascalCase = (text) => {
4
+ return upperFirst(camelCase(text))
5
+ }
6
+
7
+ export default pascalCase
@@ -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,10 @@
1
+ import fs from 'fs-extra'
2
+ import { isEmpty } from 'lodash-es'
3
+
4
+ const readJson = (file) => {
5
+ let resp = fs.readFileSync(file, 'utf8')
6
+ if (isEmpty(resp)) resp = '{}'
7
+ return JSON.parse(resp)
8
+ }
9
+
10
+ export default readJson
@@ -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
@@ -0,0 +1,3 @@
1
+ const whiteSpace = [' ', '\t', '\n', '\r']
2
+
3
+ export default whiteSpace
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
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ const omittedPluginKeys = ['name', 'dir', 'alias', 'pkg', 'dependencies']
2
+
3
+ export default omittedPluginKeys