bajo 2.11.0 → 2.12.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.
- package/class/bajo.js +69 -28
- package/class/helper/base.js +5 -4
- package/extend/bajo/intl/en-US.json +3 -1
- package/extend/bajo/intl/id.json +3 -1
- package/package.json +1 -1
- package/wiki/CHANGES.md +10 -0
package/class/bajo.js
CHANGED
|
@@ -91,7 +91,7 @@ class Bajo extends Plugin {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
breakNsPathFromFile = ({ file, dir,
|
|
94
|
+
breakNsPathFromFile = ({ file = '', dir = '', ns, suffix = '', getType } = {}) => {
|
|
95
95
|
let item = file.replace(dir + suffix, '')
|
|
96
96
|
let type
|
|
97
97
|
if (getType) {
|
|
@@ -103,12 +103,12 @@ class Bajo extends Plugin {
|
|
|
103
103
|
let [name, _path] = item.split('@')
|
|
104
104
|
if (!_path) {
|
|
105
105
|
_path = name
|
|
106
|
-
name =
|
|
106
|
+
name = ns
|
|
107
107
|
}
|
|
108
108
|
_path = camelCase(_path)
|
|
109
109
|
const names = map(name.split('.'), n => camelCase(n))
|
|
110
|
-
const [
|
|
111
|
-
return { ns, subNs, path: _path, fullNs: names.join('.'), type }
|
|
110
|
+
const [_ns, subNs] = names
|
|
111
|
+
return { ns: _ns, subNs, path: _path, fullNs: names.join('.'), type }
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
@@ -301,15 +301,14 @@ class Bajo extends Plugin {
|
|
|
301
301
|
scope = item
|
|
302
302
|
item = args.shift()
|
|
303
303
|
}
|
|
304
|
-
const bajo = scope.app.bajo
|
|
305
304
|
if (isString(item)) {
|
|
306
|
-
if (item.startsWith('applet:') &&
|
|
305
|
+
if (item.startsWith('applet:') && this.app.applets.length > 0) {
|
|
307
306
|
const [, ns, path] = item.split(':')
|
|
308
|
-
const applet = find(
|
|
309
|
-
if (applet &&
|
|
307
|
+
const applet = find(this.app.applets, a => (a.ns === ns || a.alias === ns))
|
|
308
|
+
if (applet && this.app.bajoCli) result = await this.app.bajoCli.runApplet(applet, path, ...args)
|
|
310
309
|
} else {
|
|
311
310
|
const [ns, method, ...params] = item.split(':')
|
|
312
|
-
const fn =
|
|
311
|
+
const fn = this.getMethod(`${ns}:${method}`)
|
|
313
312
|
if (fn) {
|
|
314
313
|
if (params.length > 0) args.unshift(...params)
|
|
315
314
|
result = await fn(...args)
|
|
@@ -454,7 +453,7 @@ class Bajo extends Plugin {
|
|
|
454
453
|
* @returns {string} Formatted value
|
|
455
454
|
*/
|
|
456
455
|
format = (value, type, options = {}) => {
|
|
457
|
-
const { defaultsDeep } = this.app.lib.aneka
|
|
456
|
+
const { defaultsDeep, isSet } = this.app.lib.aneka
|
|
458
457
|
const { format } = this.config.intl
|
|
459
458
|
const { emptyValue = format.emptyValue } = options
|
|
460
459
|
const lang = options.lang ?? this.config.lang
|
|
@@ -496,6 +495,7 @@ class Bajo extends Plugin {
|
|
|
496
495
|
}
|
|
497
496
|
if (['array'].includes(type)) return value.join(', ')
|
|
498
497
|
if (['object'].includes(type)) return JSON.stringify(value)
|
|
498
|
+
if (['boolean'].includes(type) && isSet(value)) return value ? this.t('true', { lang }) : this.t('false', { lang })
|
|
499
499
|
return value
|
|
500
500
|
}
|
|
501
501
|
|
|
@@ -800,15 +800,17 @@ class Bajo extends Plugin {
|
|
|
800
800
|
* @param {string} [options.lastSeparator=and] - Text to use as the last separator
|
|
801
801
|
* @returns {string}
|
|
802
802
|
*/
|
|
803
|
-
join = (array, options) => {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
803
|
+
join = (array, options = {}) => {
|
|
804
|
+
let separator = ', '
|
|
805
|
+
let lastSeparator = 'and'
|
|
806
|
+
let lang
|
|
807
|
+
if (isString(options)) separator = options
|
|
808
|
+
else ({ separator, lastSeparator, lang } = options)
|
|
809
|
+
const translate = (val) => {
|
|
810
|
+
return this.t(val, { lang }).toLowerCase()
|
|
807
811
|
}
|
|
808
812
|
if (array.length === 0) return translate('none')
|
|
809
813
|
if (array.length === 1) return array[0]
|
|
810
|
-
if (isSet(options) && !isPlainObject(options)) return array.join(options)
|
|
811
|
-
let { separator = ', ', lastSeparator = 'and' } = options ?? {}
|
|
812
814
|
lastSeparator = translate(lastSeparator)
|
|
813
815
|
const last = (array.pop() ?? '').trim()
|
|
814
816
|
return array.map(a => (a + '').trim()).join(separator) + ` ${lastSeparator} ${last}`
|
|
@@ -841,14 +843,53 @@ class Bajo extends Plugin {
|
|
|
841
843
|
* @param {boolean} [options.ignoreError] - Any exception will be silently discarded
|
|
842
844
|
* @param {string} [options.ns] - If given, use this as the scope
|
|
843
845
|
* @param {string} [options.pattern] - If given and auto detection is on (extension is ```.*```), it will be used for instead the default one
|
|
844
|
-
* @param {Object} [options.globOptions={}] - {@link https://github.com/mrmlnc/fast-glob|fast-glob} options
|
|
845
846
|
* @param {Object} [options.defValue={}] - Default value to use if value returned empty
|
|
846
|
-
* @param {Object} [options.
|
|
847
|
+
* @param {Object} [options.parserOpts={}] - Parser setting
|
|
848
|
+
* @param {Object} [options.globOpts={}] - {@link https://github.com/mrmlnc/fast-glob|fast-glob} options
|
|
847
849
|
* @returns {Object}
|
|
848
850
|
*/
|
|
849
|
-
readConfig = async (file,
|
|
851
|
+
readConfig = async (file, options = {}) => {
|
|
850
852
|
const { parseObject } = this.app.lib
|
|
851
|
-
|
|
853
|
+
const { defaultsDeep } = this.app.lib.aneka
|
|
854
|
+
const { uniq, isString, isArray, findIndex, isPlainObject } = this.app.lib._
|
|
855
|
+
let { ns, baseNs, extend, pattern, ignoreError = true, defValue = {}, parserOpts = {}, globOpts = {} } = options
|
|
856
|
+
|
|
857
|
+
const output = async (obj) => {
|
|
858
|
+
const orig = parseObject(obj)
|
|
859
|
+
if (!baseNs || extend === false) return orig
|
|
860
|
+
const { suffix = '', keys = [] } = options
|
|
861
|
+
let bases = this.app.getAllNs()
|
|
862
|
+
if (isString(extend)) extend = extend.split(',').map(i => i.trim)
|
|
863
|
+
if (isArray(extend)) bases = [...extend, 'main']
|
|
864
|
+
bases = uniq(bases)
|
|
865
|
+
let ext = isArray(obj) ? [] : {}
|
|
866
|
+
const dir = this.app[ns].dir.pkg
|
|
867
|
+
let [names, _path] = file.split(':')
|
|
868
|
+
if (file.slice(0, names.length + 1) !== `${ns}:`) _path = file.slice(dir.length + 1)
|
|
869
|
+
if (_path.startsWith('extend/')) _path = _path.slice(7)
|
|
870
|
+
if (_path.startsWith(`${baseNs}/`)) _path = _path.slice(baseNs.length + 1)
|
|
871
|
+
_path = _path.slice(0, -(path.extname(_path).length)) + '.*'
|
|
872
|
+
const opts = omit(options, ['suffix', 'keys', 'extend'])
|
|
873
|
+
opts.parserOpts = opts.parserOpts ?? {}
|
|
874
|
+
opts.parserOpts.args = opts.parserOpts.args ?? []
|
|
875
|
+
const idx = findIndex(opts.parserOpts.args, item => {
|
|
876
|
+
return isPlainObject(item) && Object.keys(item)[0] === '_orig'
|
|
877
|
+
})
|
|
878
|
+
if (idx > -1) opts.parserOpts.args[idx] = { _orig: orig }
|
|
879
|
+
else opts.parserOpts.args.push({ _orig: orig })
|
|
880
|
+
|
|
881
|
+
for (const base of bases) {
|
|
882
|
+
if (!this.app[base]) continue
|
|
883
|
+
const fileExt = `${this.app[base].dir.pkg}/extend/${baseNs}/extend/${ns}${suffix}/${_path}`
|
|
884
|
+
const result = parseObject(await this.readConfig(fileExt, { ...opts, extend: false }))
|
|
885
|
+
if (isEmpty(result)) continue
|
|
886
|
+
if (isArray(result)) ext = [...result, ...ext]
|
|
887
|
+
else ext = defaultsDeep({}, result, ext)
|
|
888
|
+
}
|
|
889
|
+
return isArray(orig) ? [...orig, ...ext] : defaultsDeep({}, keys.length > 0 ? pick(ext, keys) : ext, orig)
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
parserOpts.readFromFile = true
|
|
852
893
|
if (!ns) ns = this.ns
|
|
853
894
|
file = resolvePath(this.getPluginFile(file))
|
|
854
895
|
let ext = path.extname(file)
|
|
@@ -856,22 +897,22 @@ class Bajo extends Plugin {
|
|
|
856
897
|
ext = ext.toLowerCase()
|
|
857
898
|
if (ext === '.js') {
|
|
858
899
|
const { readHandler } = find(this.app.configHandlers, { ext })
|
|
859
|
-
return
|
|
900
|
+
return await output(await readHandler.call(this.app[ns], file, parserOpts))
|
|
860
901
|
}
|
|
861
|
-
if (ext === '.json') return await this.fromJson(file,
|
|
902
|
+
if (ext === '.json') return await output(await this.fromJson(file, parserOpts))
|
|
862
903
|
if (!['', '.*'].includes(ext)) {
|
|
863
904
|
const item = find(this.app.configHandlers, { ext })
|
|
864
905
|
if (!item) {
|
|
865
906
|
if (!ignoreError) throw this.error('cantParse%s', file, { code: 'BAJO_CONFIG_NO_PARSER' })
|
|
866
|
-
return
|
|
907
|
+
return await output(defValue)
|
|
867
908
|
}
|
|
868
|
-
return
|
|
909
|
+
return await output(await item.readHandler.call(this.app[ns], file, parserOpts))
|
|
869
910
|
}
|
|
870
911
|
const item = pattern ?? `${fname}.{${map(map(this.app.configHandlers, 'ext'), k => k.slice(1)).join(',')}}`
|
|
871
|
-
const files = await fastGlob(item,
|
|
912
|
+
const files = await fastGlob(item, globOpts ?? {})
|
|
872
913
|
if (files.length === 0) {
|
|
873
914
|
if (!ignoreError) throw this.error('noConfigFileFound', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
|
|
874
|
-
return
|
|
915
|
+
return await output(defValue)
|
|
875
916
|
}
|
|
876
917
|
let config = defValue
|
|
877
918
|
for (const f of files) {
|
|
@@ -881,10 +922,10 @@ class Bajo extends Plugin {
|
|
|
881
922
|
if (!ignoreError) throw this.error('cantParse%s', f, { code: 'BAJO_CONFIG_NO_PARSER' })
|
|
882
923
|
continue
|
|
883
924
|
}
|
|
884
|
-
config = await item.readHandler.call(this.app[ns], f,
|
|
925
|
+
config = await item.readHandler.call(this.app[ns], f, parserOpts)
|
|
885
926
|
if (!isEmpty(config)) break
|
|
886
927
|
}
|
|
887
|
-
return
|
|
928
|
+
return await output(config)
|
|
888
929
|
}
|
|
889
930
|
|
|
890
931
|
/**
|
package/class/helper/base.js
CHANGED
|
@@ -99,16 +99,17 @@ export async function checkDependencies () {
|
|
|
99
99
|
* @fires bajo:afterCollectHooks
|
|
100
100
|
*/
|
|
101
101
|
export async function collectHooks () {
|
|
102
|
-
const { eachPlugins, runHook, isLogInRange, importModule
|
|
102
|
+
const { eachPlugins, runHook, isLogInRange, importModule } = this.bajo
|
|
103
103
|
const me = this
|
|
104
104
|
me.bajo.log.trace('collecting%s', this.t('hooks'))
|
|
105
105
|
// collects
|
|
106
106
|
await eachPlugins(async function ({ dir, file }) {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
107
|
+
const _file = file.replace(dir + '/hook/', '').replace('.js', '')
|
|
108
|
+
const [names, path] = _file.split('@')
|
|
109
|
+
const [ns, subNs] = names.split('.').map(n => camelCase(n))
|
|
109
110
|
const mod = await importModule(file, { asHandler: true })
|
|
110
111
|
if (!mod) return undefined
|
|
111
|
-
merge(mod, { ns, subNs, path, src:
|
|
112
|
+
merge(mod, { ns, subNs, path: camelCase(path), src: this.ns })
|
|
112
113
|
me.bajo.hooks.push(mod)
|
|
113
114
|
}, { glob: 'hook/**/*.js', prefix: me.bajo.ns })
|
|
114
115
|
// for log trace purpose only
|
|
@@ -182,5 +182,7 @@
|
|
|
182
182
|
"fieldError%s%s": "'%s': %s|lowerFirst",
|
|
183
183
|
"reservedName%s%s": "%s|upperFirst name '%s' is a reserved name. Please rename to something else",
|
|
184
184
|
"missing%s%s": "Missing '%s' %s",
|
|
185
|
-
"processing...": "Processing..."
|
|
185
|
+
"processing...": "Processing...",
|
|
186
|
+
"true": "True",
|
|
187
|
+
"false": "False"
|
|
186
188
|
}
|
package/extend/bajo/intl/id.json
CHANGED
|
@@ -182,5 +182,7 @@
|
|
|
182
182
|
"fieldError%s%s": "'%s': %s|lowerFirst",
|
|
183
183
|
"reservedName%s%s": "Nama %s|lowerFirst '%s' adalah nama tang di reserve. Silahkan gunakan nama lainnya",
|
|
184
184
|
"missing%s%s": "%s|upperFirst '%s' tidak ditemukan",
|
|
185
|
-
"processing...": "Memroses..."
|
|
185
|
+
"processing...": "Memroses...",
|
|
186
|
+
"true": "Benar",
|
|
187
|
+
"false": "Salah"
|
|
186
188
|
}
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-04-23
|
|
4
|
+
|
|
5
|
+
- [2.12.0] Remove ```breakNsPathFromFile()```
|
|
6
|
+
- [2.12.0] Add feature to read in extended path ```readConfig()```
|
|
7
|
+
|
|
8
|
+
## 2026-04-11
|
|
9
|
+
|
|
10
|
+
- [2.11.1] Bug fix in ```join()```
|
|
11
|
+
- [2.11.1] Bug fix in ```format()```
|
|
12
|
+
|
|
3
13
|
## 2026-04-07
|
|
4
14
|
|
|
5
15
|
- [2.11.0] Change ```dispose()``` to be an async function
|