bajo 2.17.0 → 2.18.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/app.js +100 -1
- package/class/bajo.js +6 -77
- package/class/cache.js +1 -2
- package/lib/import-module.js +1 -1
- package/package.json +1 -1
- package/wiki/CHANGES.md +5 -0
package/class/app.js
CHANGED
|
@@ -3,6 +3,7 @@ import Bajo from './bajo.js'
|
|
|
3
3
|
import Base from './base.js'
|
|
4
4
|
import Cache from './cache.js'
|
|
5
5
|
import Tools from './tools.js'
|
|
6
|
+
import Plugin from './plugin.js'
|
|
6
7
|
import { outmatchNs, parseObject, lib, runAsApplet } from './_helper.js'
|
|
7
8
|
import { fileURLToPath } from 'url'
|
|
8
9
|
|
|
@@ -255,6 +256,103 @@ class App {
|
|
|
255
256
|
return this.pluginPkgs.map(pkg => camelCase(pkg))
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Get loaded plugins
|
|
261
|
+
*
|
|
262
|
+
* @method
|
|
263
|
+
* @param {string[]} [nss] - Array of namespaces. If empty, it returns all loaded plugins
|
|
264
|
+
* @returns {TPlugin[]}
|
|
265
|
+
*/
|
|
266
|
+
getPlugins = (nss) => {
|
|
267
|
+
const allNs = nss ?? this.getAllNs()
|
|
268
|
+
return allNs.map(ns => this[ns])
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get all plugins loaded plugins
|
|
273
|
+
*
|
|
274
|
+
* @method
|
|
275
|
+
* @returns {TPlugin[]}
|
|
276
|
+
*/
|
|
277
|
+
getAllPlugins = () => {
|
|
278
|
+
return this.getPlugins()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get plugin by name
|
|
283
|
+
*
|
|
284
|
+
* @method
|
|
285
|
+
* @param {string} name - Plugin name/namespace or alias
|
|
286
|
+
* @param {boolean} [silent] - If ```true```, silently return undefined even on error
|
|
287
|
+
* @returns {Object} Plugin object
|
|
288
|
+
*/
|
|
289
|
+
getPlugin = (name, silent) => {
|
|
290
|
+
if (!this[name]) {
|
|
291
|
+
// alias?
|
|
292
|
+
let plugin
|
|
293
|
+
for (const key in this) {
|
|
294
|
+
const item = this[key]
|
|
295
|
+
if (item instanceof Plugin && (item.alias === name || item.pkgName === name)) {
|
|
296
|
+
plugin = item
|
|
297
|
+
break
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (!plugin) {
|
|
301
|
+
if (silent) return false
|
|
302
|
+
throw this.bajo.error('pluginWithNameAliasNotLoaded%s', name)
|
|
303
|
+
}
|
|
304
|
+
name = plugin.ns
|
|
305
|
+
}
|
|
306
|
+
return this[name]
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Get plugin data directory
|
|
311
|
+
*
|
|
312
|
+
* @method
|
|
313
|
+
* @param {string} name - Plugin name (namespace) or alias
|
|
314
|
+
* @param {boolean} [ensureDir=true] - Set ```true``` (default) to ensure directory is existed
|
|
315
|
+
* @returns {string}
|
|
316
|
+
*/
|
|
317
|
+
getPluginDataDir = (name, ensureDir = true) => {
|
|
318
|
+
const { fs } = this.lib
|
|
319
|
+
const plugin = this.getPlugin(name)
|
|
320
|
+
const dir = `${this.bajo.dir.data}/plugins/${plugin.ns}`
|
|
321
|
+
if (ensureDir) fs.ensureDirSync(dir)
|
|
322
|
+
return dir
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Resolve file path from:
|
|
327
|
+
*
|
|
328
|
+
* - local/absolute file
|
|
329
|
+
* - TNsPath (```myPlugin:/path/to/file.txt```)
|
|
330
|
+
* - file under node_modules, e.g. ```myPlugin:node_modules/some-package/file.txt```
|
|
331
|
+
*
|
|
332
|
+
* @method
|
|
333
|
+
* @param {string} file - File path, see above for supported types
|
|
334
|
+
* @returns {string} Resolved file path
|
|
335
|
+
*/
|
|
336
|
+
getPluginFile = (file) => {
|
|
337
|
+
const { currentLoc } = this.lib.aneka
|
|
338
|
+
const { fs } = this.lib
|
|
339
|
+
const { trim } = this.lib._
|
|
340
|
+
if (!this) return file
|
|
341
|
+
if (file[0] === '.') file = `${currentLoc(import.meta).dir}/${trim(file.slice(1), '/')}`
|
|
342
|
+
if (file.includes(':')) {
|
|
343
|
+
if (file.slice(1, 2) === ':') return file // windows fs
|
|
344
|
+
const { ns, path } = this.bajo.breakNsPath(file, false)
|
|
345
|
+
if (ns !== 'file' && this && this[ns] && ns.length > 1) {
|
|
346
|
+
file = `${this[ns].dir.pkg}${path}`
|
|
347
|
+
if (path.startsWith('node_modules/')) {
|
|
348
|
+
file = `${this[ns].dir.pkg}/${path}`
|
|
349
|
+
if (!fs.existsSync(file)) file = `${this[ns].dir.pkg}/../${path.slice('node_modules/'.length)}`
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return file
|
|
354
|
+
}
|
|
355
|
+
|
|
258
356
|
/**
|
|
259
357
|
* Dumping variable on screen. Like ```console.log``` with configurable options. Useful for quick debugging and testing. You can also use it to dump variables in production without worrying about performance because it is using Bajo's built-in cache to store the result of util's inspect, so it will only be processed once for each unique variable.
|
|
260
358
|
*
|
|
@@ -273,7 +371,8 @@ class App {
|
|
|
273
371
|
dump = (...args) => {
|
|
274
372
|
let caller = getCallerFilename()
|
|
275
373
|
caller = caller ? fileURLToPath(caller) : 'Unavailable'
|
|
276
|
-
const
|
|
374
|
+
const opts = last(args)
|
|
375
|
+
const terminate = isPlainObject(opts) && opts.abort
|
|
277
376
|
if (terminate) args.pop()
|
|
278
377
|
const value = args.length === 1 ? args[0] : args
|
|
279
378
|
const options = { ...this.bajo.config.dump }
|
package/class/bajo.js
CHANGED
|
@@ -33,7 +33,7 @@ const {
|
|
|
33
33
|
last, get, has, values, dropRight, pick
|
|
34
34
|
} = lodash
|
|
35
35
|
|
|
36
|
-
const { resolvePath
|
|
36
|
+
const { resolvePath } = aneka
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* The Core. The main engine. The one and only plugin that control app's boot process and
|
|
@@ -172,7 +172,7 @@ class Bajo extends Plugin {
|
|
|
172
172
|
[ns, subNs, subSubNs] = ns.split('.')
|
|
173
173
|
if (checkNs) {
|
|
174
174
|
if (!this.app[ns]) {
|
|
175
|
-
const plugin = this.getPlugin(ns)
|
|
175
|
+
const plugin = this.app.getPlugin(ns)
|
|
176
176
|
if (plugin) ns = plugin.ns
|
|
177
177
|
}
|
|
178
178
|
if (!this.app[ns]) throw this.error('unknownPluginOrNotLoaded%s')
|
|
@@ -572,77 +572,6 @@ class Bajo extends Plugin {
|
|
|
572
572
|
return resolvePath(path.dirname(dir))
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
/**
|
|
576
|
-
* Get plugin data directory
|
|
577
|
-
*
|
|
578
|
-
* @method
|
|
579
|
-
* @param {string} name - Plugin name (namespace) or alias
|
|
580
|
-
* @param {boolean} [ensureDir=true] - Set ```true``` (default) to ensure directory is existed
|
|
581
|
-
* @returns {string}
|
|
582
|
-
*/
|
|
583
|
-
getPluginDataDir = (name, ensureDir = true) => {
|
|
584
|
-
const plugin = this.getPlugin(name)
|
|
585
|
-
const dir = `${this.app.bajo.dir.data}/plugins/${plugin.ns}`
|
|
586
|
-
if (ensureDir) fs.ensureDirSync(dir)
|
|
587
|
-
return dir
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Resolve file path from:
|
|
592
|
-
*
|
|
593
|
-
* - local/absolute file
|
|
594
|
-
* - TNsPath (```myPlugin:/path/to/file.txt```)
|
|
595
|
-
* - file under node_modules, e.g. ```myPlugin:node_modules/some-package/file.txt```
|
|
596
|
-
*
|
|
597
|
-
* @method
|
|
598
|
-
* @param {string} file - File path, see above for supported types
|
|
599
|
-
* @returns {string} Resolved file path
|
|
600
|
-
*/
|
|
601
|
-
getPluginFile = (file) => {
|
|
602
|
-
if (!this) return file
|
|
603
|
-
if (file[0] === '.') file = `${currentLoc(import.meta).dir}/${trim(file.slice(1), '/')}`
|
|
604
|
-
if (file.includes(':')) {
|
|
605
|
-
if (file.slice(1, 2) === ':') return file // windows fs
|
|
606
|
-
const { ns, path } = this.breakNsPath(file)
|
|
607
|
-
if (ns !== 'file' && this && this.app && this.app[ns] && ns.length > 1) {
|
|
608
|
-
file = `${this.app[ns].dir.pkg}${path}`
|
|
609
|
-
if (path.startsWith('node_modules/')) {
|
|
610
|
-
file = `${this.app[ns].dir.pkg}/${path}`
|
|
611
|
-
if (!fs.existsSync(file)) file = `${this.app[ns].dir.pkg}/../${path.slice('node_modules/'.length)}`
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
return file
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Get plugin by name
|
|
620
|
-
*
|
|
621
|
-
* @method
|
|
622
|
-
* @param {string} name - Plugin name/namespace or alias
|
|
623
|
-
* @param {boolean} [silent] - If ```true```, silently return undefined even on error
|
|
624
|
-
* @returns {Object} Plugin object
|
|
625
|
-
*/
|
|
626
|
-
getPlugin = (name, silent) => {
|
|
627
|
-
if (!this.app[name]) {
|
|
628
|
-
// alias?
|
|
629
|
-
let plugin
|
|
630
|
-
for (const key in this.app) {
|
|
631
|
-
const item = this.app[key]
|
|
632
|
-
if (item instanceof Plugin && (item.alias === name || item.pkgName === name)) {
|
|
633
|
-
plugin = item
|
|
634
|
-
break
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
if (!plugin) {
|
|
638
|
-
if (silent) return false
|
|
639
|
-
throw this.error('pluginWithNameAliasNotLoaded%s', name)
|
|
640
|
-
}
|
|
641
|
-
name = plugin.ns
|
|
642
|
-
}
|
|
643
|
-
return this.app[name]
|
|
644
|
-
}
|
|
645
|
-
|
|
646
575
|
/**
|
|
647
576
|
* Import file/module from any loaded plugins.
|
|
648
577
|
*
|
|
@@ -730,7 +659,7 @@ class Bajo extends Plugin {
|
|
|
730
659
|
* @returns {boolean}
|
|
731
660
|
*/
|
|
732
661
|
isEmptyDir = async (dir, filterFn) => {
|
|
733
|
-
dir = resolvePath(this.getPluginFile(dir))
|
|
662
|
+
dir = resolvePath(this.app.getPluginFile(dir))
|
|
734
663
|
await fs.exists(dir)
|
|
735
664
|
return await emptyDir(dir, filterFn)
|
|
736
665
|
}
|
|
@@ -916,7 +845,7 @@ class Bajo extends Plugin {
|
|
|
916
845
|
await this.runHook('bajo:beforeReadConfig', file, options)
|
|
917
846
|
parserOpts.readFromFile = true
|
|
918
847
|
if (!ns) ns = this.ns
|
|
919
|
-
file = resolvePath(this.getPluginFile(file))
|
|
848
|
+
file = resolvePath(this.app.getPluginFile(file))
|
|
920
849
|
let ext = path.extname(file)
|
|
921
850
|
const fname = path.dirname(file) + '/' + path.basename(file, ext)
|
|
922
851
|
ext = ext.toLowerCase()
|
|
@@ -1065,8 +994,8 @@ class Bajo extends Plugin {
|
|
|
1065
994
|
* @returns {string} Full file path
|
|
1066
995
|
*/
|
|
1067
996
|
saveAsDownload = async (file, item, printSaved = true) => {
|
|
1068
|
-
const { print
|
|
1069
|
-
const fname = increment(`${getPluginDataDir(this.ns)}/download/${trim(file, '/')}`, { fs: true })
|
|
997
|
+
const { print } = this.app.bajo
|
|
998
|
+
const fname = increment(`${this.app.getPluginDataDir(this.ns)}/download/${trim(file, '/')}`, { fs: true })
|
|
1070
999
|
const dir = path.dirname(fname)
|
|
1071
1000
|
if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
|
|
1072
1001
|
await fs.writeFile(fname, item, 'utf8')
|
package/class/cache.js
CHANGED
package/lib/import-module.js
CHANGED
|
@@ -43,7 +43,7 @@ async function importModule (file, { asDefaultImport = true, asHandler, noCache
|
|
|
43
43
|
return imported
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
if (this) file = this.getPluginFile(file)
|
|
46
|
+
if (this) file = this.app.getPluginFile(file)
|
|
47
47
|
if (!fs.existsSync(file)) return
|
|
48
48
|
let mod = await load(file, asDefaultImport, noCache)
|
|
49
49
|
if (!asHandler) return mod
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-06-12
|
|
4
|
+
|
|
5
|
+
- [2.18.0] Move plugin related methods to ```app```
|
|
6
|
+
- [2.18.0] Last argument of ```app.dump()``` serves as options if it a plain object with certain keys
|
|
7
|
+
|
|
3
8
|
## 2026-06-03
|
|
4
9
|
|
|
5
10
|
- [2.17.0] Combine all helpers to ```_helper.js```
|