bajo 1.1.17 → 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/boot/class/app.js CHANGED
@@ -58,7 +58,7 @@ class App {
58
58
  await exitHandler.call(bajo)
59
59
  // boot complete
60
60
  const elapsed = new Date() - bajo.runAt
61
- bajo.log.info('bootCompleted%s', bajo.secToHms(elapsed, true))
61
+ bajo.log.info('bootCompleted%s', bajo.lib.aneka.secToHms(elapsed, true))
62
62
  await bajo.runHook('bajo:afterBootComplete')
63
63
  if (bajo.applet) await runAsApplet.call(bajo)
64
64
  }
@@ -39,8 +39,9 @@ const defConfig = {
39
39
  }
40
40
 
41
41
  export async function buildBaseConfig () {
42
+ const { defaultsDeep } = this.lib.aneka
42
43
  this.applet = this.app.argv._.applet
43
- this.config = this.defaultsDeep({}, this.app.env._, this.app.argv._)
44
+ this.config = defaultsDeep({}, this.app.env._, this.app.argv._)
44
45
  this.alias = this.name
45
46
  set(this, 'dir.base', this.app.dir)
46
47
  const path = currentLoc(import.meta).dir + '/../../..'
@@ -61,11 +62,12 @@ export async function buildBaseConfig () {
61
62
 
62
63
  export async function buildExtConfig () {
63
64
  // config merging
65
+ const { defaultsDeep } = this.lib.aneka
64
66
  let resp = await readAllConfigs.call(this.app, `${this.dir.data}/config/${this.name}`)
65
67
  resp = omitDeep(pick(resp, ['log', 'exitHandler', 'env']), omitted)
66
- this.config = this.defaultsDeep({}, resp, this.config, defConfig)
68
+ this.config = defaultsDeep({}, resp, this.config, defConfig)
67
69
  this.config.env = (this.config.env ?? 'dev').toLowerCase()
68
- if (values(this.envs).includes(this.config.env)) this.config.env = this.getKeyByValue(this.envs, this.config.env)
70
+ if (values(this.envs).includes(this.config.env)) this.config.env = this.lib.aneka.getKeyByValue(this.envs, this.config.env)
69
71
  if (!keys(this.envs).includes(this.config.env)) throw new Error(`Unknown environment '${this.config.env}'. Supported: ${this.join(keys(this.envs))}`)
70
72
  process.env.NODE_ENV = this.envs[this.config.env]
71
73
  if (!this.config.log.level) this.config.log.level = this.config.env === 'dev' ? 'debug' : 'info'
@@ -26,10 +26,10 @@ import { types as formatTypes, formats } from '../lib/formats.js'
26
26
  const require = createRequire(import.meta.url)
27
27
 
28
28
  const {
29
- isFunction, words, upperFirst, map, concat, uniq, forOwn, padStart,
29
+ isFunction, map,
30
30
  trim, filter, isEmpty, orderBy, pullAt, find, camelCase, isNumber,
31
31
  cloneDeep, isPlainObject, isArray, isString, set, omit, keys, indexOf,
32
- last, get, has, values, dropRight, pick, mergeWith
32
+ last, get, has, values, dropRight, pick
33
33
  } = lodash
34
34
 
35
35
  class BajoCore extends Plugin {
@@ -77,21 +77,6 @@ class BajoCore extends Plugin {
77
77
  })
78
78
  }
79
79
 
80
- arrangeArray = (inputs, trimItem = true) => {
81
- const first = []
82
- const last = []
83
-
84
- const items = filter(inputs, item => {
85
- if (trimItem) item = trim(item)
86
- if (item[0] === '^') first.push(item.slice(1))
87
- else if (item[0] === '$') last.push(item.slice(1))
88
- return !['^', '$'].includes(item[0])
89
- })
90
- items.unshift(...first)
91
- items.push(...last)
92
- return items
93
- }
94
-
95
80
  breakNsPathFromFile = ({ file, dir, baseNs, suffix = '', getType } = {}) => {
96
81
  let item = file.replace(dir + suffix, '')
97
82
  let type
@@ -205,16 +190,6 @@ class BajoCore extends Plugin {
205
190
  return result
206
191
  }
207
192
 
208
- defaultsDeep = (...args) => {
209
- const output = {}
210
- args.reverse().forEach(function (item) {
211
- mergeWith(output, item, function (objectValue, sourceValue) {
212
- return isArray(sourceValue) ? sourceValue : undefined
213
- })
214
- })
215
- return output
216
- }
217
-
218
193
  eachPlugins = async (handler, options = {}) => {
219
194
  if (typeof options === 'string') options = { glob: options }
220
195
  const result = {}
@@ -265,20 +240,6 @@ class BajoCore extends Plugin {
265
240
  return result
266
241
  }
267
242
 
268
- extractText = (text, patternStart, patternEnd) => {
269
- let result = ''
270
- const open = text.indexOf(patternStart)
271
- if (open > -1) {
272
- text = text.slice(open + patternStart.length)
273
- const close = text.indexOf(patternEnd)
274
- if (close > -1) {
275
- result = text.slice(0, close)
276
- }
277
- }
278
- const pattern = `${patternStart}${result}${patternEnd}`
279
- return { result, pattern }
280
- }
281
-
282
243
  getUnitFormat = (options = {}) => {
283
244
  const lang = options.lang ?? this.config.lang
284
245
  let unitSys = options.unitSys ?? this.config.intl.unitSys[lang] ?? 'metric'
@@ -287,6 +248,7 @@ class BajoCore extends Plugin {
287
248
  }
288
249
 
289
250
  formatByType = (type, value, dataType, options = {}) => {
251
+ const { defaultsDeep } = this.lib.aneka
290
252
  const { format } = this.getUnitFormat(options)
291
253
  const { withUnit = true } = options
292
254
  const lang = options.lang ?? this.config.lang
@@ -294,12 +256,13 @@ class BajoCore extends Plugin {
294
256
  const unit = format[`${type}Unit`]
295
257
  const sep = format[`${type}UnitSep`] ?? ' '
296
258
  if (!withUnit) return [value, unit, sep]
297
- const setting = this.defaultsDeep(options[dataType], this.config.intl.format[dataType])
259
+ const setting = defaultsDeep(options[dataType], this.config.intl.format[dataType])
298
260
  value = new Intl.NumberFormat(lang, setting).format(value)
299
261
  return `${value}${sep}${unit}`
300
262
  }
301
263
 
302
264
  format = (value, type, options = {}) => {
265
+ const { defaultsDeep } = this.lib.aneka
303
266
  const { format } = this.config.intl
304
267
  const { emptyValue = format.emptyValue } = options
305
268
  const lang = options.lang ?? this.config.lang
@@ -321,21 +284,21 @@ class BajoCore extends Plugin {
321
284
  }
322
285
  }
323
286
  if (['integer', 'smallint'].includes(type)) {
324
- const setting = this.defaultsDeep(options.integer, format.integer)
287
+ const setting = defaultsDeep(options.integer, format.integer)
325
288
  value = new Intl.NumberFormat(lang, setting).format(Math.round(value))
326
289
  return valueFormatted && options.withUnit ? valueFormatted : value
327
290
  }
328
291
  if (['float', 'double'].includes(type)) {
329
- const setting = this.defaultsDeep(options[type], format[type])
292
+ const setting = defaultsDeep(options[type], format[type])
330
293
  value = new Intl.NumberFormat(lang, setting).format(value)
331
294
  return valueFormatted && options.withUnit ? valueFormatted : value
332
295
  }
333
296
  if (['datetime', 'date'].includes(type)) {
334
- const setting = this.defaultsDeep(options[type], format[type])
297
+ const setting = defaultsDeep(options[type], format[type])
335
298
  return new Intl.DateTimeFormat(lang, setting).format(new Date(value))
336
299
  }
337
300
  if (['time'].includes(type)) {
338
- const setting = this.defaultsDeep(options.time, format.time)
301
+ const setting = defaultsDeep(options.time, format.time)
339
302
  return new Intl.DateTimeFormat(lang, setting).format(new Date(`1970-01-01T${value}Z`))
340
303
  }
341
304
  if (['array'].includes(type)) return value.join(', ')
@@ -383,10 +346,6 @@ class BajoCore extends Plugin {
383
346
  return dir
384
347
  }
385
348
 
386
- getKeyByValue = (object, value) => {
387
- return Object.keys(object).find(key => object[key] === value)
388
- }
389
-
390
349
  getMethod = (name = '', thrown = true) => {
391
350
  const { ns, path } = this.breakNsPath(name)
392
351
  const method = get(this.app, `${ns}.${path}`)
@@ -467,11 +426,12 @@ class BajoCore extends Plugin {
467
426
  }
468
427
 
469
428
  importPkg = async (...pkgs) => {
429
+ const { defaultsDeep } = this.lib.aneka
470
430
  const result = {}
471
431
  const notFound = []
472
432
  let opts = { returnDefault: true, thrownNotFound: false }
473
433
  if (isPlainObject(last(pkgs))) {
474
- opts = this.defaultsDeep(pkgs.pop(), opts)
434
+ opts = defaultsDeep(pkgs.pop(), opts)
475
435
  }
476
436
  for (const pkg of pkgs) {
477
437
  const { ns, path: name } = this.breakNsPath(pkg)
@@ -501,22 +461,6 @@ class BajoCore extends Plugin {
501
461
  return values(result)
502
462
  }
503
463
 
504
- includes = (matcher = [], array = []) => {
505
- if (typeof matcher === 'string') matcher = [matcher]
506
- let found = false
507
- for (const m of matcher) {
508
- found = array.includes(m)
509
- if (found) break
510
- }
511
- return found
512
- }
513
-
514
- isClass = (item) => {
515
- return typeof item === 'function' &&
516
- Object.prototype.hasOwnProperty.call(item, 'prototype') &&
517
- !Object.prototype.hasOwnProperty.call(item, 'arguments')
518
- }
519
-
520
464
  isEmptyDir = async (dir) => {
521
465
  await fs.exists(dir)
522
466
  return await emptyDir(dir)
@@ -528,10 +472,6 @@ class BajoCore extends Plugin {
528
472
  return indexOf(levels, level) >= logLevel
529
473
  }
530
474
 
531
- isSet = (input) => {
532
- return ![null, undefined].includes(input)
533
- }
534
-
535
475
  isValidApp = (dir) => {
536
476
  if (!dir) dir = this.app.dir
537
477
  dir = resolvePath(dir)
@@ -549,13 +489,14 @@ class BajoCore extends Plugin {
549
489
  }
550
490
 
551
491
  join = (array, sep) => {
492
+ const { isSet } = this.lib.aneka
552
493
  const translate = val => {
553
494
  if (this && this.print) return this.print.write(val).toLowerCase()
554
495
  return val
555
496
  }
556
497
  if (array.length === 0) return translate('none')
557
498
  if (array.length === 1) return array[0]
558
- if (this.isSet(sep) && !isPlainObject(sep)) return array.join(sep)
499
+ if (isSet(sep) && !isPlainObject(sep)) return array.join(sep)
559
500
  let { separator = ', ', joiner = 'and' } = sep ?? {}
560
501
  joiner = translate(joiner)
561
502
  const last = (array.pop() ?? '').trim()
@@ -568,29 +509,6 @@ class BajoCore extends Plugin {
568
509
  return `${num[0]}${isEmpty(unit) ? defUnit : unit[0]}`
569
510
  }
570
511
 
571
- paginate = (collection, { page = 1, limit = 25, sort } = {}) => {
572
- const count = collection.length
573
- const offset = (page - 1) * limit
574
- const fields = []
575
- const dirs = []
576
- if (isPlainObject(sort)) {
577
- forOwn(sort, (v, k) => {
578
- fields.push(k)
579
- dirs.push(v < 0 ? 'desc' : 'asc')
580
- })
581
- }
582
- if (!isEmpty(fields)) collection = orderBy(collection, fields, dirs)
583
- const data = collection.slice(offset, offset + limit)
584
-
585
- return {
586
- data,
587
- page,
588
- limit,
589
- count,
590
- pages: Math.ceil(collection.length / limit)
591
- }
592
- }
593
-
594
512
  parseDur = (val) => {
595
513
  return isNumber(val) ? val : ms(val)
596
514
  }
@@ -603,6 +521,7 @@ class BajoCore extends Plugin {
603
521
 
604
522
  parseObject = (input, options = {}) => {
605
523
  const { silent = true, parseValue = false, lang, ns } = options
524
+ const { isSet } = this.lib.aneka
606
525
  const translate = (item) => {
607
526
  const scope = ns ? this.app[ns] : this
608
527
  const [text, ...args] = item.split('|')
@@ -622,7 +541,7 @@ class BajoCore extends Plugin {
622
541
  else if (parseValue) obj[k][idx] = dotenvParseVariables(set({}, 'item', obj[k][idx]), { assignToProcessEnv: false }).item
623
542
  if (isArray(obj[k][idx])) obj[k][idx] = obj[k][idx].map(item => typeof item === 'string' ? item.trim() : item)
624
543
  })
625
- } else if (this.isSet(v)) {
544
+ } else if (isSet(v)) {
626
545
  if (isString(v) && v.startsWith('t:') && lang) v = translate(v.slice(2))
627
546
  try {
628
547
  if (statics.includes(v)) obj[k] = v
@@ -647,15 +566,12 @@ class BajoCore extends Plugin {
647
566
  return obj
648
567
  }
649
568
 
650
- pascalCase = (text) => {
651
- return upperFirst(camelCase(text))
652
- }
653
-
654
569
  pick = (obj, items, excludeUnset) => {
570
+ const { isSet } = this.lib.aneka
655
571
  const result = {}
656
572
  for (const item of items) {
657
573
  const [k, nk] = item.split(':')
658
- if (excludeUnset && !this.isSet(obj[k])) continue
574
+ if (excludeUnset && !isSet(obj[k])) continue
659
575
  result[nk ?? k] = obj[k]
660
576
  }
661
577
  return result
@@ -711,11 +627,6 @@ class BajoCore extends Plugin {
711
627
  return this.parseObject(JSON.parse(resp))
712
628
  }
713
629
 
714
- round = (val, scale = 0) => {
715
- scale = scale <= 0 ? 1 : 10 ** scale
716
- return Math.round(val * scale) / scale
717
- }
718
-
719
630
  runHook = async (hookName, ...args) => {
720
631
  const [ns, path] = (hookName ?? '').split(':')
721
632
  let fns = filter(this.app.bajo.hooks, { ns, path })
@@ -745,44 +656,6 @@ class BajoCore extends Plugin {
745
656
  if (printSaved) print.succeed('savedAs%s', path.resolve(fname), { skipSilence: true })
746
657
  return fname
747
658
  }
748
-
749
- // based on: https://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript
750
- secToHms = (secs, ms) => {
751
- let remain
752
- if (ms) {
753
- remain = secs % 1000
754
- secs = Math.floor(secs / 1000)
755
- }
756
- const secNum = parseInt(secs, 10)
757
- const hours = Math.floor(secNum / 3600)
758
- const minutes = Math.floor(secNum / 60) % 60
759
- const seconds = secNum % 60
760
-
761
- let hms = [hours, minutes, seconds]
762
- .map(v => v < 10 ? '0' + v : v)
763
- .filter((v, i) => v !== '00' || i > 0)
764
- .join(':')
765
- if (ms) hms += '+' + padStart(remain, 3, '0')
766
- return hms
767
- }
768
-
769
- titleize = (text, { ignores = [], replacement = {} } = {}) => {
770
- const defIgnores = ['or', 'and', 'of', 'with']
771
- const replacer = {}
772
- forOwn(replacement, (v, k) => {
773
- const id = this.generateId('int')
774
- replacer[id] = k
775
- text = text.replace(k, ` ${id} `)
776
- })
777
- return map(words(text), t => {
778
- forOwn(replacer, (v, k) => {
779
- if (k === t) t = replacement[replacer[k]]
780
- })
781
- ignores = uniq(concat(ignores, defIgnores))
782
- if (ignores.includes(t)) return t
783
- return upperFirst(t)
784
- }).join(' ')
785
- }
786
659
  }
787
660
 
788
661
  export default BajoCore
@@ -13,7 +13,8 @@ class BajoPlugin extends Plugin {
13
13
  }
14
14
 
15
15
  loadConfig = async () => {
16
- const { log, getModuleDir, readJson, defaultsDeep, parseObject } = this.app.bajo
16
+ const { defaultsDeep } = this.lib.aneka
17
+ const { log, getModuleDir, readJson, parseObject } = this.app.bajo
17
18
  log.trace('- %s', this.name)
18
19
  const dir = this.name === this.app.bajo.mainNs ? (`${this.app.bajo.dir.base}/${this.app.bajo.mainNs}`) : getModuleDir(this.pkgName)
19
20
  let cfg = await readAllConfigs.call(this.app, `${dir}/plugin/config`)
@@ -8,6 +8,7 @@ import { sprintf } from 'sprintf-js'
8
8
  import outmatch from 'outmatch'
9
9
  import dayjs from '../lib/dayjs.js'
10
10
  import fs from 'fs-extra'
11
+ import aneka from 'aneka/index.js'
11
12
 
12
13
  function outmatchNs (source, pattern) {
13
14
  const { breakNsPath } = this.app.bajo
@@ -28,7 +29,8 @@ const lib = {
28
29
  fastGlob,
29
30
  sprintf,
30
31
  outmatch,
31
- dayjs
32
+ dayjs,
33
+ aneka
32
34
  }
33
35
 
34
36
  const { get, isEmpty, cloneDeep, omit, isPlainObject, camelCase } = lodash
@@ -71,7 +71,7 @@ class Print {
71
71
  let opts = {}
72
72
  if (isPlainObject(args.slice(-1)[0])) opts = args.pop()
73
73
  this.opts.isSilent = !!(config.silent || this.opts.isSilent)
74
- this.opts = this.plugin.app.bajo.defaultsDeep(opts, this.opts)
74
+ this.opts = this.plugin.lib.aneka.defaultsDeep(opts, this.opts)
75
75
  }
76
76
 
77
77
  setText = (text, ...args) => {
@@ -89,8 +89,8 @@ class Print {
89
89
 
90
90
  getElapsed = (unit = 'hms') => {
91
91
  const u = unit === 'hms' ? 'second' : unit
92
- const elapsed = this.plugin.app.bajo.lib.dayjs().diff(this.startTime, u)
93
- return unit === 'hms' ? this.plugin.app.bajo.secToHms(elapsed) : elapsed
92
+ const elapsed = this.plugin.lib.dayjs().diff(this.startTime, u)
93
+ return unit === 'hms' ? this.plugin.lib.aneka.secToHms(elapsed) : elapsed
94
94
  }
95
95
 
96
96
  start = (text, ...args) => {
@@ -13,7 +13,7 @@ async function readAllConfigs (base) {
13
13
  } catch (err) {
14
14
  if (!['BAJO_CONFIG_FILE_NOT_FOUND'].includes(err.code)) throw err
15
15
  }
16
- return this.bajo.defaultsDeep({}, ext, cfg)
16
+ return this.bajo.lib.aneka.defaultsDeep({}, ext, cfg)
17
17
  }
18
18
 
19
19
  export default readAllConfigs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajo",
3
- "version": "1.1.17",
3
+ "version": "1.1.18",
4
4
  "description": "A framework to build a giant monstrous app rapidly",
5
5
  "main": "boot/index.js",
6
6
  "scripts": {
@@ -26,6 +26,7 @@
26
26
  "homepage": "https://github.com/ardhi/bajo#readme",
27
27
  "dependencies": {
28
28
  "add-filename-increment": "^1.0.0",
29
+ "aneka": "^0.1.4",
29
30
  "dayjs": "^1.11.13",
30
31
  "deep-freeze-strict": "^1.1.1",
31
32
  "delay": "^6.0.0",