@simplysm/core-node 14.0.16 → 14.0.17
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/README.md +27 -2
- package/dist/features/consola/file-reporter.d.ts +9 -0
- package/dist/features/consola/file-reporter.d.ts.map +1 -0
- package/dist/features/consola/file-reporter.js +108 -0
- package/dist/features/consola/file-reporter.js.map +1 -0
- package/dist/features/consola/pretty-reporter.d.ts +14 -0
- package/dist/features/consola/pretty-reporter.d.ts.map +1 -0
- package/dist/features/consola/pretty-reporter.js +139 -0
- package/dist/features/consola/pretty-reporter.js.map +1 -0
- package/dist/features/consola/setup-consola.d.ts +7 -0
- package/dist/features/consola/setup-consola.d.ts.map +1 -0
- package/dist/features/consola/setup-consola.js +35 -0
- package/dist/features/consola/setup-consola.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/cp.js +2 -2
- package/dist/utils/cp.js.map +1 -1
- package/docs/consola.md +141 -0
- package/package.json +3 -3
- package/src/features/consola/file-reporter.ts +127 -0
- package/src/features/consola/pretty-reporter.ts +172 -0
- package/src/features/consola/setup-consola.ts +40 -0
- package/src/index.ts +3 -0
- package/src/utils/cp.ts +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @simplysm/core-node
|
|
2
2
|
|
|
3
|
-
Node.js-specific core utilities for the Simplysm framework. Provides enhanced file system operations, child process execution, path utilities, file watching, and a type-safe worker thread abstraction.
|
|
3
|
+
Node.js-specific core utilities for the Simplysm framework. Provides enhanced file system operations, child process execution, path utilities, file watching, consola logging configuration, and a type-safe worker thread abstraction.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -82,7 +82,7 @@ Namespace `pathx` -- Path manipulation utilities.
|
|
|
82
82
|
|
|
83
83
|
> See [docs/pathx.md](./docs/pathx.md) for details.
|
|
84
84
|
|
|
85
|
-
### Features
|
|
85
|
+
### Features / FsWatcher
|
|
86
86
|
|
|
87
87
|
| API | Type | Description |
|
|
88
88
|
|-----|------|-------------|
|
|
@@ -92,6 +92,19 @@ Namespace `pathx` -- Path manipulation utilities.
|
|
|
92
92
|
|
|
93
93
|
> See [docs/fs-watcher.md](./docs/fs-watcher.md) for details.
|
|
94
94
|
|
|
95
|
+
### Features / Consola
|
|
96
|
+
|
|
97
|
+
| API | Type | Description |
|
|
98
|
+
|-----|------|-------------|
|
|
99
|
+
| `PrettyReporter` | class | Terminal consola reporter with icons, colors, and error stack formatting |
|
|
100
|
+
| `FileReporterOptions` | interface | Options for `createFileReporter` (maxSize, maxDays) |
|
|
101
|
+
| `createFileReporter` | function | Create a file-based consola reporter (JSON lines, date rotation) |
|
|
102
|
+
| `withMaxLevel` | function | Wrap a reporter to filter out log entries above a max level |
|
|
103
|
+
| `SetupConsolaOptions` | interface | Options for `setupConsola` |
|
|
104
|
+
| `setupConsola` | function | Configure consola reporters based on environment (prod/dev/debug) |
|
|
105
|
+
|
|
106
|
+
> See [docs/consola.md](./docs/consola.md) for details.
|
|
107
|
+
|
|
95
108
|
### Worker
|
|
96
109
|
|
|
97
110
|
| API | Type | Description |
|
|
@@ -162,6 +175,18 @@ const name = pathx.basenameWithoutExt("file.spec.ts"); // "file.spec"
|
|
|
162
175
|
const isChild = pathx.isChildPath("/a/b/c", "/a/b"); // true
|
|
163
176
|
```
|
|
164
177
|
|
|
178
|
+
### Consola logging
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
182
|
+
|
|
183
|
+
// Auto-configure based on environment (prod → file only, dev → file + terminal)
|
|
184
|
+
setupConsola();
|
|
185
|
+
|
|
186
|
+
// CLI mode — always use terminal output regardless of environment
|
|
187
|
+
setupConsola({ cli: true });
|
|
188
|
+
```
|
|
189
|
+
|
|
165
190
|
### File watcher
|
|
166
191
|
|
|
167
192
|
```typescript
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConsolaReporter } from "consola";
|
|
2
|
+
export interface FileReporterOptions {
|
|
3
|
+
/** @default 20MB */
|
|
4
|
+
maxSize?: number;
|
|
5
|
+
/** @default 14 */
|
|
6
|
+
maxDays?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function createFileReporter(options?: FileReporterOptions): ConsolaReporter;
|
|
9
|
+
//# sourceMappingURL=file-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-reporter.d.ts","sourceRoot":"","sources":["../../../src/features/consola/file-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,eAAe,EAAa,MAAM,SAAS,CAAC;AAI1E,MAAM,WAAW,mBAAmB;IAClC,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,eAAe,CAyEjF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
|
|
4
|
+
const DEFAULT_MAX_DAYS = 14;
|
|
5
|
+
export function createFileReporter(options) {
|
|
6
|
+
const maxSize = options?.maxSize ?? DEFAULT_MAX_SIZE;
|
|
7
|
+
const maxDays = options?.maxDays ?? DEFAULT_MAX_DAYS;
|
|
8
|
+
const outDir = path.resolve(process.cwd(), ".logs");
|
|
9
|
+
let dirEnsured = false;
|
|
10
|
+
let stream = null;
|
|
11
|
+
let currentDate = "";
|
|
12
|
+
let currentSize = 0;
|
|
13
|
+
let lastCleanDate = "";
|
|
14
|
+
function rotate(dateStr) {
|
|
15
|
+
if (stream != null) {
|
|
16
|
+
stream.end();
|
|
17
|
+
stream = null;
|
|
18
|
+
}
|
|
19
|
+
if (!dirEnsured) {
|
|
20
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
21
|
+
dirEnsured = true;
|
|
22
|
+
}
|
|
23
|
+
const filePath = resolveLogFilePath(outDir, dateStr, maxSize);
|
|
24
|
+
try {
|
|
25
|
+
currentSize = fs.statSync(filePath).size;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
currentSize = 0;
|
|
29
|
+
}
|
|
30
|
+
stream = fs.createWriteStream(filePath, { flags: "a" });
|
|
31
|
+
currentDate = dateStr;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
log(logObj, _ctx) {
|
|
35
|
+
const entry = {
|
|
36
|
+
time: logObj.date.toISOString(),
|
|
37
|
+
level: logObj.type.toUpperCase(),
|
|
38
|
+
};
|
|
39
|
+
if (logObj.tag) {
|
|
40
|
+
entry["tag"] = logObj.tag;
|
|
41
|
+
}
|
|
42
|
+
const msgs = [];
|
|
43
|
+
for (const a of logObj.args) {
|
|
44
|
+
if (a instanceof Error) {
|
|
45
|
+
entry["err"] = { message: a.message, stack: a.stack };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
msgs.push(typeof a === "string" ? a : String(a));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (msgs.length > 0) {
|
|
52
|
+
entry["msg"] = msgs.join(" ");
|
|
53
|
+
}
|
|
54
|
+
const line = JSON.stringify(entry) + "\n";
|
|
55
|
+
const date = logObj.date;
|
|
56
|
+
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
57
|
+
if (dateStr !== currentDate || currentSize + line.length >= maxSize) {
|
|
58
|
+
rotate(dateStr);
|
|
59
|
+
}
|
|
60
|
+
stream.write(line);
|
|
61
|
+
currentSize += line.length;
|
|
62
|
+
if (lastCleanDate !== dateStr) {
|
|
63
|
+
lastCleanDate = dateStr;
|
|
64
|
+
cleanOldFiles(outDir, maxDays);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function resolveLogFilePath(outDir, dateStr, maxSize) {
|
|
70
|
+
const basePath = path.join(outDir, `app.${dateStr}.log`);
|
|
71
|
+
if (!fs.existsSync(basePath))
|
|
72
|
+
return basePath;
|
|
73
|
+
if (fs.statSync(basePath).size < maxSize)
|
|
74
|
+
return basePath;
|
|
75
|
+
let seq = 1;
|
|
76
|
+
while (true) {
|
|
77
|
+
const seqPath = path.join(outDir, `app.${dateStr}.${seq}.log`);
|
|
78
|
+
if (!fs.existsSync(seqPath))
|
|
79
|
+
return seqPath;
|
|
80
|
+
if (fs.statSync(seqPath).size < maxSize)
|
|
81
|
+
return seqPath;
|
|
82
|
+
seq++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function cleanOldFiles(outDir, maxDays) {
|
|
86
|
+
let entries;
|
|
87
|
+
try {
|
|
88
|
+
entries = fs.readdirSync(outDir);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const cutoff = new Date();
|
|
94
|
+
cutoff.setDate(cutoff.getDate() - maxDays);
|
|
95
|
+
const cutoffStr = `${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, "0")}-${String(cutoff.getDate()).padStart(2, "0")}`;
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
const match = /^app\.(\d{4}-\d{2}-\d{2})(?:\.\d+)?\.log$/.exec(entry);
|
|
98
|
+
if (match != null && match[1] < cutoffStr) {
|
|
99
|
+
try {
|
|
100
|
+
fs.unlinkSync(path.join(outDir, entry));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// ignore
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=file-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-reporter.js","sourceRoot":"","sources":["../../../src/features/consola/file-reporter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AASxB,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1C,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,MAAM,UAAU,kBAAkB,CAAC,OAA6B;IAC9D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,gBAAgB,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,gBAAgB,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IAEpD,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,MAAM,GAA0B,IAAI,CAAC;IACzC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,SAAS,MAAM,CAAC,OAAe;QAC7B,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACxD,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,OAAO;QACL,GAAG,CAAC,MAAiB,EAAE,IAAiC;YACtD,MAAM,KAAK,GAA4B;gBACrC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;gBAC/B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;aACjC,CAAC;YACF,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;gBACf,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;YAC5B,CAAC;YAED,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC;oBACvB,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;gBACxD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;YAE1C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACzB,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAEnI,IAAI,OAAO,KAAK,WAAW,IAAI,WAAW,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC;gBACpE,MAAM,CAAC,OAAO,CAAC,CAAC;YAClB,CAAC;YAED,MAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC;YAE3B,IAAI,aAAa,KAAK,OAAO,EAAE,CAAC;gBAC9B,aAAa,GAAG,OAAO,CAAC;gBACxB,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc,EAAE,OAAe,EAAE,OAAe;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,OAAO;QAAE,OAAO,QAAQ,CAAC;IAE1D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,OAAO,IAAI,GAAG,MAAM,CAAC,CAAC;QAC/D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC;QAC5C,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,GAAG,OAAO;YAAE,OAAO,OAAO,CAAC;QACxD,GAAG,EAAE,CAAC;IACR,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,OAAe;IACpD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAC1B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAE3I,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,2CAA2C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConsolaReporter, LogObject, ConsolaOptions } from "consola";
|
|
2
|
+
export declare class PrettyReporter implements ConsolaReporter {
|
|
3
|
+
log(logObj: LogObject, ctx: {
|
|
4
|
+
options: ConsolaOptions;
|
|
5
|
+
}): void;
|
|
6
|
+
private _formatLogObj;
|
|
7
|
+
private _formatArgs;
|
|
8
|
+
private _formatError;
|
|
9
|
+
private _formatStack;
|
|
10
|
+
private _formatIcon;
|
|
11
|
+
private _formatDate;
|
|
12
|
+
private _formatBox;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=pretty-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretty-reporter.d.ts","sourceRoot":"","sources":["../../../src/features/consola/pretty-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA4E1E,qBAAa,cAAe,YAAW,eAAe;IACpD,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE;QAAE,OAAO,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI;IAe9D,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,UAAU;CAMnB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { formatWithOptions } from "node:util";
|
|
2
|
+
import { sep } from "node:path";
|
|
3
|
+
import { env } from "@simplysm/core-common";
|
|
4
|
+
// -- Constants ----------------------------------------------------------------
|
|
5
|
+
const TYPE_ICONS = {
|
|
6
|
+
error: "\u2716",
|
|
7
|
+
fatal: "\u2716",
|
|
8
|
+
ready: "\u2714",
|
|
9
|
+
warn: "\u26A0",
|
|
10
|
+
info: "\u2139",
|
|
11
|
+
success: "\u2714",
|
|
12
|
+
debug: "\u2699",
|
|
13
|
+
trace: "\u2192",
|
|
14
|
+
fail: "\u2716",
|
|
15
|
+
start: "\u25D0",
|
|
16
|
+
log: "",
|
|
17
|
+
};
|
|
18
|
+
const TYPE_COLORS = {
|
|
19
|
+
info: "cyan",
|
|
20
|
+
fail: "red",
|
|
21
|
+
success: "green",
|
|
22
|
+
ready: "green",
|
|
23
|
+
start: "magenta",
|
|
24
|
+
};
|
|
25
|
+
const LEVEL_COLORS = {
|
|
26
|
+
0: "red",
|
|
27
|
+
1: "yellow",
|
|
28
|
+
};
|
|
29
|
+
const ANSI_CODES = {
|
|
30
|
+
gray: "\x1b[90m",
|
|
31
|
+
red: "\x1b[31m",
|
|
32
|
+
green: "\x1b[32m",
|
|
33
|
+
yellow: "\x1b[33m",
|
|
34
|
+
cyan: "\x1b[36m",
|
|
35
|
+
magenta: "\x1b[35m",
|
|
36
|
+
};
|
|
37
|
+
const ANSI_RESET = "\x1b[0m";
|
|
38
|
+
// -- Helpers ------------------------------------------------------------------
|
|
39
|
+
function colorize(color, text, enabled) {
|
|
40
|
+
if (!enabled)
|
|
41
|
+
return text;
|
|
42
|
+
return `${ANSI_CODES[color]}${text}${ANSI_RESET}`;
|
|
43
|
+
}
|
|
44
|
+
function writeStream(data, stream) {
|
|
45
|
+
const s = stream;
|
|
46
|
+
const write = s.__write ?? s.write;
|
|
47
|
+
write.call(stream, data);
|
|
48
|
+
}
|
|
49
|
+
function detectColorSupport() {
|
|
50
|
+
if (env("NO_COLOR") != null)
|
|
51
|
+
return false;
|
|
52
|
+
if (env("FORCE_COLOR") != null)
|
|
53
|
+
return true;
|
|
54
|
+
if (process.stdout.isTTY === true)
|
|
55
|
+
return true;
|
|
56
|
+
return process.platform === "win32";
|
|
57
|
+
}
|
|
58
|
+
export class PrettyReporter {
|
|
59
|
+
log(logObj, ctx) {
|
|
60
|
+
const opts = {
|
|
61
|
+
...ctx.options.formatOptions,
|
|
62
|
+
colors: detectColorSupport(),
|
|
63
|
+
};
|
|
64
|
+
const line = this._formatLogObj(logObj, opts);
|
|
65
|
+
const stream = logObj.level < 2
|
|
66
|
+
? ctx.options.stderr ?? process.stderr
|
|
67
|
+
: ctx.options.stdout ?? process.stdout;
|
|
68
|
+
writeStream(line + "\n", stream);
|
|
69
|
+
}
|
|
70
|
+
_formatLogObj(logObj, opts) {
|
|
71
|
+
const formattedArgs = this._formatArgs(logObj.args, opts);
|
|
72
|
+
const [message, ...additional] = formattedArgs.split("\n");
|
|
73
|
+
if (logObj.type === "box") {
|
|
74
|
+
return this._formatBox(logObj, formattedArgs);
|
|
75
|
+
}
|
|
76
|
+
const tag = logObj.tag !== "" ? colorize("gray", `[${logObj.tag}]`, opts.colors) : "";
|
|
77
|
+
const icon = this._formatIcon(logObj, opts.colors);
|
|
78
|
+
const date = this._formatDate(logObj.date, opts);
|
|
79
|
+
const coloredDate = date !== "" ? colorize("gray", date, opts.colors) : "";
|
|
80
|
+
let fullLine = [tag, icon, message, coloredDate].filter(Boolean).join(" ");
|
|
81
|
+
if (additional.length > 0) {
|
|
82
|
+
fullLine += "\n" + additional.join("\n");
|
|
83
|
+
}
|
|
84
|
+
if (logObj.type === "trace") {
|
|
85
|
+
const err = new Error("Trace: " + logObj.message);
|
|
86
|
+
fullLine += this._formatStack(err.stack ?? "", err.message);
|
|
87
|
+
}
|
|
88
|
+
const isBadge = logObj.badge ?? logObj.level < 2;
|
|
89
|
+
return isBadge ? "\n" + fullLine + "\n" : fullLine;
|
|
90
|
+
}
|
|
91
|
+
_formatArgs(args, opts) {
|
|
92
|
+
const processed = args.map((arg) => {
|
|
93
|
+
if (arg != null && typeof arg === "object" && typeof arg.stack === "string") {
|
|
94
|
+
return this._formatError(arg, opts);
|
|
95
|
+
}
|
|
96
|
+
return arg;
|
|
97
|
+
});
|
|
98
|
+
return formatWithOptions({ colors: opts.colors, compact: opts.compact }, ...processed);
|
|
99
|
+
}
|
|
100
|
+
_formatError(err, opts) {
|
|
101
|
+
const message = err.message;
|
|
102
|
+
const stack = err.stack != null ? this._formatStack(err.stack, message, opts) : "";
|
|
103
|
+
const level = opts.errorLevel ?? 0;
|
|
104
|
+
const prefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : "";
|
|
105
|
+
const cause = err.cause instanceof Error
|
|
106
|
+
? "\n\n" + this._formatError(err.cause, { ...opts, errorLevel: level + 1 })
|
|
107
|
+
: "";
|
|
108
|
+
return prefix + message + "\n" + stack + cause;
|
|
109
|
+
}
|
|
110
|
+
_formatStack(stack, message, opts) {
|
|
111
|
+
const cwd = process.cwd() + sep;
|
|
112
|
+
const indent = " ".repeat((opts?.errorLevel ?? 0) + 1);
|
|
113
|
+
const lines = stack
|
|
114
|
+
.split("\n")
|
|
115
|
+
.splice(message.split("\n").length)
|
|
116
|
+
.map((l) => l.trim().replace("file://", "").replace(cwd, ""));
|
|
117
|
+
return `\n${indent}` + lines.map((l) => ` ${l}`).join(`\n${indent}`);
|
|
118
|
+
}
|
|
119
|
+
_formatIcon(logObj, useColors) {
|
|
120
|
+
const icon = TYPE_ICONS[logObj.type] ?? "";
|
|
121
|
+
if (icon === "")
|
|
122
|
+
return "";
|
|
123
|
+
const color = TYPE_COLORS[logObj.type] ?? LEVEL_COLORS[logObj.level] ?? "gray";
|
|
124
|
+
return colorize(color, icon, useColors);
|
|
125
|
+
}
|
|
126
|
+
_formatDate(date, opts) {
|
|
127
|
+
if (!opts.date)
|
|
128
|
+
return "";
|
|
129
|
+
const base = date.toLocaleTimeString();
|
|
130
|
+
return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
|
|
131
|
+
}
|
|
132
|
+
_formatBox(logObj, message) {
|
|
133
|
+
const tag = logObj.tag !== "" ? `[${logObj.tag}]` : "";
|
|
134
|
+
const title = logObj.title;
|
|
135
|
+
const lines = [tag, title, ...message.split("\n")].filter(Boolean);
|
|
136
|
+
return "\n" + lines.map((l) => ` > ${l}`).join("\n") + "\n";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=pretty-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretty-reporter.js","sourceRoot":"","sources":["../../../src/features/consola/pretty-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConsolaReporter } from "consola";
|
|
2
|
+
export declare function withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter;
|
|
3
|
+
export interface SetupConsolaOptions {
|
|
4
|
+
cli?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function setupConsola(opts?: SetupConsolaOptions): void;
|
|
7
|
+
//# sourceMappingURL=setup-consola.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-consola.d.ts","sourceRoot":"","sources":["../../../src/features/consola/setup-consola.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,eAAe,EAAa,MAAM,SAAS,CAAC;AAM1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAOzF;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAoB7D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import consola, { LogLevels } from "consola";
|
|
2
|
+
import { env, parseBoolEnv } from "@simplysm/core-common";
|
|
3
|
+
import { PrettyReporter } from "./pretty-reporter.js";
|
|
4
|
+
import { createFileReporter } from "./file-reporter.js";
|
|
5
|
+
export function withMaxLevel(reporter, maxLevel) {
|
|
6
|
+
return {
|
|
7
|
+
log(logObj, ctx) {
|
|
8
|
+
if (logObj.level > maxLevel)
|
|
9
|
+
return;
|
|
10
|
+
reporter.log(logObj, ctx);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function setupConsola(opts) {
|
|
15
|
+
if (!opts?.cli && !parseBoolEnv(env("DEV"))) {
|
|
16
|
+
// prod: debug 포함 FileReporter
|
|
17
|
+
consola.level = LogLevels.debug;
|
|
18
|
+
consola.options.reporters = [createFileReporter()];
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (parseBoolEnv(env("SD_DEBUG"))) {
|
|
22
|
+
// dev + SD_DEBUG: debug 포함 PrettyReporter
|
|
23
|
+
consola.level = LogLevels.debug;
|
|
24
|
+
consola.options.reporters = [new PrettyReporter()];
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// dev: debug 포함 FileReporter + debug 비포함 PrettyReporter
|
|
28
|
+
consola.level = LogLevels.debug;
|
|
29
|
+
consola.options.reporters = [
|
|
30
|
+
createFileReporter(),
|
|
31
|
+
withMaxLevel(new PrettyReporter(), LogLevels.info),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=setup-consola.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-consola.js","sourceRoot":"","sources":["../../../src/features/consola/setup-consola.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,UAAU,YAAY,CAAC,QAAyB,EAAE,QAAgB;IACtE,OAAO;QACL,GAAG,CAAC,MAAiB,EAAE,GAAgC;YACrD,IAAI,MAAM,CAAC,KAAK,GAAG,QAAQ;gBAAE,OAAO;YACpC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC;AAMD,MAAM,UAAU,YAAY,CAAC,IAA0B;IACrD,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC5C,8BAA8B;QAC9B,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAClC,0CAA0C;QAC1C,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,wDAAwD;QACxD,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG;YAC1B,kBAAkB,EAAE;YACpB,YAAY,CAAC,IAAI,cAAc,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC;SACnD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export * as cpx from "./utils/cp";
|
|
|
2
2
|
export * as fsx from "./utils/fs";
|
|
3
3
|
export * as pathx from "./utils/path";
|
|
4
4
|
export * from "./features/fs-watcher";
|
|
5
|
+
export * from "./features/consola/pretty-reporter";
|
|
6
|
+
export * from "./features/consola/file-reporter";
|
|
7
|
+
export * from "./features/consola/setup-consola";
|
|
5
8
|
export * from "./worker/types";
|
|
6
9
|
export * from "./worker/worker";
|
|
7
10
|
export * from "./worker/create-worker";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,cAAc,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AAGjD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,9 @@ export * as fsx from "./utils/fs.js";
|
|
|
4
4
|
export * as pathx from "./utils/path.js";
|
|
5
5
|
// 기능
|
|
6
6
|
export * from "./features/fs-watcher.js";
|
|
7
|
+
export * from "./features/consola/pretty-reporter.js";
|
|
8
|
+
export * from "./features/consola/file-reporter.js";
|
|
9
|
+
export * from "./features/consola/setup-consola.js";
|
|
7
10
|
// 워커
|
|
8
11
|
export * from "./worker/types.js";
|
|
9
12
|
export * from "./worker/worker.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,KAAK;AACL,cAAc,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,KAAK;AACL,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AAEjD,KAAK;AACL,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC"}
|
package/dist/utils/cp.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync as cpExecSync, spawn as cpSpawn, spawnSync as cpSpawnSync } from "child_process";
|
|
2
|
-
import { bytes } from "@simplysm/core-common";
|
|
2
|
+
import { bytes, env } from "@simplysm/core-common";
|
|
3
3
|
const CODE_PAGE_MAP = {
|
|
4
4
|
65001: "utf-8",
|
|
5
5
|
949: "euc-kr",
|
|
@@ -31,7 +31,7 @@ export function getSystemEncoding() {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
const lang =
|
|
34
|
+
const lang = env("LANG") ?? env("LC_ALL") ?? "";
|
|
35
35
|
const dotIndex = lang.indexOf(".");
|
|
36
36
|
if (dotIndex >= 0) {
|
|
37
37
|
let encoding = lang.slice(dotIndex + 1).split("@")[0].toLowerCase();
|
package/dist/utils/cp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cp.js","sourceRoot":"","sources":["../../src/utils/cp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,KAAK,IAAI,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"cp.js","sourceRoot":"","sources":["../../src/utils/cp.ts"],"names":[],"mappings":"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"}
|
package/docs/consola.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Consola
|
|
2
|
+
|
|
3
|
+
Consola logging utilities for environment-aware reporter configuration. Provides a terminal pretty-printer, a file-based JSON logger with rotation, and a one-call setup function.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import {
|
|
7
|
+
setupConsola,
|
|
8
|
+
withMaxLevel,
|
|
9
|
+
PrettyReporter,
|
|
10
|
+
createFileReporter,
|
|
11
|
+
} from "@simplysm/core-node";
|
|
12
|
+
import type { SetupConsolaOptions, FileReporterOptions } from "@simplysm/core-node";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Types
|
|
16
|
+
|
|
17
|
+
### SetupConsolaOptions
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
interface SetupConsolaOptions {
|
|
21
|
+
cli?: boolean;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
| Field | Type | Description |
|
|
26
|
+
|-------|------|-------------|
|
|
27
|
+
| `cli` | `boolean` | When `true`, always use `PrettyReporter` regardless of environment (for CLI tools) |
|
|
28
|
+
|
|
29
|
+
### FileReporterOptions
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
interface FileReporterOptions {
|
|
33
|
+
maxSize?: number;
|
|
34
|
+
maxDays?: number;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
| Field | Type | Description |
|
|
39
|
+
|-------|------|-------------|
|
|
40
|
+
| `maxSize` | `number` | Maximum size per log file in bytes. Default: `20 * 1024 * 1024` (20 MB). When exceeded, a new sequenced file is created (e.g., `app.2026-04-03.1.log`). |
|
|
41
|
+
| `maxDays` | `number` | Number of days to retain log files. Default: `14`. Files older than this are deleted on the next log write. |
|
|
42
|
+
|
|
43
|
+
## PrettyReporter
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
class PrettyReporter implements ConsolaReporter {
|
|
47
|
+
log(logObj: LogObject, ctx: { options: ConsolaOptions }): void;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A terminal-oriented consola reporter. Formats log output with:
|
|
52
|
+
- Type-specific icons (e.g., checkmark for success, cross for error, gear for debug)
|
|
53
|
+
- ANSI color coding based on log type and level (respects `NO_COLOR`/`FORCE_COLOR` env vars)
|
|
54
|
+
- Error stack trace formatting with relative paths and cause chain support
|
|
55
|
+
- Badge-style formatting (extra newlines) for error/fatal level messages
|
|
56
|
+
- Box formatting for `box` type log entries
|
|
57
|
+
- Timestamp display when `formatOptions.date` is enabled
|
|
58
|
+
|
|
59
|
+
Errors at level < 2 are written to stderr; all others to stdout.
|
|
60
|
+
|
|
61
|
+
## Functions
|
|
62
|
+
|
|
63
|
+
### setupConsola
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
function setupConsola(opts?: SetupConsolaOptions): void
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Configure the global `consola` instance with appropriate reporters based on the runtime environment. Sets the log level to `debug` in all cases.
|
|
70
|
+
|
|
71
|
+
| Environment | Behavior |
|
|
72
|
+
|-------------|----------|
|
|
73
|
+
| Production (`env.DEV` is falsy, `cli` not set) | `FileReporter` only -- all logs (including debug) go to `.logs/` |
|
|
74
|
+
| Development + `SD_DEBUG` env var | `PrettyReporter` only -- all logs (including debug) to terminal |
|
|
75
|
+
| Development (default) | `FileReporter` (all levels) + `PrettyReporter` (info and below only) |
|
|
76
|
+
| `cli: true` | Same as `SD_DEBUG` mode -- always uses `PrettyReporter` |
|
|
77
|
+
|
|
78
|
+
| Parameter | Type | Description |
|
|
79
|
+
|-----------|------|-------------|
|
|
80
|
+
| `opts` | `SetupConsolaOptions` | Optional configuration |
|
|
81
|
+
|
|
82
|
+
### createFileReporter
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
function createFileReporter(options?: FileReporterOptions): ConsolaReporter
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Create a file-based consola reporter that writes JSON-line entries to `.logs/` directory.
|
|
89
|
+
|
|
90
|
+
| Parameter | Type | Description |
|
|
91
|
+
|-----------|------|-------------|
|
|
92
|
+
| `options` | `FileReporterOptions` | Optional size and retention settings |
|
|
93
|
+
|
|
94
|
+
File naming: `app.YYYY-MM-DD.log`, with sequential suffix (`app.YYYY-MM-DD.1.log`) when size limit is reached.
|
|
95
|
+
|
|
96
|
+
Each log entry is a single JSON line with fields:
|
|
97
|
+
|
|
98
|
+
| Field | Type | Description |
|
|
99
|
+
|-------|------|-------------|
|
|
100
|
+
| `time` | `string` | ISO 8601 timestamp |
|
|
101
|
+
| `level` | `string` | Uppercase log type (e.g., `"INFO"`, `"ERROR"`) |
|
|
102
|
+
| `tag` | `string` | Log tag (omitted if empty) |
|
|
103
|
+
| `msg` | `string` | Concatenated message arguments (omitted if none) |
|
|
104
|
+
| `err` | `{ message, stack }` | Error details (present when an Error argument is logged) |
|
|
105
|
+
|
|
106
|
+
Log rotation: when the date changes or file size exceeds `maxSize`, a new file is opened. Files older than `maxDays` are automatically cleaned up.
|
|
107
|
+
|
|
108
|
+
### withMaxLevel
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
function withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Wrap a consola reporter to suppress log entries above a specified level. Log entries with `logObj.level > maxLevel` are silently dropped.
|
|
115
|
+
|
|
116
|
+
| Parameter | Type | Description |
|
|
117
|
+
|-----------|------|-------------|
|
|
118
|
+
| `reporter` | `ConsolaReporter` | The reporter to wrap |
|
|
119
|
+
| `maxLevel` | `number` | Maximum log level to pass through (e.g., `LogLevels.info` for info and below) |
|
|
120
|
+
|
|
121
|
+
## Usage
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { setupConsola, createFileReporter, PrettyReporter, withMaxLevel } from "@simplysm/core-node";
|
|
125
|
+
import consola, { LogLevels } from "consola";
|
|
126
|
+
|
|
127
|
+
// One-call setup (recommended)
|
|
128
|
+
setupConsola();
|
|
129
|
+
|
|
130
|
+
// Manual configuration example
|
|
131
|
+
consola.level = LogLevels.debug;
|
|
132
|
+
consola.options.reporters = [
|
|
133
|
+
createFileReporter({ maxSize: 10 * 1024 * 1024, maxDays: 7 }),
|
|
134
|
+
withMaxLevel(new PrettyReporter(), LogLevels.info),
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
// Then use consola as usual
|
|
138
|
+
consola.info("Server started on port 3000");
|
|
139
|
+
consola.debug("Connection pool initialized");
|
|
140
|
+
consola.error(new Error("Database connection failed"));
|
|
141
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/core-node",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.17",
|
|
4
4
|
"description": "심플리즘 패키지 - 코어 (node)",
|
|
5
5
|
"author": "심플리즘",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"glob": "^13.0.6",
|
|
26
26
|
"minimatch": "^10.2.5",
|
|
27
27
|
"tsx": "^4.21.0",
|
|
28
|
-
"@simplysm/core-common": "14.0.
|
|
28
|
+
"@simplysm/core-common": "14.0.17"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@types/node": "^20.19.
|
|
31
|
+
"@types/node": "^20.19.39"
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { ConsolaOptions, ConsolaReporter, LogObject } from "consola";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
export interface FileReporterOptions {
|
|
6
|
+
/** @default 20MB */
|
|
7
|
+
maxSize?: number;
|
|
8
|
+
/** @default 14 */
|
|
9
|
+
maxDays?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
|
|
13
|
+
const DEFAULT_MAX_DAYS = 14;
|
|
14
|
+
|
|
15
|
+
export function createFileReporter(options?: FileReporterOptions): ConsolaReporter {
|
|
16
|
+
const maxSize = options?.maxSize ?? DEFAULT_MAX_SIZE;
|
|
17
|
+
const maxDays = options?.maxDays ?? DEFAULT_MAX_DAYS;
|
|
18
|
+
const outDir = path.resolve(process.cwd(), ".logs");
|
|
19
|
+
|
|
20
|
+
let dirEnsured = false;
|
|
21
|
+
let stream: fs.WriteStream | null = null;
|
|
22
|
+
let currentDate = "";
|
|
23
|
+
let currentSize = 0;
|
|
24
|
+
let lastCleanDate = "";
|
|
25
|
+
|
|
26
|
+
function rotate(dateStr: string): void {
|
|
27
|
+
if (stream != null) {
|
|
28
|
+
stream.end();
|
|
29
|
+
stream = null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!dirEnsured) {
|
|
33
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
34
|
+
dirEnsured = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const filePath = resolveLogFilePath(outDir, dateStr, maxSize);
|
|
38
|
+
try {
|
|
39
|
+
currentSize = fs.statSync(filePath).size;
|
|
40
|
+
} catch {
|
|
41
|
+
currentSize = 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
stream = fs.createWriteStream(filePath, { flags: "a" });
|
|
45
|
+
currentDate = dateStr;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
log(logObj: LogObject, _ctx: { options: ConsolaOptions }) {
|
|
50
|
+
const entry: Record<string, unknown> = {
|
|
51
|
+
time: logObj.date.toISOString(),
|
|
52
|
+
level: logObj.type.toUpperCase(),
|
|
53
|
+
};
|
|
54
|
+
if (logObj.tag) {
|
|
55
|
+
entry["tag"] = logObj.tag;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const msgs: string[] = [];
|
|
59
|
+
for (const a of logObj.args) {
|
|
60
|
+
if (a instanceof Error) {
|
|
61
|
+
entry["err"] = { message: a.message, stack: a.stack };
|
|
62
|
+
} else {
|
|
63
|
+
msgs.push(typeof a === "string" ? a : String(a));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (msgs.length > 0) {
|
|
67
|
+
entry["msg"] = msgs.join(" ");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const line = JSON.stringify(entry) + "\n";
|
|
71
|
+
|
|
72
|
+
const date = logObj.date;
|
|
73
|
+
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
74
|
+
|
|
75
|
+
if (dateStr !== currentDate || currentSize + line.length >= maxSize) {
|
|
76
|
+
rotate(dateStr);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
stream!.write(line);
|
|
80
|
+
currentSize += line.length;
|
|
81
|
+
|
|
82
|
+
if (lastCleanDate !== dateStr) {
|
|
83
|
+
lastCleanDate = dateStr;
|
|
84
|
+
cleanOldFiles(outDir, maxDays);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function resolveLogFilePath(outDir: string, dateStr: string, maxSize: number): string {
|
|
91
|
+
const basePath = path.join(outDir, `app.${dateStr}.log`);
|
|
92
|
+
|
|
93
|
+
if (!fs.existsSync(basePath)) return basePath;
|
|
94
|
+
if (fs.statSync(basePath).size < maxSize) return basePath;
|
|
95
|
+
|
|
96
|
+
let seq = 1;
|
|
97
|
+
while (true) {
|
|
98
|
+
const seqPath = path.join(outDir, `app.${dateStr}.${seq}.log`);
|
|
99
|
+
if (!fs.existsSync(seqPath)) return seqPath;
|
|
100
|
+
if (fs.statSync(seqPath).size < maxSize) return seqPath;
|
|
101
|
+
seq++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function cleanOldFiles(outDir: string, maxDays: number): void {
|
|
106
|
+
let entries: string[];
|
|
107
|
+
try {
|
|
108
|
+
entries = fs.readdirSync(outDir);
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const cutoff = new Date();
|
|
114
|
+
cutoff.setDate(cutoff.getDate() - maxDays);
|
|
115
|
+
const cutoffStr = `${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, "0")}-${String(cutoff.getDate()).padStart(2, "0")}`;
|
|
116
|
+
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
const match = /^app\.(\d{4}-\d{2}-\d{2})(?:\.\d+)?\.log$/.exec(entry);
|
|
119
|
+
if (match != null && match[1] < cutoffStr) {
|
|
120
|
+
try {
|
|
121
|
+
fs.unlinkSync(path.join(outDir, entry));
|
|
122
|
+
} catch {
|
|
123
|
+
// ignore
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { ConsolaReporter, LogObject, ConsolaOptions } from "consola";
|
|
2
|
+
import { formatWithOptions } from "node:util";
|
|
3
|
+
import { sep } from "node:path";
|
|
4
|
+
import { env } from "@simplysm/core-common";
|
|
5
|
+
|
|
6
|
+
// -- Constants ----------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
const TYPE_ICONS: Record<string, string> = {
|
|
9
|
+
error: "\u2716",
|
|
10
|
+
fatal: "\u2716",
|
|
11
|
+
ready: "\u2714",
|
|
12
|
+
warn: "\u26A0",
|
|
13
|
+
info: "\u2139",
|
|
14
|
+
success: "\u2714",
|
|
15
|
+
debug: "\u2699",
|
|
16
|
+
trace: "\u2192",
|
|
17
|
+
fail: "\u2716",
|
|
18
|
+
start: "\u25D0",
|
|
19
|
+
log: "",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type AnsiColor = "gray" | "red" | "green" | "yellow" | "cyan" | "magenta";
|
|
23
|
+
|
|
24
|
+
const TYPE_COLORS: Record<string, AnsiColor | undefined> = {
|
|
25
|
+
info: "cyan",
|
|
26
|
+
fail: "red",
|
|
27
|
+
success: "green",
|
|
28
|
+
ready: "green",
|
|
29
|
+
start: "magenta",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const LEVEL_COLORS: Record<number, AnsiColor | undefined> = {
|
|
33
|
+
0: "red",
|
|
34
|
+
1: "yellow",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const ANSI_CODES: Record<AnsiColor, string> = {
|
|
38
|
+
gray: "\x1b[90m",
|
|
39
|
+
red: "\x1b[31m",
|
|
40
|
+
green: "\x1b[32m",
|
|
41
|
+
yellow: "\x1b[33m",
|
|
42
|
+
cyan: "\x1b[36m",
|
|
43
|
+
magenta: "\x1b[35m",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const ANSI_RESET = "\x1b[0m";
|
|
47
|
+
|
|
48
|
+
// -- Helpers ------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
function colorize(color: AnsiColor, text: string, enabled: boolean): string {
|
|
51
|
+
if (!enabled) return text;
|
|
52
|
+
return `${ANSI_CODES[color]}${text}${ANSI_RESET}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function writeStream(data: string, stream: NodeJS.WritableStream): void {
|
|
56
|
+
const s = stream as NodeJS.WritableStream & { __write?: typeof stream.write };
|
|
57
|
+
const write = s.__write ?? s.write;
|
|
58
|
+
write.call(stream, data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function detectColorSupport(): boolean {
|
|
62
|
+
if (env("NO_COLOR") != null) return false;
|
|
63
|
+
if (env("FORCE_COLOR") != null) return true;
|
|
64
|
+
if (process.stdout.isTTY === true) return true;
|
|
65
|
+
return process.platform === "win32";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// -- Reporter -----------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
interface FormatOpts {
|
|
71
|
+
date?: boolean;
|
|
72
|
+
colors: boolean;
|
|
73
|
+
compact?: boolean | number;
|
|
74
|
+
errorLevel?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class PrettyReporter implements ConsolaReporter {
|
|
78
|
+
log(logObj: LogObject, ctx: { options: ConsolaOptions }): void {
|
|
79
|
+
const opts: FormatOpts = {
|
|
80
|
+
...ctx.options.formatOptions,
|
|
81
|
+
colors: detectColorSupport(),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const line = this._formatLogObj(logObj, opts);
|
|
85
|
+
const stream =
|
|
86
|
+
logObj.level < 2
|
|
87
|
+
? ctx.options.stderr ?? process.stderr
|
|
88
|
+
: ctx.options.stdout ?? process.stdout;
|
|
89
|
+
|
|
90
|
+
writeStream(line + "\n", stream);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private _formatLogObj(logObj: LogObject, opts: FormatOpts): string {
|
|
94
|
+
const formattedArgs = this._formatArgs(logObj.args, opts);
|
|
95
|
+
const [message, ...additional] = formattedArgs.split("\n");
|
|
96
|
+
|
|
97
|
+
if (logObj.type === "box") {
|
|
98
|
+
return this._formatBox(logObj, formattedArgs);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const tag = logObj.tag !== "" ? colorize("gray", `[${logObj.tag}]`, opts.colors) : "";
|
|
102
|
+
const icon = this._formatIcon(logObj, opts.colors);
|
|
103
|
+
const date = this._formatDate(logObj.date, opts);
|
|
104
|
+
const coloredDate = date !== "" ? colorize("gray", date, opts.colors) : "";
|
|
105
|
+
|
|
106
|
+
let fullLine = [tag, icon, message, coloredDate].filter(Boolean).join(" ");
|
|
107
|
+
|
|
108
|
+
if (additional.length > 0) {
|
|
109
|
+
fullLine += "\n" + additional.join("\n");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (logObj.type === "trace") {
|
|
113
|
+
const err = new Error("Trace: " + logObj.message);
|
|
114
|
+
fullLine += this._formatStack(err.stack ?? "", err.message);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const isBadge = (logObj as LogObject & { badge?: boolean }).badge ?? logObj.level < 2;
|
|
118
|
+
return isBadge ? "\n" + fullLine + "\n" : fullLine;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private _formatArgs(args: unknown[], opts: FormatOpts): string {
|
|
122
|
+
const processed = args.map((arg) => {
|
|
123
|
+
if (arg != null && typeof arg === "object" && typeof (arg as Error).stack === "string") {
|
|
124
|
+
return this._formatError(arg as Error, opts);
|
|
125
|
+
}
|
|
126
|
+
return arg;
|
|
127
|
+
});
|
|
128
|
+
return formatWithOptions({ colors: opts.colors, compact: opts.compact }, ...processed);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private _formatError(err: Error, opts: FormatOpts): string {
|
|
132
|
+
const message = err.message;
|
|
133
|
+
const stack = err.stack != null ? this._formatStack(err.stack, message, opts) : "";
|
|
134
|
+
const level = opts.errorLevel ?? 0;
|
|
135
|
+
const prefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : "";
|
|
136
|
+
const cause =
|
|
137
|
+
err.cause instanceof Error
|
|
138
|
+
? "\n\n" + this._formatError(err.cause, { ...opts, errorLevel: level + 1 })
|
|
139
|
+
: "";
|
|
140
|
+
return prefix + message + "\n" + stack + cause;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private _formatStack(stack: string, message: string, opts?: FormatOpts): string {
|
|
144
|
+
const cwd = process.cwd() + sep;
|
|
145
|
+
const indent = " ".repeat((opts?.errorLevel ?? 0) + 1);
|
|
146
|
+
const lines = stack
|
|
147
|
+
.split("\n")
|
|
148
|
+
.splice(message.split("\n").length)
|
|
149
|
+
.map((l) => l.trim().replace("file://", "").replace(cwd, ""));
|
|
150
|
+
return `\n${indent}` + lines.map((l) => ` ${l}`).join(`\n${indent}`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private _formatIcon(logObj: LogObject, useColors: boolean): string {
|
|
154
|
+
const icon = TYPE_ICONS[logObj.type] ?? "";
|
|
155
|
+
if (icon === "") return "";
|
|
156
|
+
const color: AnsiColor = TYPE_COLORS[logObj.type] ?? LEVEL_COLORS[logObj.level] ?? "gray";
|
|
157
|
+
return colorize(color, icon, useColors);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private _formatDate(date: Date, opts: FormatOpts): string {
|
|
161
|
+
if (!opts.date) return "";
|
|
162
|
+
const base = date.toLocaleTimeString();
|
|
163
|
+
return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private _formatBox(logObj: LogObject, message: string): string {
|
|
167
|
+
const tag = logObj.tag !== "" ? `[${logObj.tag}]` : "";
|
|
168
|
+
const title = (logObj as LogObject & { title?: string }).title;
|
|
169
|
+
const lines = [tag, title, ...message.split("\n")].filter(Boolean);
|
|
170
|
+
return "\n" + lines.map((l) => ` > ${l}`).join("\n") + "\n";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ConsolaOptions, ConsolaReporter, LogObject } from "consola";
|
|
2
|
+
import consola, { LogLevels } from "consola";
|
|
3
|
+
import { env, parseBoolEnv } from "@simplysm/core-common";
|
|
4
|
+
import { PrettyReporter } from "./pretty-reporter";
|
|
5
|
+
import { createFileReporter } from "./file-reporter";
|
|
6
|
+
|
|
7
|
+
export function withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter {
|
|
8
|
+
return {
|
|
9
|
+
log(logObj: LogObject, ctx: { options: ConsolaOptions }) {
|
|
10
|
+
if (logObj.level > maxLevel) return;
|
|
11
|
+
reporter.log(logObj, ctx);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SetupConsolaOptions {
|
|
17
|
+
cli?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function setupConsola(opts?: SetupConsolaOptions): void {
|
|
21
|
+
if (!opts?.cli && !parseBoolEnv(env("DEV"))) {
|
|
22
|
+
// prod: debug 포함 FileReporter
|
|
23
|
+
consola.level = LogLevels.debug;
|
|
24
|
+
consola.options.reporters = [createFileReporter()];
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (parseBoolEnv(env("SD_DEBUG"))) {
|
|
29
|
+
// dev + SD_DEBUG: debug 포함 PrettyReporter
|
|
30
|
+
consola.level = LogLevels.debug;
|
|
31
|
+
consola.options.reporters = [new PrettyReporter()];
|
|
32
|
+
} else {
|
|
33
|
+
// dev: debug 포함 FileReporter + debug 비포함 PrettyReporter
|
|
34
|
+
consola.level = LogLevels.debug;
|
|
35
|
+
consola.options.reporters = [
|
|
36
|
+
createFileReporter(),
|
|
37
|
+
withMaxLevel(new PrettyReporter(), LogLevels.info),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,9 @@ export * as pathx from "./utils/path";
|
|
|
5
5
|
|
|
6
6
|
// 기능
|
|
7
7
|
export * from "./features/fs-watcher";
|
|
8
|
+
export * from "./features/consola/pretty-reporter";
|
|
9
|
+
export * from "./features/consola/file-reporter";
|
|
10
|
+
export * from "./features/consola/setup-consola";
|
|
8
11
|
|
|
9
12
|
// 워커
|
|
10
13
|
export * from "./worker/types";
|
package/src/utils/cp.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChildProcess, SpawnOptions, SpawnSyncOptions } from "child_process";
|
|
2
2
|
import { execSync as cpExecSync, spawn as cpSpawn, spawnSync as cpSpawnSync } from "child_process";
|
|
3
|
-
import { bytes } from "@simplysm/core-common";
|
|
3
|
+
import { bytes, env } from "@simplysm/core-common";
|
|
4
4
|
|
|
5
5
|
const CODE_PAGE_MAP: Record<number, string> = {
|
|
6
6
|
65001: "utf-8",
|
|
@@ -36,7 +36,7 @@ export function getSystemEncoding(): string {
|
|
|
36
36
|
return _cachedEncoding;
|
|
37
37
|
}
|
|
38
38
|
} else {
|
|
39
|
-
const lang =
|
|
39
|
+
const lang = env("LANG") ?? env("LC_ALL") ?? "";
|
|
40
40
|
const dotIndex = lang.indexOf(".");
|
|
41
41
|
if (dotIndex >= 0) {
|
|
42
42
|
let encoding = lang.slice(dotIndex + 1).split("@")[0].toLowerCase();
|