bajo 0.1.0 → 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 (72) hide show
  1. package/bajoBook/book/doc/.metadata.json +28 -0
  2. package/bajoBook/book/doc/How-to-Make-a-Paper-Boat-564x400@2x.jpg +0 -0
  3. package/bajoBook/book/doc/pages/guides/definition.md +7 -0
  4. package/bajoBook/book/doc/pages/guides/intro.md +3 -0
  5. package/bajoBook/book/doc/pages/guides/setup.md +22 -0
  6. package/bajoBook/book/reference/.metadata.json +152 -0
  7. package/bajoBook/book/reference/concept-leadership-business-with-paper-boats.jpg +0 -0
  8. package/bajoBook/book/reference/pages/configuration/configuration-file.md +52 -0
  9. package/bajoBook/book/reference/pages/helper/break-ns-path.md +24 -0
  10. package/bajoBook/book/reference/pages/helper/build-collections.md +19 -0
  11. package/bajoBook/book/reference/pages/helper/call-helper-or-handler.md +35 -0
  12. package/bajoBook/book/reference/pages/helper/current-loc.md +28 -0
  13. package/bajoBook/book/reference/pages/helper/dayjs.md +13 -0
  14. package/bajoBook/book/reference/pages/helper/defaults-deep.md +29 -0
  15. package/bajoBook/book/reference/pages/helper/dump.md +32 -0
  16. package/bajoBook/book/reference/pages/helper/each-plugins.md +24 -0
  17. package/bajoBook/book/reference/pages/helper/envs.md +11 -0
  18. package/bajoBook/book/reference/pages/helper/error.md +29 -0
  19. package/bajoBook/book/reference/pages/helper/fatal.md +18 -0
  20. package/bajoBook/book/reference/pages/helper/freeze.md +13 -0
  21. package/bajoBook/book/reference/pages/helper/generate-id.md +36 -0
  22. package/bajoBook/book/reference/pages/helper/get-config.md +27 -0
  23. package/bajoBook/book/reference/pages/helper/get-global-module-dir.md +13 -0
  24. package/bajoBook/book/reference/pages/helper/get-helper.md +13 -0
  25. package/bajoBook/book/reference/pages/helper/get-item-by-name.md +13 -0
  26. package/bajoBook/book/reference/pages/helper/get-key-by-value.md +13 -0
  27. package/bajoBook/book/reference/pages/helper/get-module-dir.md +13 -0
  28. package/bajoBook/book/reference/pages/helper/get-plugin-data-dir.md +13 -0
  29. package/bajoBook/book/reference/pages/helper/get-plugin-name.md +13 -0
  30. package/bajoBook/book/reference/pages/helper/get-plugin.md +13 -0
  31. package/bajoBook/book/reference/pages/helper/import-module.md +13 -0
  32. package/bajoBook/book/reference/pages/helper/import-pkg.md +13 -0
  33. package/bajoBook/book/reference/pages/helper/is-empty-dir.md +13 -0
  34. package/bajoBook/book/reference/pages/helper/is-log-in-range.md +13 -0
  35. package/bajoBook/book/reference/pages/helper/is-set.md +13 -0
  36. package/bajoBook/book/reference/pages/helper/is-valid-app.md +13 -0
  37. package/bajoBook/book/reference/pages/helper/is-valid-plugin.md +13 -0
  38. package/bajoBook/book/reference/pages/helper/log-levels.md +13 -0
  39. package/bajoBook/book/reference/pages/helper/log.md +13 -0
  40. package/bajoBook/book/reference/pages/helper/paginate.md +13 -0
  41. package/bajoBook/book/reference/pages/helper/pascal-case.md +13 -0
  42. package/bajoBook/book/reference/pages/helper/print.md +13 -0
  43. package/bajoBook/book/reference/pages/helper/read-config.md +13 -0
  44. package/bajoBook/book/reference/pages/helper/read-json.md +13 -0
  45. package/bajoBook/book/reference/pages/helper/resolve-path.md +13 -0
  46. package/bajoBook/book/reference/pages/helper/resolve-tpl-path.md +13 -0
  47. package/bajoBook/book/reference/pages/helper/run-hook.md +13 -0
  48. package/bajoBook/book/reference/pages/helper/save-as-download.md +13 -0
  49. package/bajoBook/book/reference/pages/helper/titleize.md +13 -0
  50. package/bajoBook/book/reference/pages/helper/white-space.md +13 -0
  51. package/boot/attach-helper.js +8 -0
  52. package/boot/build-config.js +8 -3
  53. package/boot/helper/break-ns-path.js +17 -0
  54. package/boot/helper/build-collections.js +17 -23
  55. package/boot/helper/each-plugins.js +59 -49
  56. package/boot/helper/error.js +22 -2
  57. package/boot/helper/generate-id.js +4 -3
  58. package/boot/helper/get-config.js +3 -2
  59. package/boot/helper/get-global-module-dir.js +2 -2
  60. package/boot/helper/get-helper.js +2 -1
  61. package/boot/helper/get-plugin-data-dir.js +12 -0
  62. package/boot/helper/get-plugin.js +9 -2
  63. package/boot/helper/paginate.js +26 -0
  64. package/boot/helper/print.js +12 -2
  65. package/boot/helper/resolve-tpl-path.js +5 -11
  66. package/boot/helper/save-as-download.js +2 -3
  67. package/boot/helper/titleize.js +14 -0
  68. package/boot/lib/build-helper.js +1 -2
  69. package/boot/plugins/build-config.js +11 -4
  70. package/boot/plugins/collect-hooks.js +10 -9
  71. package/package.json +1 -1
  72. package/boot/helper/index.js +0 -36
@@ -1,4 +1,4 @@
1
- import { last, isPlainObject } from 'lodash-es'
1
+ import { last, isPlainObject, each, isArray, get } from 'lodash-es'
2
2
  import print from './print.js'
3
3
  import getPluginName from './get-plugin-name.js'
4
4
 
@@ -17,6 +17,21 @@ import getPluginName from './get-plugin-name.js'
17
17
 
18
18
  Error.stackTraceLimit = 15
19
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
+
20
35
  function error (msg = 'Internal server error', ...args) {
21
36
  let payload = last(args)
22
37
  let ns
@@ -25,6 +40,7 @@ function error (msg = 'Internal server error', ...args) {
25
40
  ns = payload.ns
26
41
  }
27
42
  if (!ns) ns = getPluginName.call(this, 3)
43
+ const orgMsg = msg
28
44
  const message = print._format.call(this, ns, msg, ...args)
29
45
  let err
30
46
  if (isPlainObject(payload) && payload.class) err = payload.class(message)
@@ -38,7 +54,11 @@ function error (msg = 'Internal server error', ...args) {
38
54
  delete payload.class
39
55
  delete payload.ns
40
56
  for (const key in payload) {
41
- err[key] = payload[key]
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
42
62
  }
43
63
  }
44
64
  return err
@@ -1,7 +1,8 @@
1
1
  import { cloneDeep, isPlainObject } from 'lodash-es'
2
2
  import { customAlphabet } from 'nanoid'
3
3
 
4
- const generateId = ({ pattern, length = 21, returnInstance } = {}) => {
4
+ const generateId = (options = {}) => {
5
+ let { pattern, length = 21, returnInstance } = options
5
6
  let opts = {}
6
7
  if (isPlainObject(pattern)) {
7
8
  opts = cloneDeep(pattern)
@@ -10,8 +11,8 @@ const generateId = ({ pattern, length = 21, returnInstance } = {}) => {
10
11
  pattern = opts.pattern
11
12
  }
12
13
  pattern = pattern ?? 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
13
- if (opts.lowerCase) pattern = 'abcdefghijklmnopqrstuvwxyz0123456789'
14
- else if (opts.upperCase) pattern = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
14
+ if (opts.lowerCase) pattern = pattern.toLowerCase()
15
+ else if (opts.upperCase) pattern = pattern.toUpperCase()
15
16
  const nid = customAlphabet(pattern, length)
16
17
  return returnInstance ? nid : nid()
17
18
  }
@@ -1,7 +1,8 @@
1
1
  import { isEmpty, isPlainObject, cloneDeep, omit, find } from 'lodash-es'
2
2
  import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
3
3
 
4
- function getConfig (name, { full, clone } = {}) {
4
+ function getConfig (name, options = {}) {
5
+ const { full, clone } = options
5
6
  if (name === 'bajo' || isEmpty(name)) return this.bajo.config
6
7
  if (this[name] && isPlainObject(this[name].config) && this[name].config.name === name) {
7
8
  const cfg = clone ? cloneDeep(this[name].config) : this[name].config
@@ -9,7 +10,7 @@ function getConfig (name, { full, clone } = {}) {
9
10
  }
10
11
  const ref = find(this.bajo.pluginRefs ?? [], { alias: name })
11
12
  if (ref) {
12
- const cfg = clone ? cloneDeep(this[ref.name].config) : this[ref.name].config
13
+ const cfg = clone ? cloneDeep(this[ref.plugin].config) : this[ref.plugin].config
13
14
  return full ? cfg : omit(cfg, omittedPluginKeys)
14
15
  }
15
16
  return {}
@@ -10,7 +10,7 @@ const getGlobalModuleDir = (pkgName, silent = true) => {
10
10
  const npmPath = globalModulesPath.getPath('npm')
11
11
  if (!npmPath) {
12
12
  if (silent) return
13
- throw error(`Can't locate npm global module directory`, { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
13
+ throw error('Can\'t locate npm global module directory', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
14
14
  }
15
15
  nodeModulesDir = dropRight(resolvePath(npmPath).split('/'), 1).join('/')
16
16
  process.env.BAJO_GLOBAL_MODULE_DIR = nodeModulesDir
@@ -19,7 +19,7 @@ const getGlobalModuleDir = (pkgName, silent = true) => {
19
19
  const dir = `${nodeModulesDir}/${pkgName}`
20
20
  if (!fs.existsSync(dir)) {
21
21
  if (silent) return
22
- throw error(`Can't locate '%s' global module directory`, pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
22
+ throw error('Can\'t locate \'%s\' global module directory', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
23
23
  }
24
24
  return dir
25
25
  }
@@ -1,8 +1,9 @@
1
1
  import { get } from 'lodash-es'
2
2
  import error from './error.js'
3
+ import breakNsPath from './break-ns-path.js'
3
4
 
4
5
  function getHelper (name = '', thrown = true) {
5
- const [plugin, method] = name.split(':')
6
+ const [plugin, method] = breakNsPath(name)
6
7
  const helper = get(this, `${plugin}.helper.${method}`)
7
8
  if (helper) return helper
8
9
  if (thrown) throw error.call(this, 'Can\'t find helper named \'%s\'', name)
@@ -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
@@ -1,6 +1,13 @@
1
- async function getPlugin (name) {
1
+ import { find } from 'lodash-es'
2
+
3
+ function getPlugin (name) {
2
4
  const { error } = this.bajo.helper
3
- if (!this[name]) throw error('\'%s\' is not loaded', name)
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
+ }
4
11
  return this[name]
5
12
  }
6
13
 
@@ -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
@@ -1,6 +1,6 @@
1
1
  import bora from '../lib/bora.js'
2
2
  import Sprintf from 'sprintf-js'
3
- import { last, isPlainObject, get } from 'lodash-es'
3
+ import { last, isPlainObject, get, merge, upperFirst } from 'lodash-es'
4
4
  import defaultsDeep from './defaults-deep.js'
5
5
  import getPluginName from './get-plugin-name.js'
6
6
 
@@ -21,7 +21,17 @@ function format (...args) {
21
21
  if (!msg) return ''
22
22
  const i18n = get(this, 'bajoI18N.instance')
23
23
  if (i18n) {
24
- if (isPlainObject(params[0])) return i18n.t(msg, params[0])
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
+ }
25
35
  return i18n.t(msg, { ns, pkg: opts.pkg, postProcess: 'sprintf', sprintf: params })
26
36
  }
27
37
  return sprintf(msg, ...params)
@@ -1,19 +1,13 @@
1
- import { isEmpty, trim } from 'lodash-es'
1
+ import { trim } from 'lodash-es'
2
2
  import fs from 'fs-extra'
3
3
 
4
4
  function resolveTplPath (name, baseTpl, extTpl = '') {
5
- const { error, getConfig } = this.bajo.helper
6
- let [ns, path] = name.split(':')
7
- if (isEmpty(path)) {
8
- path = ns
9
- ns = 'app'
10
- }
11
- if (path.startsWith('.')) throw error('Path \'%s\' must be an absolute path', path)
12
- if (!this[ns]) throw error('Unknown plugin \'%s\' or plugin isn\'t loaded yet', ns)
5
+ const { getConfig, breakNsPath } = this.bajo.helper
6
+ const [ns, path] = breakNsPath(name)
13
7
  const cfgNs = getConfig(ns, { full: true })
14
8
  const cfgApp = getConfig('app', { full: true })
15
- let file = `${cfgNs.dir}/${baseTpl}/${trim(path, '/')}${extTpl}`
16
- const override = `${cfgApp.dir}/${baseTpl}/override/${ns}/${trim(path, '/')}${extTpl}`
9
+ let file = `${cfgNs.dir.pkg}/${baseTpl}/${trim(path, '/')}${extTpl}`
10
+ const override = `${cfgApp.dir.pkg}/${baseTpl}/override/${ns}/${trim(path, '/')}${extTpl}`
17
11
  if (fs.existsSync(override)) file = override
18
12
  return file
19
13
  }
@@ -4,10 +4,9 @@ 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, resolvePath } = this.bajo.helper
8
- const config = this.bajo.config
7
+ const { print, getPluginName, getPluginDataDir } = this.bajo.helper
9
8
  const plugin = getPluginName(4)
10
- const fname = resolvePath(increment(`${config.dir.data}/plugins/${plugin}/${trim(file, '/')}`, { fs: true }))
9
+ const fname = increment(`${getPluginDataDir(plugin)}/${trim(file, '/')}`, { fs: true })
11
10
  const dir = path.dirname(fname)
12
11
  if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
13
12
  await fs.writeFile(fname, obj, 'utf8')
@@ -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
@@ -45,8 +45,7 @@ export default async function (dir, { pkg = 'bajo', exclude = [] } = {}) {
45
45
  if (mod.constructor.name === 'AsyncFunction') mod = wrapAsyncFn.call(this, fnName, mod, true)
46
46
  else mod = wrapFn.call(this, fnName, mod, true)
47
47
  } else if (isPlainObject(mod)) {
48
- if (isFunction(mod.class)) mod = new mod.class(this)
49
- else {
48
+ if (!mod.exec) { // mod.exec offer unbind, nacked function people can band to anything else later
50
49
  forOwn(mod, (v, k) => {
51
50
  if (isFunction(v)) mod[k] = v.bind(this)
52
51
  })
@@ -2,6 +2,7 @@ import { camelCase, pick, isString, omit, pull, each } from 'lodash-es'
2
2
  import fs from 'fs-extra'
3
3
  import lockfile from 'proper-lockfile'
4
4
  import omittedPluginKeys from '../lib/omitted-plugin-keys.js'
5
+ import titleize from '../helper/titleize.js'
5
6
 
6
7
  export async function readAllConfigs (base, name) {
7
8
  const { readConfig, getConfig } = this.bajo.helper
@@ -31,12 +32,18 @@ async function runner (pkg, { singles, argv, env }) {
31
32
  const dir = pkg === 'app' ? (config.dir.base + '/app') : getModuleDir(pkg)
32
33
  if (pkg !== 'app' && !fs.existsSync(`${dir}/bajo`)) throw error('Package \'%s\' isn\'t a valid Bajo package', pkg, { code: 'BAJO_INVALID_PACKAGE' })
33
34
  let cfg = await readAllConfigs.call(this, `${dir}/bajo/config`, name)
34
- cfg.dir = dir
35
+ cfg.dir = {
36
+ pkg: dir,
37
+ data: `${config.dir.data}/plugins/${name}`
38
+ }
35
39
  const pkgJson = await readJson(`${dir + (pkg === 'app' ? '/..' : '')}/package.json`)
36
40
  cfg.pkg = pick(pkgJson,
37
41
  ['name', 'version', 'description', 'author', 'license', 'homepage'])
38
- if (cfg.name === 'app') cfg.alias = 'app'
39
- else if (!isString(cfg.alias)) cfg.alias = pkg.slice(0, 5) === 'bajo-' ? pkg.slice(5).toLowerCase() : pkg // fix. can't be overriden
42
+ if (cfg.name === 'app') {
43
+ cfg.alias = 'app'
44
+ cfg.title = 'Application'
45
+ } else if (!isString(cfg.alias)) cfg.alias = pkg.slice(0, 5) === 'bajo-' ? pkg.slice(5).toLowerCase() : pkg // fix. can't be overriden
46
+ cfg.title = cfg.title ?? titleize.call(this, cfg.alias)
40
47
  // merge with config from datadir
41
48
  try {
42
49
  const altCfg = await readConfig(`${config.dir.data}/config/${cfg.name}.*`)
@@ -50,7 +57,7 @@ async function runner (pkg, { singles, argv, env }) {
50
57
  const lockfileDir = `${config.dir.tmp}/lock`
51
58
  const lockfilePath = `${lockfileDir}/${name}.lock`
52
59
  fs.ensureDirSync(lockfileDir)
53
- const file = `${cfg.dir}/package.json`
60
+ const file = `${dir}/package.json`
54
61
  try {
55
62
  await lockfile.lock(file, { lockfilePath })
56
63
  } catch (err) {
@@ -1,4 +1,4 @@
1
- import { map, camelCase, merge, filter, groupBy } from 'lodash-es'
1
+ import { map, camelCase, merge, forOwn, groupBy } from 'lodash-es'
2
2
 
3
3
  async function collectHooks () {
4
4
  const { eachPlugins, log, runHook, isLogInRange, importModule } = this.bajo.helper
@@ -7,11 +7,13 @@ async function collectHooks () {
7
7
  // collects
8
8
  await eachPlugins(async function ({ plugin, dir, file }) {
9
9
  const hookName = (file.slice(dir.length + 1) ?? '').split('/')[1]
10
- let [ns, path] = map(hookName.replace('.js', '').split('@'), e => camelCase(e))
10
+ let [ns, path] = hookName.replace('.js', '').split('@')
11
11
  if (!path) {
12
12
  path = ns
13
13
  ns = plugin
14
14
  }
15
+ path = camelCase(path)
16
+ ns = map(ns.split('.'), (n, i) => i === 1 ? n : camelCase(n)).join('.')
15
17
  const mod = await importModule(file, { asHandler: true })
16
18
  if (!mod) return undefined
17
19
  merge(mod, { ns, path })
@@ -20,13 +22,12 @@ async function collectHooks () {
20
22
  await runHook('bajo:afterCollectHooks')
21
23
  // for log trace purpose only
22
24
  if (!isLogInRange('trace')) return
23
- await eachPlugins(async function ({ plugin }) {
24
- const hooks = filter(this.bajo.hooks, { ns: plugin })
25
- if (hooks.length === 0) return undefined
26
- const items = groupBy(hooks, 'path')
27
- for (const hook of hooks) {
28
- log.trace('Collect hook: %s:%s (%d)', hook.ns, hook.path, items[hook.path].length)
29
- }
25
+ const items = groupBy(this.bajo.hooks, 'ns')
26
+ forOwn(items, (v, k) => {
27
+ const hooks = groupBy(v, 'path')
28
+ forOwn(hooks, (v1, k1) => {
29
+ log.trace('Collect hook: %s:%s (%d)', k, k1, v1.length)
30
+ })
30
31
  })
31
32
  }
32
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajo",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A framework to build a giant monstrous app rapidly",
5
5
  "main": "boot/index.js",
6
6
  "scripts": {
@@ -1,36 +0,0 @@
1
- /**
2
- * Bajo Helper is a general-purpose container that consists of functions, objects, or arrays
3
- * that are accessible across all plugins/Bajos and applications. It also serves as a proxy
4
- * to some exported third-party libraries.
5
- *
6
- * To use it, simply deconstruct the variables you want from Bajo Helper as shown in the
7
- * example below.
8
- *
9
- * @module helper
10
- * @example
11
- * module.exports = async function () {
12
- * const { fs, getConfig } = this.bajo.helper
13
- * const config = getConfig('bajoExtra')
14
- * await fs.writeFile('./bajo-extra-config.json', JSON.stringify(config), 'utf8')
15
- * }
16
- */
17
-
18
- /**
19
- * | Attached As | Package Name | Usage |
20
- * |-------------|--------------|-------|
21
- * | _ | [lodash](https://lodash.com/) | ```const { _ } = this.bajo.helper``` |
22
- * | callsites | [callsites](https://github.com/sindresorhus/callsites) | ```const { _ } = this.bajo.helper``` |
23
- * | dateFormat | [dateformat](https://github.com/felixge/node-dateformat) | ```const { dateFormat } = this.bajo.helper``` |
24
- * | fastGlob | [fast-glob](https://github.com/mrmlnc/fast-glob) | ```const { fastGlob } = this.bajo.helper``` |
25
- * | flatten | [flat](https://github.com/hughsk/flat) | ```const { flatten } = this.bajo.helper``` |
26
- * | freeze | [deep-freeze-strict](https://github.com/jsdf/deep-freeze) | ```const { freeze } = this.bajo.helper``` |
27
- * | fs | [fs-extra](https://github.com/jprichardson/node-fs-extra) | ```const { fs } = this.bajo.helper``` |
28
- * | lockfile | [proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) | ```const { lockfile } = this.bajo.helper``` |
29
- * | outmatch | [outmatch](https://github.com/axtgr/outmatch) | ```const { outmatch } = this.bajo.helper``` |
30
- * | semver | [semver](https://github.com/npm/node-semver) | ```const { semver } = this.bajo.helper``` |
31
- * | unflatten | [flat](https://github.com/hughsk/flat) | ```const { unflatten } = this.bajo.helper``` |
32
- *
33
- * @memberof module:helper/3rdPartyLibs
34
- * @name 3rd Party Libraries
35
- * @instance
36
- */