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,60 @@
1
+ async function exit (signal) {
2
+ const { eachPlugins, log } = this.bajo.helper
3
+ log.warn('\'%s\' signal received', signal)
4
+ await eachPlugins(async function ({ plugin }) {
5
+ const handler = this.bajo.exitHandler[plugin]
6
+ if (!handler) return undefined
7
+ await handler.call(this)
8
+ log.debug('Exited: %s', plugin)
9
+ })
10
+ log.debug('Program shutdown')
11
+ process.exit(0)
12
+ }
13
+
14
+ async function exitHandler () {
15
+ const { log, getConfig } = this.bajo.helper
16
+ const config = getConfig()
17
+ if (!config.exitHandler) return
18
+
19
+ log.debug('Exit handlings')
20
+
21
+ process.on('SIGINT', async () => {
22
+ await exit.call(this, 'SIGINT')
23
+ })
24
+
25
+ process.on('SIGTERM', async () => {
26
+ await exit.call(this, 'SIGTERM')
27
+ })
28
+
29
+ process.on('uncaughtException', (error, origin) => {
30
+ const { getConfig } = this.bajo.helper
31
+ const config = getConfig()
32
+ if (config.log.report.includes('sys:uncaughtException')) log.fatal({ origin }, '%s', error.message)
33
+ setTimeout(() => {
34
+ console.error(error)
35
+ process.exit(1)
36
+ }, 50)
37
+ })
38
+
39
+ process.on('unhandledRejection', (reason, promise) => {
40
+ const stackFile = reason.stack.split('\n')[1]
41
+ let file
42
+ const info = stackFile.match(/\((.*)\)/) // file is in (<file>)
43
+ if (info) file = info[1]
44
+ else if (stackFile.startsWith(' at ')) file = stackFile.slice(7) // file is stackFile itself
45
+ if (!file) return
46
+ const parts = file.split(':')
47
+ const column = parseInt(parts[parts.length - 1])
48
+ const line = parseInt(parts[parts.length - 2])
49
+ parts.pop()
50
+ parts.pop()
51
+ file = parts.join(':')
52
+ log.error({ file, line, column }, '%s', reason.message)
53
+ })
54
+
55
+ process.on('warning', warning => {
56
+ log.error('%s', warning.message)
57
+ })
58
+ }
59
+
60
+ export default exitHandler
@@ -0,0 +1,17 @@
1
+ import { isEmpty } from 'lodash-es'
2
+
3
+ function breakNsPath (item = '') {
4
+ const { error, getPlugin } = this.bajo.helper
5
+ let [ns, ...path] = item.split(':')
6
+ path = path.join(':')
7
+ if (isEmpty(path)) {
8
+ path = ns
9
+ ns = null
10
+ }
11
+ // if (path.startsWith('.')) throw error('Path \'%s\' must be an absolute path', path)
12
+ if (!this[ns]) ns = (getPlugin(ns) || {}).name
13
+ if (!this[ns]) throw error('Unknown plugin \'%s\' or plugin isn\'t loaded yet', ns)
14
+ return [ns, path]
15
+ }
16
+
17
+ export default breakNsPath
@@ -0,0 +1,34 @@
1
+ import { filter, isArray, each, pullAt, camelCase } from 'lodash-es'
2
+
3
+ async function buildCollections (options = {}) {
4
+ const { getConfig, getPluginName, fatal, runHook } = this.bajo.helper
5
+ let { plugin, handler, dupChecks = [], container = 'connections' } = options
6
+ if (!plugin) plugin = getPluginName(4)
7
+ const cfg = getConfig(plugin, { full: true })
8
+ if (!cfg[container]) return []
9
+ if (!isArray(cfg[container])) cfg[container] = [cfg[container]]
10
+ cfg[container] = cfg[container] ?? []
11
+ await runHook(`${plugin}:${camelCase(`before build ${container}`)}`)
12
+ const deleted = []
13
+ for (const index in cfg[container]) {
14
+ const item = cfg[container][index]
15
+ const result = await handler.call(this, { item, index, cfg })
16
+ if (result) cfg[container][index] = result
17
+ else if (result === false) deleted.push(index)
18
+ }
19
+ if (deleted.length > 0) pullAt(cfg[container], deleted)
20
+
21
+ // check for duplicity
22
+ each(cfg[container], c => {
23
+ const checker = {}
24
+ each(dupChecks, d => {
25
+ checker[d] = c[d]
26
+ })
27
+ const match = filter(cfg[container], checker)
28
+ if (match.length > 1) fatal('One or more %s shared the same \'%s\'', container, dupChecks.join(', '), { code: 'BAJOMQTT_CONNECTION_NOT_UNIQUE' })
29
+ })
30
+ await runHook(`${plugin}:${camelCase(`after build ${container}`)}`)
31
+ return cfg[container]
32
+ }
33
+
34
+ export default buildCollections
@@ -0,0 +1,15 @@
1
+ import { isString, isFunction } from 'lodash-es'
2
+ import getHelper from './get-helper.js'
3
+
4
+ async function callHelperOrHandler (nameOrFn, ...args) {
5
+ let result
6
+ if (isString(nameOrFn)) {
7
+ const helper = getHelper.call(this, nameOrFn)
8
+ if (isFunction(helper)) result = await helper(...args)
9
+ } else if (isFunction(nameOrFn)) {
10
+ result = await nameOrFn.call(this, ...args)
11
+ }
12
+ return result
13
+ }
14
+
15
+ export default callHelperOrHandler
@@ -0,0 +1,11 @@
1
+ import path from 'path'
2
+ import resolvePath from './resolve-path.js'
3
+ import { fileURLToPath } from 'url'
4
+
5
+ const currentLoc = (meta) => {
6
+ const file = resolvePath(fileURLToPath(meta.url))
7
+ const dir = path.dirname(file)
8
+ return { dir, file, __dirname: dir, __filename: file }
9
+ }
10
+
11
+ export default currentLoc
@@ -0,0 +1,14 @@
1
+ import { mergeWith, isArray } from 'lodash-es'
2
+ // taken from https://github.com/nodeutils/defaults-deep/blob/master/lib/index.js
3
+
4
+ const defaultsDeep = (...args) => {
5
+ const output = {}
6
+ args.reverse().forEach(function (item) {
7
+ mergeWith(output, item, function (objectValue, sourceValue) {
8
+ return isArray(sourceValue) ? sourceValue : undefined
9
+ })
10
+ })
11
+ return output
12
+ }
13
+
14
+ export default defaultsDeep
@@ -0,0 +1,10 @@
1
+ import util from 'util'
2
+
3
+ const dump = (...args) => {
4
+ for (const arg of args) {
5
+ const result = util.inspect(arg, false, null, true)
6
+ console.log(result)
7
+ }
8
+ }
9
+
10
+ export default dump
@@ -0,0 +1,104 @@
1
+ import { camelCase, isString, omit, trim } from 'lodash-es'
2
+ import fastGlob from 'fast-glob'
3
+ import path from 'path'
4
+ import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
5
+
6
+ async function _eachPlugins (handler, { key = 'name', glob, ns, useBajo } = {}) {
7
+ const { getConfig } = this.bajo.helper
8
+ const config = getConfig()
9
+ const result = {}
10
+ const plugins = [...config.plugins]
11
+ if (useBajo) plugins.unshift('bajo')
12
+ for (const pkg of plugins) {
13
+ const plugin = camelCase(pkg)
14
+ let cfg = getConfig(plugin, { full: true })
15
+ const { alias, dependencies } = cfg
16
+ const dir = cfg.dir.pkg
17
+ cfg = omit(cfg, omittedPluginKeys)
18
+ let r
19
+ if (glob) {
20
+ const base = `${dir}/${ns}`
21
+ let opts = isString(glob) ? { pattern: [glob] } : glob
22
+ let pattern = opts.pattern ?? []
23
+ if (isString(pattern)) pattern = [pattern]
24
+ opts = omit(opts, ['pattern'])
25
+ for (const i in pattern) {
26
+ pattern[i] = `${base}/${pattern[i]}`
27
+ }
28
+ const files = await fastGlob(pattern, opts)
29
+ for (const f of files) {
30
+ const resp = await handler.call(this, { plugin, pkg, cfg, alias, file: f, dir: base, dependencies })
31
+ if (resp === false) break
32
+ else if (resp === undefined) continue
33
+ else {
34
+ result[plugin] = result[plugin] ?? {}
35
+ result[plugin][f] = resp
36
+ }
37
+ }
38
+ } else {
39
+ r = await handler.call(this, { plugin, pkg, cfg, dir, alias, dependencies })
40
+ if (r === false) break
41
+ else if (r === undefined) continue
42
+ else result[plugin] = r
43
+ }
44
+ }
45
+ return result
46
+ }
47
+
48
+ /**
49
+ * @module helper/eachPlugins
50
+ */
51
+
52
+ /**
53
+ * Callback function that will be executed while walking through all Bajos
54
+ *
55
+ * @callback handlerFn
56
+ * @async
57
+ * @param {Object} argument - Provides information about current Bajo
58
+ * @param {string} argument.name - Bajo's name
59
+ * @param {string} argument.pkgName - Bajo's package name
60
+ * @param {Object} argument.cfg - Bajo's config object
61
+ * @returns {Object|boolean|undefined}
62
+ */
63
+
64
+ /**
65
+ * Walk through all plugins and execute the callback handler
66
+ *
67
+ * @instance
68
+ * @async
69
+ * @param {function} handlerFn - [The callback]{@link module:helper/eachPlugins~handlerFn}
70
+ * @param {Object} [options] - Optional parameter
71
+ * @param {string} [options.key=name] - Key of Bajo's config object that will be used as the key of returned object
72
+ * @returns {Object} Results from callback execution through all Bajos
73
+ *
74
+ * @example
75
+ * const { eachPlugins } = this.bajo.helper
76
+ * await eachPlugins(async function ({ name }) => {
77
+ * console.log(name)
78
+ * })
79
+ */
80
+
81
+ async function eachPlugins (handler, options = {}) {
82
+ const { getConfig, getPluginName } = this.bajo.helper
83
+ let { key = 'name', glob, ns, extend, extendHandler, useBajo } = options
84
+ if (!extendHandler) extendHandler = handler
85
+ ns = ns ?? getPluginName(4)
86
+ const result = await _eachPlugins.call(this, handler, { key, glob, ns, useBajo })
87
+ if (extend && isString(glob)) {
88
+ let nsExtend = ns
89
+ if (isString(extend)) nsExtend += '/' + trim(extend, '/')
90
+ const cfg = getConfig('app', { full: true })
91
+ const ext = `${cfg.dir.pkg}/${nsExtend}/extend/*`
92
+ const exts = await fastGlob(ext, { onlyDirectories: true })
93
+ for (const e of exts) {
94
+ const plugin = path.basename(e)
95
+ const files = await fastGlob(`${e}/${glob}`)
96
+ for (const file of files) {
97
+ await extendHandler.call(this, { file, plugin, dir: e })
98
+ }
99
+ }
100
+ }
101
+ return result // TODO: merge with extender
102
+ }
103
+
104
+ export default eachPlugins
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Supported environment
3
+ *
4
+ * @memberof module:helper
5
+ * @type Object
6
+ * @instance
7
+ */
8
+
9
+ const envs = {
10
+ dev: 'development',
11
+ prod: 'production'
12
+ }
13
+
14
+ export default envs
@@ -0,0 +1,67 @@
1
+ import { last, isPlainObject, each, isArray, get } from 'lodash-es'
2
+ import print from './print.js'
3
+ import getPluginName from './get-plugin-name.js'
4
+
5
+ /**
6
+ * It's a shortcut to create an instance of Error with message and optional parameter
7
+ * in a single line
8
+ *
9
+ * @memberof helper
10
+ * @type Object
11
+ * @instance
12
+ * @param {string} msg - String that will be used as error message
13
+ * @param {options} [options] - Optional parameter
14
+ * @param {string} [options.code] - Error code
15
+ * @returns {error} Instance of Error
16
+ */
17
+
18
+ Error.stackTraceLimit = 15
19
+
20
+ function formatErrorDetails (value, ns) {
21
+ each(value, (v, i) => {
22
+ if (!v.context) {
23
+ v.error = print._format.call(this, ns, v.error, {})
24
+ return undefined
25
+ }
26
+ v.context.message = v.message
27
+ if (v.type === 'any.only') v.context.ref = print._format.call(this, ns, `field.${get(v, 'context.valids.0.key')}`, {})
28
+ value[i] = {
29
+ field: get(v, 'context.key'),
30
+ error: print._format.call(this, ns, `validation.${v.type}`, v.context, {})
31
+ }
32
+ })
33
+ }
34
+
35
+ function error (msg = 'Internal server error', ...args) {
36
+ let payload = last(args)
37
+ let ns
38
+ if (isPlainObject(payload)) {
39
+ payload = args.pop()
40
+ ns = payload.ns
41
+ }
42
+ if (!ns) ns = getPluginName.call(this, 3)
43
+ const orgMsg = msg
44
+ const message = print._format.call(this, ns, msg, ...args)
45
+ let err
46
+ if (isPlainObject(payload) && payload.class) err = payload.class(message)
47
+ else err = Error(message)
48
+ const stacks = err.stack.split('\n')
49
+ stacks.splice(1, 1) // this file
50
+ if (stacks[1].includes('/helper/fatal.js')) stacks.splice(1, 1) // if it goes to fatal.js
51
+ stacks.splice(1, 1) // for buildHelper.js
52
+ err.stack = stacks.join('\n')
53
+ if (isPlainObject(payload)) {
54
+ delete payload.class
55
+ delete payload.ns
56
+ for (const key in payload) {
57
+ const value = payload[key]
58
+ if (key === 'details' && isArray(value) && orgMsg === 'Validation Error') {
59
+ formatErrorDetails.call(this, value, ns)
60
+ }
61
+ err[key] = value
62
+ }
63
+ }
64
+ return err
65
+ }
66
+
67
+ export default error
@@ -0,0 +1,12 @@
1
+ import error from './error.js'
2
+ import getPluginName from './get-plugin-name.js'
3
+
4
+ function fatal (...args) {
5
+ const ns = getPluginName.call(this, 3)
6
+ args.push({ ns })
7
+ const err = error(...args)
8
+ console.error(err)
9
+ process.exit(1)
10
+ }
11
+
12
+ export default fatal
@@ -0,0 +1,20 @@
1
+ import { cloneDeep, isPlainObject } from 'lodash-es'
2
+ import { customAlphabet } from 'nanoid'
3
+
4
+ const generateId = (options = {}) => {
5
+ let { pattern, length = 21, returnInstance } = options
6
+ let opts = {}
7
+ if (isPlainObject(pattern)) {
8
+ opts = cloneDeep(pattern)
9
+ returnInstance = opts.returnInstance
10
+ length = opts.length
11
+ pattern = opts.pattern
12
+ }
13
+ pattern = pattern ?? 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
14
+ if (opts.lowerCase) pattern = pattern.toLowerCase()
15
+ else if (opts.upperCase) pattern = pattern.toUpperCase()
16
+ const nid = customAlphabet(pattern, length)
17
+ return returnInstance ? nid : nid()
18
+ }
19
+
20
+ export default generateId
@@ -0,0 +1,19 @@
1
+ import { isEmpty, isPlainObject, cloneDeep, omit, find } from 'lodash-es'
2
+ import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
3
+
4
+ function getConfig (name, options = {}) {
5
+ const { full, clone } = options
6
+ if (name === 'bajo' || isEmpty(name)) return this.bajo.config
7
+ if (this[name] && isPlainObject(this[name].config) && this[name].config.name === name) {
8
+ const cfg = clone ? cloneDeep(this[name].config) : this[name].config
9
+ return full ? cfg : omit(cfg, omittedPluginKeys)
10
+ }
11
+ const ref = find(this.bajo.pluginRefs ?? [], { alias: name })
12
+ if (ref) {
13
+ const cfg = clone ? cloneDeep(this[ref.plugin].config) : this[ref.plugin].config
14
+ return full ? cfg : omit(cfg, omittedPluginKeys)
15
+ }
16
+ return {}
17
+ }
18
+
19
+ export default getConfig
@@ -0,0 +1,27 @@
1
+ import globalModulesPath from 'global-modules-path'
2
+ import resolvePath from './resolve-path.js'
3
+ import error from './error.js'
4
+ import { dropRight } from 'lodash-es'
5
+ import fs from 'fs-extra'
6
+
7
+ const getGlobalModuleDir = (pkgName, silent = true) => {
8
+ let nodeModulesDir = process.env.BAJO_GLOBAL_MODULE_DIR
9
+ if (!nodeModulesDir) {
10
+ const npmPath = globalModulesPath.getPath('npm')
11
+ if (!npmPath) {
12
+ if (silent) return
13
+ throw error('Can\'t locate npm global module directory', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
14
+ }
15
+ nodeModulesDir = dropRight(resolvePath(npmPath).split('/'), 1).join('/')
16
+ process.env.BAJO_GLOBAL_MODULE_DIR = nodeModulesDir
17
+ }
18
+ if (!pkgName) return nodeModulesDir
19
+ const dir = `${nodeModulesDir}/${pkgName}`
20
+ if (!fs.existsSync(dir)) {
21
+ if (silent) return
22
+ throw error('Can\'t locate \'%s\' global module directory', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
23
+ }
24
+ return dir
25
+ }
26
+
27
+ export default getGlobalModuleDir
@@ -0,0 +1,12 @@
1
+ import { get } from 'lodash-es'
2
+ import error from './error.js'
3
+ import breakNsPath from './break-ns-path.js'
4
+
5
+ function getHelper (name = '', thrown = true) {
6
+ const [plugin, method] = breakNsPath(name)
7
+ const helper = get(this, `${plugin}.helper.${method}`)
8
+ if (helper) return helper
9
+ if (thrown) throw error.call(this, 'Can\'t find helper named \'%s\'', name)
10
+ }
11
+
12
+ export default getHelper
@@ -0,0 +1,26 @@
1
+ import path from 'path'
2
+
3
+ async function getItemByName (name) {
4
+ const { resolvePath, getConfig, readConfig, error } = this.bajo.helper
5
+ const config = getConfig()
6
+ const [type, ...paths] = name.split(':')
7
+ let result
8
+ switch (type) {
9
+ case 'config': {
10
+ let file = paths.join(':')
11
+ if (!path.isAbsolute(file)) file = resolvePath(`${config.dir.data}/config/${file}`)
12
+ result = await readConfig(file)
13
+ break
14
+ }
15
+ case 'helper': {
16
+ const [ns, fn] = paths.join(':').split('.')
17
+ if (!(ns && fn)) throw error('Unknown helper \'%s.%s\'', ns, fn, { code: 'BAJO_UNKNOWN_HELPER' })
18
+ result = this[ns].helper[fn]
19
+ break
20
+ }
21
+ default: throw error('Unsupported type \'%s\'', type, { code: 'BAJO_UNSUPPORTED_TYPE' })
22
+ }
23
+ return result
24
+ }
25
+
26
+ export default getItemByName
@@ -0,0 +1,5 @@
1
+ const getKeyByValue = (object, value) => {
2
+ return Object.keys(object).find(key => object[key] === value)
3
+ }
4
+
5
+ export default getKeyByValue
@@ -0,0 +1,22 @@
1
+ import path from 'path'
2
+ import resolvePath from './resolve-path.js'
3
+ import { createRequire } from 'module'
4
+ const require = createRequire(import.meta.url)
5
+
6
+ const getModuleDir = (pkgName, base) => {
7
+ if (base === 'app') base = process.env.BAJOCWD
8
+ let pkgPath = pkgName + '/package.json'
9
+ if (base) pkgPath = `${base}/node_modules/${pkgPath}`
10
+ const paths = require.resolve.paths(pkgPath)
11
+ paths.unshift(path.join(process.env.BAJOCWD, 'node_modules', pkgName))
12
+ let resolved
13
+ try {
14
+ resolved = require.resolve(pkgPath, { paths })
15
+ } catch (err) {
16
+ return null
17
+ }
18
+ const dir = resolvePath(path.dirname(resolved))
19
+ return dir
20
+ }
21
+
22
+ export default getModuleDir
@@ -0,0 +1,12 @@
1
+ import fs from 'fs-extra'
2
+
3
+ function getPluginDataDir (name, ensureDir = true) {
4
+ const { getPlugin, getConfig } = this.bajo.helper
5
+ const plugin = getPlugin(name)
6
+ const cfg = getConfig()
7
+ const dir = `${cfg.dir.data}/plugins/${plugin.config.name}`
8
+ if (ensureDir) fs.ensureDirSync(dir)
9
+ return dir
10
+ }
11
+
12
+ export default getPluginDataDir
@@ -0,0 +1,39 @@
1
+ import { isString, isNumber, each, camelCase } from 'lodash-es'
2
+ import callsites from 'callsites'
3
+ import error from './error.js'
4
+ import resolvePath from './resolve-path.js'
5
+
6
+ /**
7
+ * Get the right Bajo name inside your app or plugins/Bajos. If parameter ```fname```
8
+ * is not provided, it will be set to the actual file this function is called.
9
+ *
10
+ * @memberof helper
11
+ * @instance
12
+ * @param {string} [fname] - File name (relative/absolute)
13
+ * @throws Will throw if Bajo name coldn't be resolved
14
+ * @returns {string} Bajo name
15
+ */
16
+
17
+ function getPluginName (fname) {
18
+ const config = this.bajo.config
19
+ let file
20
+ if (isString(fname)) file = fname
21
+ else file = callsites()[isNumber(fname) ? fname : 2].getFileName()
22
+ if (!file) throw error('Can\'t resolve bajo named \'%s\', sorry!', fname, { code: 'BAJO_UNABLE_TO_RESOLVE_BAJO_NAME' })
23
+ file = resolvePath(file)
24
+ let match
25
+ each(config.plugins, b => {
26
+ if (file.includes('/bajo/boot/')) {
27
+ match = 'bajo'
28
+ return false
29
+ }
30
+ if (file.includes('/' + b + '/')) {
31
+ match = b
32
+ return false
33
+ }
34
+ })
35
+ if (match) return camelCase(match)
36
+ return 'bajo'
37
+ }
38
+
39
+ export default getPluginName
@@ -0,0 +1,14 @@
1
+ import { find } from 'lodash-es'
2
+
3
+ function getPlugin (name) {
4
+ const { error } = this.bajo.helper
5
+ if (!this[name]) {
6
+ // alias?
7
+ const ref = find(this.bajo.pluginRefs ?? [], { alias: name })
8
+ if (!ref) throw error('\'%s\' is not loaded', name)
9
+ name = ref.name
10
+ }
11
+ return this[name]
12
+ }
13
+
14
+ export default getPlugin
@@ -0,0 +1,25 @@
1
+ import resolvePath from './resolve-path.js'
2
+ import { isFunction, isPlainObject } from 'lodash-es'
3
+ import error from './error.js'
4
+
5
+ async function load (file, asDefaultImport = true) {
6
+ const imported = await import(resolvePath(file, true))
7
+ if (asDefaultImport) return imported.default
8
+ return imported
9
+ }
10
+
11
+ async function importModule (file, { asDefaultImport, asHandler } = {}) {
12
+ let mod = await load(file, asDefaultImport)
13
+ if (!asHandler) return mod
14
+ if (isFunction(mod)) mod = { level: 999, handler: mod }
15
+ if (!isPlainObject(mod)) throw error.call(this, 'File \'%s\' is NOT a handler module', file)
16
+ if (mod.forceAsync && mod.handler.constructor.name !== 'AsyncFunction') {
17
+ const oldHandler = mod.handler
18
+ mod.handler = async function (...args) {
19
+ oldHandler.call(this, ...args)
20
+ }
21
+ }
22
+ return mod
23
+ }
24
+
25
+ export default importModule
@@ -0,0 +1,67 @@
1
+ import { isPlainObject, map, last, isEmpty, has, keys, values, trim, get } from 'lodash-es'
2
+ import os from 'os'
3
+ import getModuleDir from './get-module-dir.js'
4
+ import resolvePath from './resolve-path.js'
5
+ import readJson from './read-json.js'
6
+ import defaultsDeep from './defaults-deep.js'
7
+ import path from 'path'
8
+ import fs from 'fs-extra'
9
+
10
+ /**
11
+ * Load/import a package dynamically. You can import package one-by-one or multiple
12
+ * packages at once.
13
+ *
14
+ * Package 'pkg' must be in the following format: ```<original name>:<new name>:<bajo package name>```
15
+ * ```<new name>``` can be omitted, so the format will be: ```<name>::<bajo package name>```
16
+ *
17
+ * If you only import one package, returned value is the imported package itself
18
+ * If multiple packages are imported, returned value is an object with ```<new name>``` as its
19
+ * keys and imported packages as its values
20
+ *
21
+ * Example:
22
+ * ```
23
+ * const imported = await importPkg('ora::bajo-cli')
24
+ * const multiple = await importPkg('ora::bajo-cli', 'lodash:_:bajo')
25
+ *
26
+ * @param {...string} pkg
27
+ * @returns
28
+ */
29
+
30
+ const importPkg = async (...pkg) => {
31
+ const result = {}
32
+ let opts = { returnDefault: true }
33
+ if (isPlainObject(last(pkg))) {
34
+ opts = defaultsDeep(pkg.pop(), opts)
35
+ }
36
+ for (const p of pkg) {
37
+ const parts = map(p.split(':'), i => trim(i))
38
+ let [ns, orgName, name] = parts
39
+ if (parts.length === 1) {
40
+ orgName = ns
41
+ ns = 'bajo'
42
+ name = orgName
43
+ } else if (parts.length === 2) {
44
+ name = orgName
45
+ }
46
+ if (isEmpty(name)) name = orgName
47
+ const dir = getModuleDir(orgName, ns)
48
+ const pkg = readJson(`${dir}/package.json`)
49
+ const mainFileOrg = dir + '/' + (pkg.main ?? get(pkg, 'exports.default', 'index.js'))
50
+ let mainFile = resolvePath(mainFileOrg, os.platform() === 'win32')
51
+ if (isEmpty(path.extname(mainFile))) {
52
+ if (fs.existsSync(`${mainFileOrg}/index.js`)) mainFile += '/index.js'
53
+ else mainFile += '.js'
54
+ }
55
+ let mod = await import(mainFile)
56
+ if (opts.returnDefault && has(mod, 'default')) {
57
+ mod = mod.default
58
+ if (opts.returnDefault && has(mod, 'default')) mod = mod.default
59
+ }
60
+ result[name] = mod
61
+ }
62
+ if (pkg.length === 1) return result[keys(result)[0]]
63
+ if (opts.asObject) return result
64
+ return values(result)
65
+ }
66
+
67
+ export default importPkg