bajo 2.0.2 → 2.1.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 +2 -0
- package/class/helper/bajo.js +12 -7
- package/class/misc/log.js +67 -24
- package/extend/bajo/intl/en-US.json +1 -0
- package/extend/bajo/intl/id.json +1 -0
- package/package.json +1 -1
- package/wiki/CONFIG.md +7 -1
package/class/app.js
CHANGED
|
@@ -15,10 +15,12 @@ import dayjs from 'dayjs'
|
|
|
15
15
|
import utc from 'dayjs/plugin/utc.js'
|
|
16
16
|
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
|
|
17
17
|
import localizedFormat from 'dayjs/plugin/localizedFormat.js'
|
|
18
|
+
import weekOfYear from 'dayjs/plugin/weekOfYear.js'
|
|
18
19
|
|
|
19
20
|
dayjs.extend(utc)
|
|
20
21
|
dayjs.extend(customParseFormat)
|
|
21
22
|
dayjs.extend(localizedFormat)
|
|
23
|
+
dayjs.extend(weekOfYear)
|
|
22
24
|
|
|
23
25
|
const { isPlainObject, get, reverse, map, isString, last, without, keys } = lodash
|
|
24
26
|
let unknownLangWarning = false
|
package/class/helper/bajo.js
CHANGED
|
@@ -42,11 +42,18 @@ const defConfig = {
|
|
|
42
42
|
env: 'dev',
|
|
43
43
|
log: {
|
|
44
44
|
timeTaken: false,
|
|
45
|
-
dateFormat: 'YYYY-MM-DDTHH:
|
|
46
|
-
|
|
45
|
+
dateFormat: 'YYYY-MM-DDTHH:mm:ss.SSS',
|
|
46
|
+
useUtc: false,
|
|
47
47
|
pretty: false,
|
|
48
48
|
applet: false,
|
|
49
|
-
traceHook: false
|
|
49
|
+
traceHook: false,
|
|
50
|
+
save: false,
|
|
51
|
+
rotation: {
|
|
52
|
+
cycle: 'none', // none, daily, weekly, monthly
|
|
53
|
+
compressOld: true,
|
|
54
|
+
byPlugin: false,
|
|
55
|
+
retain: 5
|
|
56
|
+
}
|
|
50
57
|
},
|
|
51
58
|
lang: Intl.DateTimeFormat().resolvedOptions().lang ?? 'en-US',
|
|
52
59
|
intl: {
|
|
@@ -109,12 +116,9 @@ export async function buildBaseConfig () {
|
|
|
109
116
|
set(this, 'dir.base', this.app.dir)
|
|
110
117
|
const path = currentLoc(import.meta).dir + '/../..'
|
|
111
118
|
set(this, 'dir.pkg', this.resolvePath(path))
|
|
119
|
+
if (get(this, 'config.dir.data')) set(this, 'dir.data', this.config.dir.data)
|
|
112
120
|
if (!get(this, 'dir.data')) set(this, 'dir.data', `${this.dir.base}/data`)
|
|
113
121
|
this.dir.data = this.resolvePath(this.dir.data)
|
|
114
|
-
if (!fs.existsSync(this.dir.data)) {
|
|
115
|
-
console.log('Data directory (%s) doesn\'t exist yet', this.dir.data)
|
|
116
|
-
process.exit(1)
|
|
117
|
-
}
|
|
118
122
|
fs.ensureDirSync(`${this.dir.data}/config`)
|
|
119
123
|
if (!this.dir.tmp) {
|
|
120
124
|
this.dir.tmp = `${this.resolvePath(os.tmpdir())}/${this.ns}`
|
|
@@ -222,6 +226,7 @@ export async function buildExtConfig () {
|
|
|
222
226
|
if (!this.config.log.applet) this.config.log.level = 'silent'
|
|
223
227
|
this.config.exitHandler = false
|
|
224
228
|
}
|
|
229
|
+
this.log.trace('dataDir%s', this.dir.data)
|
|
225
230
|
this.log.debug('configHandlers%s', this.join(exts))
|
|
226
231
|
}
|
|
227
232
|
|
package/class/misc/log.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import os from 'os'
|
|
2
|
-
import lodash from 'lodash'
|
|
3
|
-
import dayjs from 'dayjs'
|
|
4
|
-
import fs from 'fs-extra'
|
|
5
2
|
import logLevels from '../../lib/log-levels.js'
|
|
6
3
|
import chalk from 'chalk'
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { stripVTControlCharacters } from 'node:util'
|
|
5
|
+
import dayjs from 'dayjs'
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* Log output in stringified JSON format. Returned when app run in ```prod``` environment
|
|
@@ -53,12 +50,9 @@ class Log {
|
|
|
53
50
|
*/
|
|
54
51
|
this.app = app
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
*/
|
|
60
|
-
const { dateFormat } = this.app.bajo.config.log ?? {}
|
|
61
|
-
this.dateFormat = dateFormat ?? 'YYYY-MM-DDTHH:mm:ss.SSS'
|
|
53
|
+
const { fs } = this.app.lib
|
|
54
|
+
this.logDir = `${this.app.bajo.dir.data}/log`
|
|
55
|
+
if (this.app.bajo.config.log.save) fs.ensureDirSync(this.logDir)
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
/**
|
|
@@ -77,9 +71,12 @@ class Log {
|
|
|
77
71
|
* @see TLogJson
|
|
78
72
|
*/
|
|
79
73
|
formatMsg = (level, prefix, ...params) => {
|
|
74
|
+
const { dayjs } = this.app.lib
|
|
75
|
+
const { isEmpty, merge, without } = this.app.lib._
|
|
76
|
+
|
|
80
77
|
if (this.app.bajo.config.log.level === 'silent') return
|
|
81
78
|
if (!this.app.bajo.isLogInRange(level)) return
|
|
82
|
-
const pretty = this.app.bajo.config.log
|
|
79
|
+
const { useUtc, timeTaken, dateFormat, pretty } = this.app.bajo.config.log
|
|
83
80
|
let [data, msg, ...args] = params
|
|
84
81
|
if (typeof data === 'string') {
|
|
85
82
|
args.unshift(msg)
|
|
@@ -93,11 +90,10 @@ class Log {
|
|
|
93
90
|
}
|
|
94
91
|
msg = this.app.t(prefix, msg, ...args)
|
|
95
92
|
let text
|
|
96
|
-
const dt =
|
|
93
|
+
const dt = dayjs()
|
|
97
94
|
let diff = null
|
|
98
|
-
const timeTaken = !!get(this, 'app.bajo.config.log.timeTaken')
|
|
99
95
|
if (timeTaken) {
|
|
100
|
-
const delta =
|
|
96
|
+
const delta = dt.diff(this.app.runAt, 'ms')
|
|
101
97
|
diff = delta - this.lastDelta
|
|
102
98
|
this.lastDelta = delta
|
|
103
99
|
}
|
|
@@ -107,11 +103,8 @@ class Log {
|
|
|
107
103
|
if (timeTaken) merge(json, { timeTaken: diff })
|
|
108
104
|
text = JSON.stringify(json)
|
|
109
105
|
} else {
|
|
110
|
-
let
|
|
111
|
-
|
|
112
|
-
let date = dayjs(dt)
|
|
113
|
-
if (!localDate) date = date.utc()
|
|
114
|
-
if (!(dateFormat.includes('L') || dateFormat.includes('l'))) dateFormat += '[Z]'
|
|
106
|
+
let date = dt.clone()
|
|
107
|
+
if (useUtc) date = dayjs.utc(dt)
|
|
115
108
|
date = date.format(dateFormat)
|
|
116
109
|
let tdate = pretty ? chalk.cyan(date) : `[${date}]`
|
|
117
110
|
if (timeTaken) {
|
|
@@ -124,11 +117,61 @@ class Log {
|
|
|
124
117
|
if (!isEmpty(data)) text += '\n' + JSON.stringify(data)
|
|
125
118
|
}
|
|
126
119
|
console.log(text)
|
|
127
|
-
if (this.app.bajo.config.log.save) {
|
|
128
|
-
fs.ensureDirSync(`${this.app.bajo.dir.data}/log`)
|
|
129
|
-
// TODO: log write, rotation, etc
|
|
130
|
-
}
|
|
131
120
|
if (data instanceof Error && level === 'trace') console.error(data)
|
|
121
|
+
if (this.app.bajo.config.log.save) this.save(text, prefix)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Calculate pattern used for log rotation
|
|
126
|
+
*
|
|
127
|
+
* @method
|
|
128
|
+
* @param {boolean} isPrev - If true, calculate previous rotation pattern
|
|
129
|
+
* @returns {string} Calculated pattern
|
|
130
|
+
*/
|
|
131
|
+
getRotationPattern = (isPrev) => {
|
|
132
|
+
const { dayjs } = this.app.lib
|
|
133
|
+
const { cycle } = this.app.bajo.config.log.rotation
|
|
134
|
+
if (cycle === 'none') return
|
|
135
|
+
let pattern
|
|
136
|
+
const now = dayjs()
|
|
137
|
+
switch (cycle) {
|
|
138
|
+
case 'monthly': {
|
|
139
|
+
const dt = isPrev ? now.subtract(1, 'month') : now
|
|
140
|
+
pattern = dt.format('YYYY-MM')
|
|
141
|
+
break
|
|
142
|
+
}
|
|
143
|
+
case 'weekly': {
|
|
144
|
+
const dt = isPrev ? now.subtract(1, 'week') : now
|
|
145
|
+
pattern = dt.format(`YYYY-W${dt.week()}`)
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
case 'daily': {
|
|
149
|
+
const dt = isPrev ? now.subtract(1, 'day') : now
|
|
150
|
+
pattern = dt.format('YYYY-MM-DD')
|
|
151
|
+
break
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return pattern
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Save log to file in {dataDir}/log
|
|
159
|
+
*
|
|
160
|
+
* @method
|
|
161
|
+
* @param {string} text - Log message to save
|
|
162
|
+
* @param {string} prefix - Use prefix as basename. Defaults to 'bajo'
|
|
163
|
+
*/
|
|
164
|
+
save = (text, prefix = 'bajo') => {
|
|
165
|
+
const { fs } = this.app.lib
|
|
166
|
+
let fname = this.app.bajo.config.log.rotation.byPlugin ? prefix : 'bajo'
|
|
167
|
+
let file = `${this.logDir}/${fname}.log`
|
|
168
|
+
const content = stripVTControlCharacters(text)
|
|
169
|
+
const pattern = this.getRotationPattern()
|
|
170
|
+
if (pattern) {
|
|
171
|
+
file = `${this.logDir}/${fname}.${pattern}.log`
|
|
172
|
+
}
|
|
173
|
+
fs.appendFileSync(file, `${content}\n`, 'utf8')
|
|
174
|
+
// TODO: symlink bajo.log to target
|
|
132
175
|
}
|
|
133
176
|
|
|
134
177
|
/**
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"appRunningAsApplet": "App runs in applet mode",
|
|
23
23
|
"setupBootOrder": "Setup boot order",
|
|
24
24
|
"configHandlers%s": "Config handlers: %s",
|
|
25
|
+
"dataDir%s": "Data dir: %s",
|
|
25
26
|
"exited": "Exited",
|
|
26
27
|
"appShutdown": "App shutdown",
|
|
27
28
|
"appletModeActivated": "Applet mode activated",
|
package/extend/bajo/intl/id.json
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"appRunningAsApplet": "App berjalan di mode applet",
|
|
23
23
|
"setupBootOrder": "Atur urutan booting",
|
|
24
24
|
"configHandlers%s": "Pengatur konfigurasi: %s",
|
|
25
|
+
"dataDir%s": "Dir data: %s",
|
|
25
26
|
"exited": "Exited",
|
|
26
27
|
"appShutdown": "Aplikasi ditutup",
|
|
27
28
|
"appletModeActivated": "Mode applet diaktifkan",
|
package/package.json
CHANGED
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 |
|