bajo 2.4.2 → 2.6.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/log.js +11 -6
- package/class/app.js +42 -25
- package/class/helper/bajo.js +3 -3
- package/class/plugin/err.js +6 -2
- package/class/plugin.js +13 -0
- package/package.json +2 -2
- package/wiki/CHANGES.md +12 -0
package/class/app/log.js
CHANGED
|
@@ -77,16 +77,17 @@ class Log {
|
|
|
77
77
|
if (!this.app.bajo.isLogInRange(level)) return
|
|
78
78
|
const { useUtc, timeTaken, dateFormat, pretty } = this.app.bajo.config.log
|
|
79
79
|
let [data, msg, ...args] = params
|
|
80
|
+
if (data instanceof Error) {
|
|
81
|
+
msg = 'error%s'
|
|
82
|
+
args = [this.getErrorMessage(data)]
|
|
83
|
+
console.error(data)
|
|
84
|
+
}
|
|
80
85
|
if (typeof data === 'string') {
|
|
81
86
|
args.unshift(msg)
|
|
82
87
|
msg = data
|
|
83
88
|
data = null
|
|
84
89
|
}
|
|
85
90
|
args = without(args, undefined)
|
|
86
|
-
if (data instanceof Error) {
|
|
87
|
-
msg = 'error%s'
|
|
88
|
-
args = [data.message]
|
|
89
|
-
}
|
|
90
91
|
msg = this.app.t(prefix, msg, ...args)
|
|
91
92
|
let text
|
|
92
93
|
const dt = dayjs()
|
|
@@ -113,13 +114,17 @@ class Log {
|
|
|
113
114
|
const tlevel = pretty ? `${chalk[logLevels[level].color](level.toUpperCase())}:` : `[${level.toUpperCase()}]`
|
|
114
115
|
const tprefix = pretty ? chalk.bgBlue(`${prefix}`) : `[${prefix}]`
|
|
115
116
|
text = `${tdate} ${tlevel} ${tprefix} ${msg}`
|
|
116
|
-
if (!isEmpty(data)) text += '\n' + JSON.stringify(data)
|
|
117
|
+
if (!isEmpty(data) && !(data instanceof Error)) text += '\n' + JSON.stringify(data)
|
|
117
118
|
}
|
|
118
119
|
console.log(text)
|
|
119
|
-
if (data instanceof Error && level === 'trace') console.error(data)
|
|
120
120
|
if (this.app.bajo.config.log.save) this.save(text, prefix)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
getErrorMessage = error => {
|
|
124
|
+
const { isEmpty } = this.app.lib._
|
|
125
|
+
return isEmpty(error.message) ? (error.code ?? error.statusCode) : error.message
|
|
126
|
+
}
|
|
127
|
+
|
|
123
128
|
/**
|
|
124
129
|
* Calculate pattern used for log rotation
|
|
125
130
|
*
|
package/class/app.js
CHANGED
|
@@ -326,27 +326,8 @@ class App {
|
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
*
|
|
332
|
-
* There is a shortcut to this method attached on all plugins. You'll normally call that shorcut
|
|
333
|
-
* instead of this method, because it is bound to plugin's name already
|
|
334
|
-
*
|
|
335
|
-
* ```javascript
|
|
336
|
-
* ... within your main plugin
|
|
337
|
-
* const translated = this.app.t('main', 'My cute cat is %s', 'purring')
|
|
338
|
-
* // or
|
|
339
|
-
* const translated = this.t('My cute cat is %s', 'purring')
|
|
340
|
-
* ```
|
|
341
|
-
* @method
|
|
342
|
-
* @param {string} ns - Namespace
|
|
343
|
-
* @param {string} text - Text to translate
|
|
344
|
-
* @param {...any} params - Arguments
|
|
345
|
-
* @returns {string}
|
|
346
|
-
*/
|
|
347
|
-
t = (ns, text, ...params) => {
|
|
348
|
-
const { formatText } = this.lib.aneka
|
|
349
|
-
|
|
329
|
+
_prepTrans = (ns, text, params) => {
|
|
330
|
+
const { fallback, supported } = this.bajo.config.intl
|
|
350
331
|
if (!text) {
|
|
351
332
|
text = ns
|
|
352
333
|
ns = 'bajo'
|
|
@@ -357,7 +338,6 @@ class App {
|
|
|
357
338
|
params.pop()
|
|
358
339
|
if (opts.lang) lang = opts.lang
|
|
359
340
|
}
|
|
360
|
-
const { fallback, supported } = this.bajo.config.intl
|
|
361
341
|
if (!unknownLangWarning && !supported.includes(lang)) {
|
|
362
342
|
unknownLangWarning = true
|
|
363
343
|
this.bajo.log.warn(`Unsupported language, fallback to '${fallback}'`)
|
|
@@ -365,7 +345,6 @@ class App {
|
|
|
365
345
|
const plugins = reverse(without([...this.getAllNs()], ns))
|
|
366
346
|
plugins.unshift(ns)
|
|
367
347
|
plugins.push('bajo')
|
|
368
|
-
|
|
369
348
|
let trans
|
|
370
349
|
for (const p of plugins) {
|
|
371
350
|
const store = get(this, `${p}.intl.${lang}`, {})
|
|
@@ -379,8 +358,46 @@ class App {
|
|
|
379
358
|
if (trans) break
|
|
380
359
|
}
|
|
381
360
|
}
|
|
382
|
-
|
|
383
|
-
|
|
361
|
+
return { ns, text, lang, params, plugins, trans }
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Translate text and interpolate with given ```args```.
|
|
366
|
+
*
|
|
367
|
+
* There is a shortcut to this method attached on all plugins. You'll normally call that shorcut
|
|
368
|
+
* instead of this method, because it is bound to plugin's name already
|
|
369
|
+
*
|
|
370
|
+
* ```javascript
|
|
371
|
+
* ... within your main plugin
|
|
372
|
+
* const translated = this.app.t('main', 'My cute cat is %s', 'purring')
|
|
373
|
+
* // or
|
|
374
|
+
* const translated = this.t('My cute cat is %s', 'purring')
|
|
375
|
+
* ```
|
|
376
|
+
* @method
|
|
377
|
+
* @param {string} ns - Namespace
|
|
378
|
+
* @param {string} text - Text to translate
|
|
379
|
+
* @param {...any} params - Arguments
|
|
380
|
+
* @returns {string}
|
|
381
|
+
*/
|
|
382
|
+
t = (ns, text, ...params) => {
|
|
383
|
+
const { formatText } = this.lib.aneka
|
|
384
|
+
let { text: newText, trans, params: args } = this._prepTrans(ns, text, params)
|
|
385
|
+
if (!trans) trans = newText
|
|
386
|
+
return formatText(trans, ...args)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Check whether translation text/key exists
|
|
391
|
+
*
|
|
392
|
+
* @method
|
|
393
|
+
* @param {string} ns - Namespace
|
|
394
|
+
* @param {string} text - Text to translate
|
|
395
|
+
* @returns {boolean}
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
te = (ns, text, ...params) => {
|
|
399
|
+
const { trans } = this._prepTrans(ns, text, params)
|
|
400
|
+
return !!trans
|
|
384
401
|
}
|
|
385
402
|
|
|
386
403
|
/**
|
package/class/helper/bajo.js
CHANGED
|
@@ -59,9 +59,9 @@ const defConfig = {
|
|
|
59
59
|
lookupOrder: [],
|
|
60
60
|
format: {
|
|
61
61
|
emptyValue: '',
|
|
62
|
-
datetime: { dateStyle: 'medium', timeStyle: 'short' },
|
|
63
|
-
date: { dateStyle: 'medium' },
|
|
64
|
-
time: { timeStyle: 'short' },
|
|
62
|
+
datetime: { dateStyle: 'medium', timeStyle: 'short', timeZone: 'UTC' },
|
|
63
|
+
date: { dateStyle: 'medium', timeZone: 'UTC' },
|
|
64
|
+
time: { timeStyle: 'short', timeZone: 'UTC' },
|
|
65
65
|
float: { maximumFractionDigits: 2 },
|
|
66
66
|
double: { maximumFractionDigits: 5 },
|
|
67
67
|
smallint: {},
|
package/class/plugin/err.js
CHANGED
|
@@ -97,6 +97,7 @@ class Err extends Tools {
|
|
|
97
97
|
*/
|
|
98
98
|
formatErrorDetails = (value) => {
|
|
99
99
|
const { isString, last } = this.app.lib._
|
|
100
|
+
const { without } = this.app.lib.aneka
|
|
100
101
|
const result = {}
|
|
101
102
|
const me = this
|
|
102
103
|
const detailsMessage = []
|
|
@@ -104,10 +105,13 @@ class Err extends Tools {
|
|
|
104
105
|
if (isString(v)) v = { error: v }
|
|
105
106
|
if (!v.context) return undefined
|
|
106
107
|
v.context.message = v.message
|
|
107
|
-
if (v.type === 'any.only')
|
|
108
|
+
if (v.type === 'any.only') {
|
|
109
|
+
const items = without(get(v, 'context.valids', []))
|
|
110
|
+
v.context.ref = items.join(', ')
|
|
111
|
+
}
|
|
108
112
|
const field = get(v, 'context.key')
|
|
109
113
|
const val = get(v, 'context.value')
|
|
110
|
-
let error = me.plugin.t(`validation.${v.type}`, v.context ?? {}, {})
|
|
114
|
+
let error = me.plugin.t(v.message[0] === '~' ? v.message.slice(1) : `validation.${v.type}`, v.context ?? {}, {})
|
|
111
115
|
if (error.includes(' ref:')) {
|
|
112
116
|
const item = last(error.split(' '))
|
|
113
117
|
const [, rfield] = item.split(':')
|
package/class/plugin.js
CHANGED
|
@@ -151,6 +151,19 @@ class Plugin {
|
|
|
151
151
|
return this.app.t(this.ns, text, ...params)
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Check whether translation text/key exists.
|
|
156
|
+
*
|
|
157
|
+
* Shortcut to {@link App#te} with ns parameter set to this plugin namespace.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} text - Text to translate
|
|
160
|
+
* @param {...any} params - Variables to interpolate to ```text```
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
te = (text, ...params) => {
|
|
164
|
+
return this.app.te(this.ns, text, ...params)
|
|
165
|
+
}
|
|
166
|
+
|
|
154
167
|
/**
|
|
155
168
|
* Force bind methods to self (```this```)
|
|
156
169
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bajo",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "The ultimate framework for whipping up massive apps in no time",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,7 +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.
|
|
29
|
+
"aneka": "^0.12.0",
|
|
30
30
|
"chalk": "^5.6.0",
|
|
31
31
|
"dayjs": "^1.11.13",
|
|
32
32
|
"deep-freeze-strict": "^1.1.1",
|
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-02-20
|
|
4
|
+
|
|
5
|
+
- [2.6.0] Upgrade to ```aneka@0.12.0```
|
|
6
|
+
- [2.6.0] Add ```te()```
|
|
7
|
+
- [2.6.0] Bug fix on ```formatErrorDetails()``` in ```Err``` class
|
|
8
|
+
|
|
9
|
+
## 2026-02-08
|
|
10
|
+
|
|
11
|
+
- [2.5.0] Bug fix on handling log for ```error``` level
|
|
12
|
+
- [2.5.0] Add ```log.getErrorMessage()``` to get the right value of error message
|
|
13
|
+
- [2.5.0] Add ```timeZone``` in config for datetime data type
|
|
14
|
+
|
|
3
15
|
## 2026-01-29
|
|
4
16
|
|
|
5
17
|
- [2.4.0] Hooks can now be added through ```config``` object. This is specially usefull if you provide a custom config object on app boot
|