bajo 1.1.17 → 1.1.19

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
@@ -310,8 +273,9 @@ class BajoCore extends Plugin {
310
273
  if (value instanceof Date) type = 'datetime'
311
274
  }
312
275
  if (['float', 'double'].includes(type) && this.app.bajoSpatial) {
313
- if (options.latitude) return this.app.bajoSpatial.latToDms(value)
314
- if (options.longitude) return this.app.bajoSpatial.lngToDms(value)
276
+ const { latToDms, lngToDms } = this.app.bajoSpatial.lib.anekaSpatial
277
+ if (options.latitude) return latToDms(value)
278
+ if (options.longitude) return lngToDms(value)
315
279
  }
316
280
  if (['integer', 'smallint', 'float', 'double'].includes(type)) {
317
281
  value = ['integer', 'smallint'].includes(type) ? parseInt(value) : parseFloat(value)
@@ -321,21 +285,21 @@ class BajoCore extends Plugin {
321
285
  }
322
286
  }
323
287
  if (['integer', 'smallint'].includes(type)) {
324
- const setting = this.defaultsDeep(options.integer, format.integer)
288
+ const setting = defaultsDeep(options.integer, format.integer)
325
289
  value = new Intl.NumberFormat(lang, setting).format(Math.round(value))
326
290
  return valueFormatted && options.withUnit ? valueFormatted : value
327
291
  }
328
292
  if (['float', 'double'].includes(type)) {
329
- const setting = this.defaultsDeep(options[type], format[type])
293
+ const setting = defaultsDeep(options[type], format[type])
330
294
  value = new Intl.NumberFormat(lang, setting).format(value)
331
295
  return valueFormatted && options.withUnit ? valueFormatted : value
332
296
  }
333
297
  if (['datetime', 'date'].includes(type)) {
334
- const setting = this.defaultsDeep(options[type], format[type])
298
+ const setting = defaultsDeep(options[type], format[type])
335
299
  return new Intl.DateTimeFormat(lang, setting).format(new Date(value))
336
300
  }
337
301
  if (['time'].includes(type)) {
338
- const setting = this.defaultsDeep(options.time, format.time)
302
+ const setting = defaultsDeep(options.time, format.time)
339
303
  return new Intl.DateTimeFormat(lang, setting).format(new Date(`1970-01-01T${value}Z`))
340
304
  }
341
305
  if (['array'].includes(type)) return value.join(', ')
@@ -383,10 +347,6 @@ class BajoCore extends Plugin {
383
347
  return dir
384
348
  }
385
349
 
386
- getKeyByValue = (object, value) => {
387
- return Object.keys(object).find(key => object[key] === value)
388
- }
389
-
390
350
  getMethod = (name = '', thrown = true) => {
391
351
  const { ns, path } = this.breakNsPath(name)
392
352
  const method = get(this.app, `${ns}.${path}`)
@@ -467,11 +427,12 @@ class BajoCore extends Plugin {
467
427
  }
468
428
 
469
429
  importPkg = async (...pkgs) => {
430
+ const { defaultsDeep } = this.lib.aneka
470
431
  const result = {}
471
432
  const notFound = []
472
433
  let opts = { returnDefault: true, thrownNotFound: false }
473
434
  if (isPlainObject(last(pkgs))) {
474
- opts = this.defaultsDeep(pkgs.pop(), opts)
435
+ opts = defaultsDeep(pkgs.pop(), opts)
475
436
  }
476
437
  for (const pkg of pkgs) {
477
438
  const { ns, path: name } = this.breakNsPath(pkg)
@@ -501,22 +462,6 @@ class BajoCore extends Plugin {
501
462
  return values(result)
502
463
  }
503
464
 
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
465
  isEmptyDir = async (dir) => {
521
466
  await fs.exists(dir)
522
467
  return await emptyDir(dir)
@@ -528,10 +473,6 @@ class BajoCore extends Plugin {
528
473
  return indexOf(levels, level) >= logLevel
529
474
  }
530
475
 
531
- isSet = (input) => {
532
- return ![null, undefined].includes(input)
533
- }
534
-
535
476
  isValidApp = (dir) => {
536
477
  if (!dir) dir = this.app.dir
537
478
  dir = resolvePath(dir)
@@ -549,13 +490,14 @@ class BajoCore extends Plugin {
549
490
  }
550
491
 
551
492
  join = (array, sep) => {
493
+ const { isSet } = this.lib.aneka
552
494
  const translate = val => {
553
495
  if (this && this.print) return this.print.write(val).toLowerCase()
554
496
  return val
555
497
  }
556
498
  if (array.length === 0) return translate('none')
557
499
  if (array.length === 1) return array[0]
558
- if (this.isSet(sep) && !isPlainObject(sep)) return array.join(sep)
500
+ if (isSet(sep) && !isPlainObject(sep)) return array.join(sep)
559
501
  let { separator = ', ', joiner = 'and' } = sep ?? {}
560
502
  joiner = translate(joiner)
561
503
  const last = (array.pop() ?? '').trim()
@@ -568,29 +510,6 @@ class BajoCore extends Plugin {
568
510
  return `${num[0]}${isEmpty(unit) ? defUnit : unit[0]}`
569
511
  }
570
512
 
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
513
  parseDur = (val) => {
595
514
  return isNumber(val) ? val : ms(val)
596
515
  }
@@ -603,6 +522,7 @@ class BajoCore extends Plugin {
603
522
 
604
523
  parseObject = (input, options = {}) => {
605
524
  const { silent = true, parseValue = false, lang, ns } = options
525
+ const { isSet } = this.lib.aneka
606
526
  const translate = (item) => {
607
527
  const scope = ns ? this.app[ns] : this
608
528
  const [text, ...args] = item.split('|')
@@ -622,7 +542,7 @@ class BajoCore extends Plugin {
622
542
  else if (parseValue) obj[k][idx] = dotenvParseVariables(set({}, 'item', obj[k][idx]), { assignToProcessEnv: false }).item
623
543
  if (isArray(obj[k][idx])) obj[k][idx] = obj[k][idx].map(item => typeof item === 'string' ? item.trim() : item)
624
544
  })
625
- } else if (this.isSet(v)) {
545
+ } else if (isSet(v)) {
626
546
  if (isString(v) && v.startsWith('t:') && lang) v = translate(v.slice(2))
627
547
  try {
628
548
  if (statics.includes(v)) obj[k] = v
@@ -647,15 +567,12 @@ class BajoCore extends Plugin {
647
567
  return obj
648
568
  }
649
569
 
650
- pascalCase = (text) => {
651
- return upperFirst(camelCase(text))
652
- }
653
-
654
570
  pick = (obj, items, excludeUnset) => {
571
+ const { isSet } = this.lib.aneka
655
572
  const result = {}
656
573
  for (const item of items) {
657
574
  const [k, nk] = item.split(':')
658
- if (excludeUnset && !this.isSet(obj[k])) continue
575
+ if (excludeUnset && !isSet(obj[k])) continue
659
576
  result[nk ?? k] = obj[k]
660
577
  }
661
578
  return result
@@ -711,11 +628,6 @@ class BajoCore extends Plugin {
711
628
  return this.parseObject(JSON.parse(resp))
712
629
  }
713
630
 
714
- round = (val, scale = 0) => {
715
- scale = scale <= 0 ? 1 : 10 ** scale
716
- return Math.round(val * scale) / scale
717
- }
718
-
719
631
  runHook = async (hookName, ...args) => {
720
632
  const [ns, path] = (hookName ?? '').split(':')
721
633
  let fns = filter(this.app.bajo.hooks, { ns, path })
@@ -745,44 +657,6 @@ class BajoCore extends Plugin {
745
657
  if (printSaved) print.succeed('savedAs%s', path.resolve(fname), { skipSilence: true })
746
658
  return fname
747
659
  }
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
660
  }
787
661
 
788
662
  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.19",
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",