bajo 2.0.2 → 2.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.
- package/.github/FUNDING.yml +0 -0
- package/.github/workflows/repo-lockdown.yml +0 -0
- package/.jsdoc.conf.json +0 -0
- package/.mocharc.json +4 -0
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/class/{misc → app}/log.js +73 -24
- package/class/app.js +65 -50
- package/class/bajo.js +43 -211
- package/class/base.js +25 -22
- package/class/helper/bajo.js +67 -60
- package/class/helper/base.js +34 -75
- package/class/{misc → plugin}/err.js +23 -18
- package/class/{misc → plugin}/print.js +7 -16
- package/class/plugin/tools.js +42 -0
- package/class/plugin.js +58 -54
- package/docs/App.html +0 -0
- package/docs/Bajo.html +0 -0
- package/docs/Base.html +0 -0
- package/docs/Err.html +0 -0
- package/docs/Log.html +0 -0
- package/docs/Plugin.html +0 -0
- package/docs/Print.html +0 -0
- package/docs/class_app.js.html +0 -0
- package/docs/class_bajo.js.html +0 -0
- package/docs/class_base.js.html +0 -0
- package/docs/class_helper_bajo.js.html +0 -0
- package/docs/class_helper_base.js.html +0 -0
- package/docs/class_misc_err.js.html +0 -0
- package/docs/class_misc_log.js.html +0 -0
- package/docs/class_misc_print.js.html +0 -0
- package/docs/class_plugin.js.html +0 -0
- package/docs/data/search.json +0 -0
- package/docs/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/global.html +0 -0
- package/docs/index.html +0 -0
- package/docs/index.js.html +0 -0
- package/docs/lib_current-loc.js.html +0 -0
- package/docs/lib_formats.js.html +0 -0
- package/docs/lib_import-module.js.html +0 -0
- package/docs/lib_log-levels.js.html +0 -0
- package/docs/lib_parse-args-argv.js.html +0 -0
- package/docs/lib_parse-env.js.html +0 -0
- package/docs/lib_resolve-path.js.html +0 -0
- package/docs/lib_shim.js.html +0 -0
- package/docs/module-Helper_Bajo.html +0 -0
- package/docs/module-Helper_Base.html +0 -0
- package/docs/module-Lib.html +0 -0
- package/docs/scripts/core.js +476 -477
- package/docs/scripts/core.min.js +0 -0
- package/docs/scripts/resize.js +36 -36
- package/docs/scripts/search.js +105 -105
- package/docs/scripts/search.min.js +0 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -0
- package/docs/scripts/third-party/fuse.js +1 -1
- package/docs/scripts/third-party/hljs-line-num-original.js +282 -285
- package/docs/scripts/third-party/hljs-line-num.js +1 -1
- package/docs/scripts/third-party/hljs-original.js +1195 -1202
- package/docs/scripts/third-party/hljs.js +1 -1
- package/docs/scripts/third-party/popper.js +1 -1
- package/docs/scripts/third-party/tippy.js +1 -1
- package/docs/scripts/third-party/tocbot.js +508 -509
- package/docs/scripts/third-party/tocbot.min.js +0 -0
- package/docs/static/bitcoin.jpeg +0 -0
- package/docs/static/home.md +0 -0
- package/docs/static/logo-ecosystem.png +0 -0
- package/docs/static/logo.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +0 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -0
- package/docs/styles/clean-jsdoc-theme-light.css +0 -0
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -0
- package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -0
- package/docs/styles/clean-jsdoc-theme.min.css +0 -0
- package/extend/bajo/intl/en-US.json +11 -5
- package/extend/bajo/intl/id.json +11 -5
- package/extend/waibuStatic/virtual.json +0 -0
- package/index.js +9 -1
- package/lib/find-deep.js +24 -0
- package/lib/formats.js +0 -0
- package/lib/freeze.js +16 -0
- package/lib/import-module.js +5 -3
- package/lib/index.js +6 -0
- package/lib/log-levels.js +0 -0
- package/package.json +5 -11
- package/test/base.test.js +108 -0
- package/wiki/CHANGES.md +63 -0
- package/wiki/CONFIG.md +7 -1
- package/wiki/CONTRIBUTING.md +0 -0
- package/wiki/DEV_GUIDE.md +0 -0
- package/wiki/ECOSYSTEM.md +0 -0
- package/wiki/GETTING-STARTED.md +1 -1
- package/wiki/USER-GUIDE.md +0 -0
- package/lib/current-loc.js +0 -33
- package/lib/parse-args-argv.js +0 -80
- package/lib/parse-env.js +0 -50
- package/lib/resolve-path.js +0 -24
- package/lib/shim.js +0 -37
|
File without changes
|
package/docs/static/bitcoin.jpeg
CHANGED
|
File without changes
|
package/docs/static/home.md
CHANGED
|
File without changes
|
|
File without changes
|
package/docs/static/logo.png
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"appRunningAsApplet": "App runs in applet mode",
|
|
23
23
|
"setupBootOrder": "Setup boot order",
|
|
24
24
|
"configHandlers%s": "Config handlers: %s",
|
|
25
|
-
"
|
|
25
|
+
"dataDir%s": "Data dir: %s",
|
|
26
|
+
"exited%s": "- %s exited",
|
|
26
27
|
"appShutdown": "App shutdown",
|
|
27
28
|
"appletModeActivated": "Applet mode activated",
|
|
28
|
-
"collected%s%d": "%s
|
|
29
|
-
"attachMethods": "Attach methods",
|
|
29
|
+
"collected%s%d": "Collected %s: %d",
|
|
30
30
|
"readConfigs": "Read configurations",
|
|
31
31
|
"checkAliasNameClash": "Checking alias & name clashes",
|
|
32
32
|
"checkDeps": "Checking dependencies",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"offlineL": "offline",
|
|
127
127
|
"reconnectingL": "reconnecting",
|
|
128
128
|
"connMustHave%s": "Connection must have '%s'",
|
|
129
|
-
"notFound%s%s": "%s '%s' not found",
|
|
129
|
+
"notFound%s%s": "%s|upperFirst '%s' not found",
|
|
130
130
|
"connection": "Connection",
|
|
131
131
|
"file": "File",
|
|
132
132
|
"applet": "Applet",
|
|
@@ -174,5 +174,11 @@
|
|
|
174
174
|
"buildPluginsComplete": "Building plugins completed",
|
|
175
175
|
"pluginPackageNotFound%s": "Plugin package '%s' file not found!",
|
|
176
176
|
"pluginPackageInvalid%s": "`Plugin package '%s' should be an instance of Base class`",
|
|
177
|
-
"appletNeedsBajoCli": "Applet needs to have 'bajo-cli' loaded"
|
|
177
|
+
"appletNeedsBajoCli": "Applet needs to have 'bajo-cli' loaded",
|
|
178
|
+
"unknown%s%s": "Unknown %s|toLower '%s'",
|
|
179
|
+
"notImplemented%s%s": "%s|upperFirst '%s' not implemented yet",
|
|
180
|
+
"method": "Method",
|
|
181
|
+
"exist%s%s": "%s|upperFirst '%s' exists already",
|
|
182
|
+
"fieldError%s%s": "'%s': %s|lowerFirst",
|
|
183
|
+
"reservedName%s%s": "%s|upperFirst name '%s' is a reserved name. Please rename to something else"
|
|
178
184
|
}
|
package/extend/bajo/intl/id.json
CHANGED
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"appRunningAsApplet": "App berjalan di mode applet",
|
|
23
23
|
"setupBootOrder": "Atur urutan booting",
|
|
24
24
|
"configHandlers%s": "Pengatur konfigurasi: %s",
|
|
25
|
-
"
|
|
25
|
+
"dataDir%s": "Dir data: %s",
|
|
26
|
+
"exited%s": "- %s keluar",
|
|
26
27
|
"appShutdown": "Aplikasi ditutup",
|
|
27
28
|
"appletModeActivated": "Mode applet diaktifkan",
|
|
28
|
-
"collected%s%d": "%s terkoleksi: %d",
|
|
29
|
-
"attachMethods": "Tempelkan metode",
|
|
29
|
+
"collected%s%d": "%s|upperFirst terkoleksi: %d",
|
|
30
30
|
"readConfigs": "Baca konfigurasi",
|
|
31
31
|
"checkAliasNameClash": "Cek bentrokan nama dan alias",
|
|
32
32
|
"checkDeps": "Cek ketergantungan",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"offlineL": "offline",
|
|
127
127
|
"reconnectingL": "mencoba menghubung kembali",
|
|
128
128
|
"connMustHave%s": "Koneksi harus memiliki '%s'",
|
|
129
|
-
"notFound%s%s": "%s '%s' tidak ditemukan",
|
|
129
|
+
"notFound%s%s": "%s|upperFirst '%s' tidak ditemukan",
|
|
130
130
|
"connection": "Koneksi",
|
|
131
131
|
"file": "Berkas",
|
|
132
132
|
"applet": "Applet",
|
|
@@ -174,5 +174,11 @@
|
|
|
174
174
|
"buildPluginsComplete": "Pemuatan plugin komplit",
|
|
175
175
|
"pluginPackageNotFound%s": "Berkas paket plugin '%s' tidak ditemukan!",
|
|
176
176
|
"pluginPackageInvalid%s": "Paket plugin '%s' harus berupa instan dari kelas Base",
|
|
177
|
-
"appletNeedsBajoCli": "Applet membutuhkan 'bajo-cli' yang harus termuat terlebih dahulu"
|
|
177
|
+
"appletNeedsBajoCli": "Applet membutuhkan 'bajo-cli' yang harus termuat terlebih dahulu",
|
|
178
|
+
"unknown%s%s": "%s|upperFirst '%s' tidak dikenal",
|
|
179
|
+
"notImplemented%s%s": "%s|upperFirst '%s' belum diimplementasikan",
|
|
180
|
+
"method": "Metode",
|
|
181
|
+
"exist%s%s": "%s|upperFirst '%s' sudah ada",
|
|
182
|
+
"fieldError%s%s": "'%s': %s|lowerFirst",
|
|
183
|
+
"reservedName%s%s": "Nama %s|lowerFirst '%s' adalah nama tang di reserve. Silahkan gunakan nama lainnya"
|
|
178
184
|
}
|
|
File without changes
|
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import App from './class/app.js'
|
|
2
|
-
import shim from '
|
|
2
|
+
import { shim } from 'aneka'
|
|
3
|
+
import fs from 'fs-extra'
|
|
3
4
|
|
|
4
5
|
shim()
|
|
5
6
|
|
|
@@ -25,6 +26,13 @@ shim()
|
|
|
25
26
|
* @returns {App}
|
|
26
27
|
*/
|
|
27
28
|
async function boot (cwd) {
|
|
29
|
+
if (!cwd) cwd = process.cwd()
|
|
30
|
+
const pkgFile = `${cwd}/package.json`
|
|
31
|
+
const pkg = fs.readJsonSync(pkgFile)
|
|
32
|
+
if (pkg.type !== 'module') {
|
|
33
|
+
console.error(`Please turn on ES6 parsing by adding "type": "module" to ${pkgFile}!`)
|
|
34
|
+
process.exit(1)
|
|
35
|
+
}
|
|
28
36
|
const app = new App(cwd)
|
|
29
37
|
return await app.boot()
|
|
30
38
|
}
|
package/lib/find-deep.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Find item deep in paths
|
|
5
|
+
*
|
|
6
|
+
* @method
|
|
7
|
+
* @memberof module:Lib
|
|
8
|
+
* @param {string} item - Item to find
|
|
9
|
+
* @param {Array} paths - Array of path to look for
|
|
10
|
+
* @returns {string}
|
|
11
|
+
*/
|
|
12
|
+
function findDeep (item, paths) {
|
|
13
|
+
let dir
|
|
14
|
+
for (const p of paths) {
|
|
15
|
+
const d = `${p}/${item}`
|
|
16
|
+
if (fs.existsSync(d)) {
|
|
17
|
+
dir = d
|
|
18
|
+
break
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return dir
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default findDeep
|
package/lib/formats.js
CHANGED
|
File without changes
|
package/lib/freeze.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import deepFreezeStrict from 'deep-freeze-strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Freeze object
|
|
5
|
+
*
|
|
6
|
+
* @method
|
|
7
|
+
* @memberof module:Lib
|
|
8
|
+
* @param {Object} obj - Object to freeze
|
|
9
|
+
* @param {boolean} [shallow=false] - If ```false``` (default), deep freeze object
|
|
10
|
+
*/
|
|
11
|
+
function freeze (obj, shallow = false) {
|
|
12
|
+
if (shallow) Object.freeze(obj)
|
|
13
|
+
else deepFreezeStrict(obj)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default freeze
|
package/lib/import-module.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import resolvePath from './resolve-path.js'
|
|
2
1
|
import fs from 'fs-extra'
|
|
3
2
|
import lodash from 'lodash'
|
|
3
|
+
import aneka from 'aneka'
|
|
4
|
+
|
|
5
|
+
const { resolvePath } = aneka
|
|
4
6
|
const { isFunction, isPlainObject } = lodash
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -32,8 +34,8 @@ const { isFunction, isPlainObject } = lodash
|
|
|
32
34
|
* @returns {any}
|
|
33
35
|
* @see Bajo#importModule
|
|
34
36
|
*/
|
|
35
|
-
async function importModule (file, { asDefaultImport, asHandler, noCache } = {}) {
|
|
36
|
-
const load = async (file, asDefaultImport
|
|
37
|
+
async function importModule (file, { asDefaultImport = true, asHandler, noCache } = {}) {
|
|
38
|
+
const load = async (file, asDefaultImport, noCache = false) => {
|
|
37
39
|
file = resolvePath(file, true)
|
|
38
40
|
if (noCache) file += `?_=${Date.now()}`
|
|
39
41
|
const imported = await import(file)
|
package/lib/index.js
ADDED
package/lib/log-levels.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bajo",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "The ultimate framework for whipping up massive apps in no time",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build-doc": "jsdoc -c .jsdoc.conf.json",
|
|
8
|
-
"test": "mocha"
|
|
8
|
+
"test": "mocha --recursive"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
11
|
"repository": {
|
|
@@ -26,29 +26,23 @@
|
|
|
26
26
|
"homepage": "https://github.com/ardhi/bajo#readme",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"add-filename-increment": "^1.0.0",
|
|
29
|
-
"aneka": "^0.
|
|
29
|
+
"aneka": "^0.10.0",
|
|
30
30
|
"chalk": "^5.6.0",
|
|
31
31
|
"dayjs": "^1.11.13",
|
|
32
32
|
"deep-freeze-strict": "^1.1.1",
|
|
33
33
|
"delay": "^6.0.0",
|
|
34
|
-
"dotenv": "^17.2.1",
|
|
35
|
-
"dotenv-parse-variables": "^2.0.0",
|
|
36
34
|
"empty-dir": "^3.0.0",
|
|
37
35
|
"fast-glob": "^3.3.3",
|
|
38
|
-
"flat": "^6.0.1",
|
|
39
36
|
"fs-extra": "^11.3.1",
|
|
40
37
|
"get-global-path": "^0.0.1",
|
|
41
38
|
"lodash": "^4.17.21",
|
|
42
|
-
"ms": "^2.1.3",
|
|
43
|
-
"nanoid": "^5.1.5",
|
|
44
39
|
"omit-deep": "^0.3.0",
|
|
45
40
|
"ora": "^8.2.0",
|
|
46
41
|
"outmatch": "^1.0.0",
|
|
47
|
-
"semver": "^7.7.2"
|
|
48
|
-
"sprintf-js": "^1.1.3",
|
|
49
|
-
"yargs": "^18.0.0"
|
|
42
|
+
"semver": "^7.7.2"
|
|
50
43
|
},
|
|
51
44
|
"devDependencies": {
|
|
45
|
+
"chai": "^6.2.1",
|
|
52
46
|
"clean-jsdoc-theme": "^4.3.0",
|
|
53
47
|
"docdash": "^2.0.2"
|
|
54
48
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { expect } from 'chai'
|
|
2
|
+
import Base from '../class/base.js'
|
|
3
|
+
|
|
4
|
+
function makeMockApp ({ mainNs = 'app-main', throwOnDataConfig = false } = {}) {
|
|
5
|
+
// small lodash-like helpers used by Base.loadConfig
|
|
6
|
+
const _ = {
|
|
7
|
+
get: (obj, path, defVal) => {
|
|
8
|
+
if (!obj) return defVal
|
|
9
|
+
const parts = String(path).split('.')
|
|
10
|
+
let cur = obj
|
|
11
|
+
for (const p of parts) {
|
|
12
|
+
if (cur == null) return defVal
|
|
13
|
+
cur = cur[p]
|
|
14
|
+
}
|
|
15
|
+
return cur === undefined ? defVal : cur
|
|
16
|
+
},
|
|
17
|
+
kebabCase: s => String(s).replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/[\s_]+/g, '-').toLowerCase(),
|
|
18
|
+
keys: obj => obj ? Object.keys(obj) : [],
|
|
19
|
+
pick: (obj, keys) => {
|
|
20
|
+
const out = {}
|
|
21
|
+
if (!obj) return out
|
|
22
|
+
for (const k of keys) if (k in obj) out[k] = obj[k]
|
|
23
|
+
return out
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// simple defaultsDeep-ish helper suitable for these tests:
|
|
28
|
+
// later objects in args take precedence over earlier ones (shallow)
|
|
29
|
+
const defaultsDeep = (...objs) => Object.assign({}, ...objs.filter(Boolean))
|
|
30
|
+
|
|
31
|
+
// bajo helpers (file reads etc). readAllConfigs will be called twice by Base.loadConfig:
|
|
32
|
+
// - once for module dir config
|
|
33
|
+
// - once for data dir config (may throw)
|
|
34
|
+
let readAllCalls = 0
|
|
35
|
+
const readAllConfigs = async (path) => {
|
|
36
|
+
readAllCalls += 1
|
|
37
|
+
if (throwOnDataConfig && readAllCalls === 2) throw new Error('readAllConfigs data dir error')
|
|
38
|
+
// return a small config object to test merge/path logic
|
|
39
|
+
return { alpha: 'file', title: 'FromFile', other: 'ignore-me' }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
mainNs,
|
|
44
|
+
lib: { aneka: { defaultsDeep }, _ },
|
|
45
|
+
bajo: {
|
|
46
|
+
dir: { base: '/base', data: '/data' },
|
|
47
|
+
readAllConfigs,
|
|
48
|
+
readJson: async (p) => ({ name: 'bajo-foo', version: '1.2.3', description: 'pkg' }),
|
|
49
|
+
parseObject: (o) => o,
|
|
50
|
+
getModuleDir: (pkgName) => `/modules/${pkgName}`,
|
|
51
|
+
log: { trace: () => {} }
|
|
52
|
+
},
|
|
53
|
+
env: {},
|
|
54
|
+
argv: {}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('Base.loadConfig', () => {
|
|
59
|
+
it('derives alias from pkgName starting with "bajo-" using kebabCase', async () => {
|
|
60
|
+
const app = makeMockApp()
|
|
61
|
+
const inst = new Base('bajo-MyPlugin', app)
|
|
62
|
+
// ensure namespace used by loadConfig
|
|
63
|
+
inst.ns = 'myplugin'
|
|
64
|
+
// set an initial config shape so defKeys isn't empty
|
|
65
|
+
inst.config = { alpha: 'default', title: 'Default' }
|
|
66
|
+
|
|
67
|
+
await inst.loadConfig()
|
|
68
|
+
|
|
69
|
+
// alias is stored on the constructor
|
|
70
|
+
expect(inst.constructor.alias).to.equal('my-plugin')
|
|
71
|
+
// dir pkg should be set according to mainNs mismatch
|
|
72
|
+
expect(inst.dir.pkg).to.equal('/modules/bajo-MyPlugin')
|
|
73
|
+
// config should keep keys only from defKeys (alpha & title), parseObject ran (no throw)
|
|
74
|
+
expect(Object.keys(inst.config)).to.include('alpha')
|
|
75
|
+
expect(Object.keys(inst.config)).to.include('title')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('when ns === app.mainNs uses app.mainNs as alias and sets title to alias', async () => {
|
|
79
|
+
const app = makeMockApp({ mainNs: 'mainns' })
|
|
80
|
+
const inst = new Base('bajo-mainpkg', app)
|
|
81
|
+
inst.ns = 'mainns'
|
|
82
|
+
inst.config = { title: undefined } // start with no title
|
|
83
|
+
|
|
84
|
+
await inst.loadConfig()
|
|
85
|
+
|
|
86
|
+
expect(inst.constructor.alias).to.equal('mainns')
|
|
87
|
+
// title should be set to alias when ns is mainNs
|
|
88
|
+
expect(inst.title).to.equal(inst.constructor.alias)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('continues when readAllConfigs for data dir throws (tolerant behavior)', async () => {
|
|
92
|
+
const app = makeMockApp({ throwOnDataConfig: true })
|
|
93
|
+
const inst = new Base('bajo-throwtest', app)
|
|
94
|
+
inst.ns = 'throwtest'
|
|
95
|
+
inst.config = { alpha: 'start' }
|
|
96
|
+
|
|
97
|
+
// should not throw even if second readAllConfigs throws
|
|
98
|
+
let threw = false
|
|
99
|
+
try {
|
|
100
|
+
await inst.loadConfig()
|
|
101
|
+
} catch (err) {
|
|
102
|
+
threw = true
|
|
103
|
+
}
|
|
104
|
+
expect(threw).to.equal(false)
|
|
105
|
+
// config should still be an object and title present (or undefined but not crash)
|
|
106
|
+
expect(inst.config).to.be.an('object')
|
|
107
|
+
})
|
|
108
|
+
})
|
package/wiki/CHANGES.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changes
|
|
2
|
+
|
|
3
|
+
## 2026-01-11
|
|
4
|
+
|
|
5
|
+
- [2.2.0] Simplify numerous things by putting most of static properties back as normal class properties
|
|
6
|
+
|
|
7
|
+
## 2025-12-29
|
|
8
|
+
|
|
9
|
+
- [2.2.0] Add ```this.selfBind()``` to class ```Plugin```
|
|
10
|
+
|
|
11
|
+
## 2025-12-27
|
|
12
|
+
|
|
13
|
+
- [2.2.0] Add some translations
|
|
14
|
+
|
|
15
|
+
## 2025-12-27
|
|
16
|
+
|
|
17
|
+
- [2.2.0] Add config object ```this.config.runtime``` to adjust some runtime settings
|
|
18
|
+
|
|
19
|
+
## 2025-12-24
|
|
20
|
+
|
|
21
|
+
- [2.2.0] Pass ```true``` to ```this.app.exit()``` to exit abruptly. Defaults to ```SIGINT```
|
|
22
|
+
- [2.2.0] Add ```detailsMessage``` to ```Err``` class if error object has ```details``` in payload
|
|
23
|
+
- [2.2.0] Upgrade ```aneka@0.10.0```
|
|
24
|
+
- [2.2.0] Bugfix: program arguments should not parsed as object
|
|
25
|
+
|
|
26
|
+
## 2025-12-21
|
|
27
|
+
|
|
28
|
+
- [2.2.0] ```runHook()``` now accept both ```alias``` & ```ns``` prefixed name
|
|
29
|
+
- [2.2.0] In case of unknown plugin or plugin isn't loaded, ```runHook``` simply exit silently
|
|
30
|
+
- [2.2.0] ```this.app.pluginClass``` is now ```this.app.baseClass``` and all containing class definition keys are pascal cased to match with their constructor names
|
|
31
|
+
|
|
32
|
+
## 2025-12-20
|
|
33
|
+
|
|
34
|
+
- [2.2.0] Removing dynamically attached methods because its problematic and leads to confusion
|
|
35
|
+
|
|
36
|
+
## 2025-12-19
|
|
37
|
+
|
|
38
|
+
- [2.2.0] Upgrade to ```aneka@0.9.0```
|
|
39
|
+
|
|
40
|
+
## 2025-12-13
|
|
41
|
+
|
|
42
|
+
- [2.2.0] Add ```app.lib.formatText()```
|
|
43
|
+
- [2.2.0] Move most bajo methods that doesn't relate to Bajo to app.lib functions
|
|
44
|
+
|
|
45
|
+
## 2025-12-11
|
|
46
|
+
|
|
47
|
+
- [2.1.1] Upgrade to ```aneka@0.5.0```
|
|
48
|
+
|
|
49
|
+
## 2025-12-09
|
|
50
|
+
|
|
51
|
+
- [2.1.1] Upgrade to ```aneka@0.2.3```
|
|
52
|
+
- [2.1.1] Some organizatory file location changes
|
|
53
|
+
- [2.1.1] Typo on class ```Tools```
|
|
54
|
+
|
|
55
|
+
## 2025-12-05
|
|
56
|
+
|
|
57
|
+
- [2.1.1] Upgrade to ```aneka@0.2.1```
|
|
58
|
+
- [2.1.1] New class ```Tools```, serves as anchestor for ```Err``` & ```Print```
|
|
59
|
+
|
|
60
|
+
## 2025-12-03
|
|
61
|
+
|
|
62
|
+
- [2.1.1] Add method ```getPkgInfo()``` to plugins main class.
|
|
63
|
+
- [2.1.1] Now you can put your plugins either in ```{dataDir}/config/.plugins``` or directly as an array in your app ```package.json``` under the ```bajo.plugins``` tree. The later takes precedence.
|
package/wiki/CONFIG.md
CHANGED
|
@@ -7,9 +7,15 @@ The following table shows the default app settings. To change these to suit your
|
|
|
7
7
|
| ```log``` | ```object``` | | |
|
|
8
8
|
| ```dateFormat``` | ```string``` | ```YYYY-MM-DDTHH:MM:ss.SSS[Z]```| See [dayjs string & format](https://day.js.org/docs/en/parse/string-format) for more info |
|
|
9
9
|
| ```timeTaken``` | ```boolean``` | ```false```| Show time taken from previous activity in ms |
|
|
10
|
-
| ```
|
|
10
|
+
| ```useUtc``` | ```boolean``` | ```false```| Use UTC, defaults: local date/time |
|
|
11
11
|
| ```pretty``` | ```boolean``` | ```false```| Colorful, pretty styling |
|
|
12
12
|
| ```applet``` | ```boolean``` | ```false```| Show log even in applet mode |
|
|
13
|
+
| ```save``` | ```boolean``` | ```false```| Save log in '{dataDir}/log' |
|
|
14
|
+
| ```rotation``` | ```object``` | | Log rotation config if ```save``` is true |
|
|
15
|
+
| ```cycle``` | ```string``` | ```none``` | Available values: ```none```, ```daily```, ```weekly```, ```monthly``` |
|
|
16
|
+
| ```compressOld``` | ```boolean``` | ```false``` | Set to ```true``` to compress old logs |
|
|
17
|
+
| ```byPlugin``` | ```boolean``` | ```false``` | Split log by plugin's name |
|
|
18
|
+
| ```retain``` | ```integer``` | ```5``` | How many old logs will be kept/retained |
|
|
13
19
|
| ```lang``` | ```string``` | Auto detected | Valid language code e.g: 'en-US', 'id', etc. |
|
|
14
20
|
| ```intl``` | ```object``` | | Internationalization settings |
|
|
15
21
|
| ```supported``` | ```array``` | ```['en-US', 'id']``` | Supported languages |
|
package/wiki/CONTRIBUTING.md
CHANGED
|
File without changes
|
package/wiki/DEV_GUIDE.md
CHANGED
|
File without changes
|
package/wiki/ECOSYSTEM.md
CHANGED
|
File without changes
|
package/wiki/GETTING-STARTED.md
CHANGED
|
@@ -139,7 +139,7 @@ This file is the main plugin factory. It gets created automatically if it's not
|
|
|
139
139
|
async function factory (pkgName) {
|
|
140
140
|
const me = this
|
|
141
141
|
|
|
142
|
-
return class Main extends this.app.
|
|
142
|
+
return class Main extends this.app.baseClass.Base {
|
|
143
143
|
constructor () {
|
|
144
144
|
super(pkgName, me.app)
|
|
145
145
|
this.config = {}
|
package/wiki/USER-GUIDE.md
CHANGED
|
File without changes
|
package/lib/current-loc.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import resolvePath from './resolve-path.js'
|
|
3
|
-
import { fileURLToPath } from 'url'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Get current directory & file. An attempt to brings back the old ```__dirname``` and ```__filename```
|
|
7
|
-
* to the ES6 era.
|
|
8
|
-
*
|
|
9
|
-
* Returns object with the following keys:
|
|
10
|
-
* - ```__dirname``` (aliases to ```dir```) - current directory name
|
|
11
|
-
* - ```__filename``` (aliases to ```file```) - current file path
|
|
12
|
-
*
|
|
13
|
-
* Example:
|
|
14
|
-
* ```javascript
|
|
15
|
-
* const { importModule } = this.app.bajo
|
|
16
|
-
* const currentLoc = await importModule('bajo:/lib/current-loc.js')
|
|
17
|
-
*
|
|
18
|
-
* const { __dirname, __filename } = currentLoc(import.meta)
|
|
19
|
-
* console.log(__dirname, __filename)
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @method
|
|
23
|
-
* @memberof module:Lib
|
|
24
|
-
* @param {Object} metaImport - ```import.meta``` object
|
|
25
|
-
* @returns {Object}
|
|
26
|
-
*/
|
|
27
|
-
const currentLoc = (metaImport) => {
|
|
28
|
-
const file = resolvePath(fileURLToPath(metaImport.url))
|
|
29
|
-
const dir = path.dirname(file)
|
|
30
|
-
return { dir, file, __dirname: dir, __filename: file }
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default currentLoc
|
package/lib/parse-args-argv.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import yargs from 'yargs'
|
|
2
|
-
import { Parser } from 'yargs/helpers'
|
|
3
|
-
import { unflatten } from 'flat'
|
|
4
|
-
import dotenvParseVariables from 'dotenv-parse-variables'
|
|
5
|
-
import lodash from 'lodash'
|
|
6
|
-
import fs from 'fs-extra'
|
|
7
|
-
import path from 'path'
|
|
8
|
-
|
|
9
|
-
const { find, each, set, camelCase, forOwn } = lodash
|
|
10
|
-
const delimiter = '-'
|
|
11
|
-
const splitter = ':'
|
|
12
|
-
|
|
13
|
-
const parseItem = (data, delimiter) => {
|
|
14
|
-
return unflatten(data, {
|
|
15
|
-
delimiter,
|
|
16
|
-
safe: true,
|
|
17
|
-
overwrite: true
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function parseWithParser () {
|
|
22
|
-
return Parser(process.argv.slice(2), {
|
|
23
|
-
configuration: {
|
|
24
|
-
'camel-case-expansion': false
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function parseWithYargs () {
|
|
30
|
-
const pkg = fs.readJSONSync(`${this.dir}/package.json`)
|
|
31
|
-
let name = `node ${pkg.main}`
|
|
32
|
-
if (pkg.bin) name = path.basename(pkg.bin, '.js')
|
|
33
|
-
const cli = yargs(process.argv.slice(2))
|
|
34
|
-
.usage('Usage: $0 [args...]')
|
|
35
|
-
.scriptName(name)
|
|
36
|
-
.positional('args', {
|
|
37
|
-
describe: 'Optional one or more arguments'
|
|
38
|
-
})
|
|
39
|
-
.parserConfiguration({
|
|
40
|
-
'camel-case-expansion': false
|
|
41
|
-
})
|
|
42
|
-
.version(pkg.version).alias('version', 'v')
|
|
43
|
-
.help().alias('help', 'h')
|
|
44
|
-
.alias('applet', 'a')
|
|
45
|
-
if (pkg.homepage) cli.epilog(`For more information please visit ${pkg.homepage}`)
|
|
46
|
-
return cli.argv
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Parse program arguments (args) & options (argv). See {@link App#args|args} & {@link App#argv|argv} for examples
|
|
51
|
-
*
|
|
52
|
-
* @method
|
|
53
|
-
* @async
|
|
54
|
-
* @memberof module:Lib
|
|
55
|
-
* @param {boolean} [useParser] - If ```true```, skip {@link https://github.com/yargs/yargs|yargs}
|
|
56
|
-
* @returns {{args: Array, argv: Object}} An object containing ```args``` and ```argv```
|
|
57
|
-
* @see App#args
|
|
58
|
-
* @see App#argv
|
|
59
|
-
*/
|
|
60
|
-
async function parseArgsArgv (useParser) {
|
|
61
|
-
if (!useParser) useParser = find(process.argv, a => a.startsWith('--spawn'))
|
|
62
|
-
let argv = useParser ? await parseWithParser.call(this) : await parseWithYargs.call(this)
|
|
63
|
-
const args = argv._
|
|
64
|
-
delete argv._
|
|
65
|
-
delete argv.$0
|
|
66
|
-
argv = dotenvParseVariables(argv)
|
|
67
|
-
const all = { _: {} }
|
|
68
|
-
each(argv, (v, k) => {
|
|
69
|
-
const parts = k.split(splitter)
|
|
70
|
-
if (!parts[1]) all._[parts[0]] = v
|
|
71
|
-
else set(all, `${camelCase(parts[0])}.${parts[1]}`, v)
|
|
72
|
-
})
|
|
73
|
-
const result = {}
|
|
74
|
-
forOwn(all, (v, k) => {
|
|
75
|
-
result[k] = parseItem(v, delimiter)
|
|
76
|
-
})
|
|
77
|
-
return { args, argv: this.bajo.parseObject(result, { parseValue: true }) }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export default parseArgsArgv
|
package/lib/parse-env.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import dotenvParseVariables from 'dotenv-parse-variables'
|
|
2
|
-
import { unflatten } from 'flat'
|
|
3
|
-
import dotEnv from 'dotenv'
|
|
4
|
-
import lodash from 'lodash'
|
|
5
|
-
|
|
6
|
-
const { each, set, camelCase, forOwn } = lodash
|
|
7
|
-
const parse = (data, delimiter) => {
|
|
8
|
-
return unflatten(data, {
|
|
9
|
-
delimiter,
|
|
10
|
-
safe: true,
|
|
11
|
-
overwrite: true,
|
|
12
|
-
transformKey: k => {
|
|
13
|
-
return camelCase(k.toLowerCase())
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const delimiter = '__'
|
|
19
|
-
const splitter = '.'
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Parse environment variables. See {@link App#envVars|envVars} for examples
|
|
23
|
-
*
|
|
24
|
-
* @method
|
|
25
|
-
* @memberof module:Lib
|
|
26
|
-
* @returns {Object}
|
|
27
|
-
* @see App#envVars
|
|
28
|
-
*/
|
|
29
|
-
function parseEnv () {
|
|
30
|
-
let env
|
|
31
|
-
try {
|
|
32
|
-
env = dotEnv.config({ quiet: true })
|
|
33
|
-
} catch (err) {
|
|
34
|
-
}
|
|
35
|
-
env = dotenvParseVariables(process.env, { assignToProcessEnv: false })
|
|
36
|
-
const all = { _: {} }
|
|
37
|
-
each(env, (v, k) => {
|
|
38
|
-
const parts = k.split(splitter)
|
|
39
|
-
if (!parts[1]) all._[parts[0]] = v
|
|
40
|
-
else set(all, `${camelCase(parts[0])}.${parts[1]}`, v)
|
|
41
|
-
})
|
|
42
|
-
const result = {}
|
|
43
|
-
forOwn(all, (v, k) => {
|
|
44
|
-
result[k] = parse(v, delimiter)
|
|
45
|
-
})
|
|
46
|
-
if (result._.lang) result._.lang = result._.lang.split('.')[0].replaceAll('_', '-')
|
|
47
|
-
return this.bajo.parseObject(result, { parseValue: true })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export default parseEnv
|
package/lib/resolve-path.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { fileURLToPath } from 'url'
|
|
3
|
-
import os from 'os'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Resolve file name to filesystem's path. Windows path separator ```\```
|
|
7
|
-
* is normalized to Unix's ```/```
|
|
8
|
-
*
|
|
9
|
-
* @memberof module:Lib
|
|
10
|
-
* @param {string} file - File to resolve
|
|
11
|
-
* @param {boolean} [asFileUrl=false] - Return as file URL format ```file:///<name>```
|
|
12
|
-
* @returns {string}
|
|
13
|
-
*/
|
|
14
|
-
function resolvePath (item, asFileUrl) {
|
|
15
|
-
if (item.startsWith('file://')) item = fileURLToPath(item)
|
|
16
|
-
item = path.resolve(item)
|
|
17
|
-
if (os.platform() === 'win32') {
|
|
18
|
-
item = item.replace(/\\/g, '/')
|
|
19
|
-
}
|
|
20
|
-
if (asFileUrl) item = `file:///${item}`
|
|
21
|
-
return item
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default resolvePath
|