@c9up/spectrum 0.1.3 → 0.1.5
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/dist/RustLogBridge.d.ts.map +1 -1
- package/dist/RustLogBridge.js +25 -12
- package/dist/RustLogBridge.js.map +1 -1
- package/dist/SpectrumProvider.d.ts +3 -0
- package/dist/SpectrumProvider.d.ts.map +1 -1
- package/dist/SpectrumProvider.js +29 -10
- package/dist/SpectrumProvider.js.map +1 -1
- package/dist/channels/FileChannel.d.ts.map +1 -1
- package/dist/channels/FileChannel.js +11 -0
- package/dist/channels/FileChannel.js.map +1 -1
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +7 -3
- package/dist/configure.js.map +1 -1
- package/dist/testing/FakeLogger.js +17 -1
- package/dist/testing/FakeLogger.js.map +1 -1
- package/package.json +1 -1
- package/src/RustLogBridge.ts +26 -13
- package/src/SpectrumProvider.ts +36 -12
- package/src/channels/FileChannel.ts +11 -0
- package/src/configure.ts +7 -3
- package/src/testing/FakeLogger.ts +15 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RustLogBridge.d.ts","sourceRoot":"","sources":["../src/RustLogBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAY,MAAM,YAAY,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAuB1D;
|
|
1
|
+
{"version":3,"file":"RustLogBridge.d.ts","sourceRoot":"","sources":["../src/RustLogBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAY,MAAM,YAAY,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAuB1D;AAiBD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG;IAC5D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CACjB,CA6FA"}
|
package/dist/RustLogBridge.js
CHANGED
|
@@ -39,8 +39,11 @@ export function parseRustLog(line) {
|
|
|
39
39
|
/**
|
|
40
40
|
* Create a bridge that captures stderr and routes Rust logs to Spectrum channels.
|
|
41
41
|
*
|
|
42
|
-
* Usage
|
|
43
|
-
*
|
|
42
|
+
* Usage — pass the same channels array you built the Logger with (Logger.config
|
|
43
|
+
* is private, so reuse the array rather than reaching into the instance):
|
|
44
|
+
* const channels = [new ConsoleChannel('pretty')]
|
|
45
|
+
* const logger = new Logger({ level: 'info', channels })
|
|
46
|
+
* const bridge = createRustLogBridge(channels)
|
|
44
47
|
* bridge.start()
|
|
45
48
|
* // ... Rust crates emit to stderr
|
|
46
49
|
* bridge.stop()
|
|
@@ -72,13 +75,23 @@ export function createRustLogBridge(channels) {
|
|
|
72
75
|
}
|
|
73
76
|
const str = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
74
77
|
let hadRustLog = false;
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
// Rebuild passthrough as one byte-faithful string instead of
|
|
79
|
+
// re-emitting each line with an appended "\n". split("\n") drops
|
|
80
|
+
// the separator, so every segment except a trailing fragment (the
|
|
81
|
+
// chunk didn't end in "\n") was newline-terminated originally —
|
|
82
|
+
// reattach accordingly. This preserves blank lines and a partial
|
|
83
|
+
// no-newline trailing write verbatim, and keeps passthrough lines
|
|
84
|
+
// in their original order.
|
|
85
|
+
let passthrough = "";
|
|
86
|
+
const segments = str.split("\n");
|
|
87
|
+
for (let i = 0; i < segments.length; i++) {
|
|
88
|
+
const seg = segments[i] ?? "";
|
|
89
|
+
const isTrailingFragment = i === segments.length - 1;
|
|
90
|
+
const original = isTrailingFragment ? seg : `${seg}\n`;
|
|
91
|
+
const trimmed = seg.trim();
|
|
92
|
+
// Only a complete, non-empty line is a Rust-log candidate. A
|
|
93
|
+
// trailing fragment is a partial write — never parse or drop it.
|
|
94
|
+
const entry = trimmed && !isTrailingFragment ? parseRustLog(trimmed) : null;
|
|
82
95
|
if (entry) {
|
|
83
96
|
hadRustLog = true;
|
|
84
97
|
for (const channel of channels) {
|
|
@@ -95,15 +108,15 @@ export function createRustLogBridge(channels) {
|
|
|
95
108
|
}
|
|
96
109
|
}
|
|
97
110
|
else {
|
|
98
|
-
|
|
111
|
+
passthrough += original;
|
|
99
112
|
}
|
|
100
113
|
}
|
|
101
114
|
// Preserve original chunk when we didn't intercept any Rust logs.
|
|
102
115
|
if (!hadRustLog) {
|
|
103
116
|
return origWrite(chunk, ...args);
|
|
104
117
|
}
|
|
105
|
-
|
|
106
|
-
origWrite(
|
|
118
|
+
if (passthrough) {
|
|
119
|
+
origWrite(passthrough);
|
|
107
120
|
}
|
|
108
121
|
return true;
|
|
109
122
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RustLogBridge.js","sourceRoot":"","sources":["../src/RustLogBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACxC,kCAAkC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,QAAQ,GAA6B;QAC1C,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,OAAO;KACd,CAAC;IAEF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,OAAO;QACN,KAAK;QACL,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QACjB,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACnC,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"RustLogBridge.js","sourceRoot":"","sources":["../src/RustLogBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,10 +10,13 @@ export interface SpectrumAppContext {
|
|
|
10
10
|
config: SpectrumConfigStore;
|
|
11
11
|
}
|
|
12
12
|
export default class SpectrumProvider {
|
|
13
|
+
#private;
|
|
13
14
|
protected app: SpectrumAppContext;
|
|
14
15
|
constructor(app: SpectrumAppContext);
|
|
15
16
|
register(): void;
|
|
16
17
|
boot(): Promise<void>;
|
|
18
|
+
/** Release channel resources (e.g. FileChannel WriteStreams) on shutdown. */
|
|
19
|
+
shutdown(): Promise<void>;
|
|
17
20
|
}
|
|
18
21
|
export {};
|
|
19
22
|
//# sourceMappingURL=SpectrumProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpectrumProvider.d.ts","sourceRoot":"","sources":["../src/SpectrumProvider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SpectrumProvider.d.ts","sourceRoot":"","sources":["../src/SpectrumProvider.ts"],"names":[],"mappings":"AAkBA,UAAU,iBAAiB;IAC1B,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC;CACxC;AAED,UAAU,mBAAmB;IAC5B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,CAAC,OAAO,OAAO,gBAAgB;;IAGxB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IA4BF,IAAI;IAIV,6EAA6E;IACvE,QAAQ;CAKd"}
|
package/dist/SpectrumProvider.js
CHANGED
|
@@ -8,22 +8,34 @@ function resolveLogLevel(raw) {
|
|
|
8
8
|
return raw;
|
|
9
9
|
return "info";
|
|
10
10
|
}
|
|
11
|
+
/** A channel that owns a resource (e.g. a FileChannel WriteStream) to release on shutdown. */
|
|
12
|
+
function hasClose(ch) {
|
|
13
|
+
return "close" in ch && typeof ch.close === "function";
|
|
14
|
+
}
|
|
11
15
|
export default class SpectrumProvider {
|
|
12
16
|
app;
|
|
17
|
+
#channels = [];
|
|
13
18
|
constructor(app) {
|
|
14
19
|
this.app = app;
|
|
15
20
|
}
|
|
16
21
|
register() {
|
|
17
|
-
this.app.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const config = this.app.config.get("logger");
|
|
23
|
+
const level = config?.level && VALID_LEVELS.has(config.level)
|
|
24
|
+
? config.level
|
|
25
|
+
: resolveLogLevel(process.env.LOG_LEVEL);
|
|
26
|
+
// Honour the configured channels (the whole point of LogConfig.channels);
|
|
27
|
+
// fall back to a pretty console channel only when none are supplied.
|
|
28
|
+
// Previously this was hardcoded and config.channels was silently ignored.
|
|
29
|
+
this.#channels =
|
|
30
|
+
config?.channels && config.channels.length > 0
|
|
31
|
+
? config.channels
|
|
32
|
+
: [new ConsoleChannel("pretty")];
|
|
33
|
+
const channels = this.#channels;
|
|
34
|
+
// Forward per-module level overrides (config.logger.modules) — Logger.log
|
|
35
|
+
// gates each module's level off config.modules?.[module]; dropping it here
|
|
36
|
+
// silently disables every per-module override in production.
|
|
37
|
+
const modules = config?.modules;
|
|
38
|
+
this.app.container.singleton(Logger, () => new Logger({ level, channels, modules }));
|
|
27
39
|
this.app.container.singleton("logger", () => {
|
|
28
40
|
return this.app.container.resolve(Logger);
|
|
29
41
|
});
|
|
@@ -31,5 +43,12 @@ export default class SpectrumProvider {
|
|
|
31
43
|
async boot() {
|
|
32
44
|
setLogger(this.app.container.resolve(Logger));
|
|
33
45
|
}
|
|
46
|
+
/** Release channel resources (e.g. FileChannel WriteStreams) on shutdown. */
|
|
47
|
+
async shutdown() {
|
|
48
|
+
for (const channel of this.#channels) {
|
|
49
|
+
if (hasClose(channel))
|
|
50
|
+
channel.close();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
34
53
|
}
|
|
35
54
|
//# sourceMappingURL=SpectrumProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpectrumProvider.js","sourceRoot":"","sources":["../src/SpectrumProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;AAEnE,SAAS,eAAe,CAAC,GAAuB;IAC/C,IAAI,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,GAAe,CAAC;IACzD,OAAO,MAAM,CAAC;AACf,CAAC;AAgBD,MAAM,CAAC,OAAO,OAAO,gBAAgB;
|
|
1
|
+
{"version":3,"file":"SpectrumProvider.js","sourceRoot":"","sources":["../src/SpectrumProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;AAEnE,SAAS,eAAe,CAAC,GAAuB;IAC/C,IAAI,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,GAAe,CAAC;IACzD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,8FAA8F;AAC9F,SAAS,QAAQ,CAAC,EAAc;IAC/B,OAAO,OAAO,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,UAAU,CAAC;AACxD,CAAC;AAgBD,MAAM,CAAC,OAAO,OAAO,gBAAgB;IAGd;IAFtB,SAAS,GAAiB,EAAE,CAAC;IAE7B,YAAsB,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAEjD,QAAQ;QACP,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAqB,QAAQ,CAAC,CAAC;QACjE,MAAM,KAAK,GACV,MAAM,EAAE,KAAK,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;YAC9C,CAAC,CAAC,MAAM,CAAC,KAAK;YACd,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,0EAA0E;QAC1E,qEAAqE;QACrE,0EAA0E;QAC1E,IAAI,CAAC,SAAS;YACb,MAAM,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAC7C,CAAC,CAAC,MAAM,CAAC,QAAQ;gBACjB,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAEhC,0EAA0E;QAC1E,2EAA2E;QAC3E,6DAA6D;QAC7D,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAC3B,MAAM,EACN,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAC9C,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAS,MAAM,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACT,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAS,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,QAAQ;QACb,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,CAAC;IACF,CAAC;CACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileChannel.d.ts","sourceRoot":"","sources":["../../src/channels/FileChannel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAY,YAAW,UAAU;;IAC7C,IAAI,SAAU;gBAUF,MAAM,EAAE,iBAAiB;IAMrC,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"FileChannel.d.ts","sourceRoot":"","sources":["../../src/channels/FileChannel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAY,YAAW,UAAU;;IAC7C,IAAI,SAAU;gBAUF,MAAM,EAAE,iBAAiB;IAMrC,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAwI5B,KAAK,IAAI,IAAI;CAMb"}
|
|
@@ -40,6 +40,17 @@ export class FileChannel {
|
|
|
40
40
|
process.stderr.write(`[Spectrum] FileChannel: failed to open '${this.#filePath}'\n`);
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
+
// A prior failed rotation strands buffered lines while #stream is
|
|
44
|
+
// null (the rotation's #flushPending early-returns on no stream).
|
|
45
|
+
// Now that we've reopened, drain them — in order, before the new
|
|
46
|
+
// line — instead of losing them until the next rotation happens to
|
|
47
|
+
// fire. #flushPending may itself trigger a rotation if a buffered
|
|
48
|
+
// line overflows, so re-check before writing the current line.
|
|
49
|
+
this.#flushPending();
|
|
50
|
+
if (this.#rotating) {
|
|
51
|
+
this.#pending.push(line);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
43
54
|
}
|
|
44
55
|
if (this.#currentSize + bytes > this.#maxSize) {
|
|
45
56
|
this.#pending.push(line);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileChannel.js","sourceRoot":"","sources":["../../src/channels/FileChannel.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileChannel.js","sourceRoot":"","sources":["../../src/channels/FileChannel.ts"],"names":[],"mappings":"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"}
|
package/dist/configure.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBjE"}
|
package/dist/configure.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export async function configure(codemods) {
|
|
2
2
|
await codemods.addProvider("@c9up/spectrum/provider");
|
|
3
|
-
await codemods.writeFile("config/logger.ts", `import { defineConfig } from '@c9up/spectrum'
|
|
3
|
+
await codemods.writeFile("config/logger.ts", `import { ConsoleChannel, defineConfig, type LogLevel } from '@c9up/spectrum'
|
|
4
4
|
|
|
5
5
|
export default defineConfig({
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// LOG_LEVEL is an untyped env string — narrow it to the LogLevel union so the
|
|
7
|
+
// generated config typechecks against defineConfig's strict \`level\`.
|
|
8
|
+
level: (process.env.LOG_LEVEL as LogLevel | undefined) ?? 'info',
|
|
9
|
+
// Channels are LogChannel instances. Add a FileChannel for disk logs:
|
|
10
|
+
// new FileChannel({ path: 'storage/logs/app.log' })
|
|
11
|
+
channels: [new ConsoleChannel('pretty')],
|
|
8
12
|
})
|
|
9
13
|
`);
|
|
10
14
|
}
|
package/dist/configure.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,MAAM,QAAQ,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;IACtD,MAAM,QAAQ,CAAC,SAAS,CACvB,kBAAkB,EAClB
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,MAAM,QAAQ,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;IACtD,MAAM,QAAQ,CAAC,SAAS,CACvB,kBAAkB,EAClB;;;;;;;;;;CAUD,CACC,CAAC;AACH,CAAC"}
|
|
@@ -106,6 +106,22 @@ function safeStringify(value) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
function deepClone(value) {
|
|
109
|
-
|
|
109
|
+
try {
|
|
110
|
+
return structuredClone(value);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// `data` can carry functions / class instances that structuredClone
|
|
114
|
+
// rejects (DataCloneError). For a test capture a perfect clone isn't
|
|
115
|
+
// needed — round-trip through safeStringify (functions → "<function>",
|
|
116
|
+
// circular → "<circular>") so the entry is still CAPTURED and assertable
|
|
117
|
+
// instead of thrown away (the throw propagated into Logger.log's swallow,
|
|
118
|
+
// dropping the entry and making assertLogged fail with "no entry").
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(safeStringify(value));
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
110
126
|
}
|
|
111
127
|
//# sourceMappingURL=FakeLogger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeLogger.js","sourceRoot":"","sources":["../../src/testing/FakeLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,MAAM,OAAO,UAAU;IACb,IAAI,GAAG,MAAM,CAAC;IACvB,SAAS,GAAe,EAAE,CAAC;IAE3B,KAAK,CAAC,KAAe;QACpB,+DAA+D;QAC/D,0DAA0D;QAC1D,2DAA2D;QAC3D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACnB,GAAG,KAAK;YACR,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SACpD,CAAC,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,SAAS;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,GAAG,CAAC;YACJ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;IACrB,CAAC;IAED,YAAY,CAAC,KAAe,EAAE,SAAkC;QAC/D,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QACvC,MAAM,IAAI,KAAK,CACd,wBAAwB,KAAK,IAAI,iBAAiB,CAAC,SAAS,CAAC,0CAA0C,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CACzI,CAAC;IACH,CAAC;IAED,eAAe,CAAC,KAAe,EAAE,SAAkC;QAClE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QACxC,MAAM,IAAI,KAAK,CACd,2BAA2B,KAAK,IAAI,iBAAiB,CAAC,SAAS,CAAC,oDAAoD,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CACtJ,CAAC;IACH,CAAC;CACD;AAED,SAAS,WAAW,CACnB,KAAe,EACf,SAA6C;IAE7C,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;IACjC,CAAC;IACD,mEAAmE;IACnE,iEAAiE;IACjE,6DAA6D;IAC7D,IAAI,SAAS,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACd,uGAAuG,CACvG,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,EAAE,EAAE;QACZ,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QACpC,IACC,SAAS,CAAC,UAAU,KAAK,SAAS;YAClC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,EACxC,CAAC;YACF,OAAO,KAAK,CAAC;QACd,CAAC;QACD,IAAI,SAAS,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CACzB,SAA6C;IAE7C,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,OAAO,SAAS,KAAK,UAAU;QAAE,OAAO,wBAAwB,CAAC;IACrE,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC;QACtC,OAAO,kCAAkC,CAAC;IAC3C,OAAO,KAAK,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAoB;IAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC;IACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CACzB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,OAAO,GAAG,CAC3E,CAAC;IACF,OAAO,aAAa,QAAQ,CAAC,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;;wDAGwD;AACxD,SAAS,aAAa,CAAC,KAAc;IACpC,MAAM,IAAI,GAAG,IAAI,OAAO,EAAU,CAAC;IACnC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAU,EAAE,EAAE;YACjD,IAAI,OAAO,CAAC,KAAK,UAAU;gBAAE,OAAO,YAAY,CAAC;YACjD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACzC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAE,OAAO,YAAY,CAAC;gBACrC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACb,CAAC;YACD,OAAO,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,mBAAmB,CAAC;IAC5B,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAI,KAAQ;IAC7B,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"FakeLogger.js","sourceRoot":"","sources":["../../src/testing/FakeLogger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/RustLogBridge.ts
CHANGED
|
@@ -44,8 +44,11 @@ export function parseRustLog(line: string): LogEntry | null {
|
|
|
44
44
|
/**
|
|
45
45
|
* Create a bridge that captures stderr and routes Rust logs to Spectrum channels.
|
|
46
46
|
*
|
|
47
|
-
* Usage
|
|
48
|
-
*
|
|
47
|
+
* Usage — pass the same channels array you built the Logger with (Logger.config
|
|
48
|
+
* is private, so reuse the array rather than reaching into the instance):
|
|
49
|
+
* const channels = [new ConsoleChannel('pretty')]
|
|
50
|
+
* const logger = new Logger({ level: 'info', channels })
|
|
51
|
+
* const bridge = createRustLogBridge(channels)
|
|
49
52
|
* bridge.start()
|
|
50
53
|
* // ... Rust crates emit to stderr
|
|
51
54
|
* bridge.stop()
|
|
@@ -89,14 +92,24 @@ export function createRustLogBridge(channels: LogChannel[]): {
|
|
|
89
92
|
const str =
|
|
90
93
|
typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
91
94
|
let hadRustLog = false;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
// Rebuild passthrough as one byte-faithful string instead of
|
|
96
|
+
// re-emitting each line with an appended "\n". split("\n") drops
|
|
97
|
+
// the separator, so every segment except a trailing fragment (the
|
|
98
|
+
// chunk didn't end in "\n") was newline-terminated originally —
|
|
99
|
+
// reattach accordingly. This preserves blank lines and a partial
|
|
100
|
+
// no-newline trailing write verbatim, and keeps passthrough lines
|
|
101
|
+
// in their original order.
|
|
102
|
+
let passthrough = "";
|
|
103
|
+
const segments = str.split("\n");
|
|
104
|
+
for (let i = 0; i < segments.length; i++) {
|
|
105
|
+
const seg = segments[i] ?? "";
|
|
106
|
+
const isTrailingFragment = i === segments.length - 1;
|
|
107
|
+
const original = isTrailingFragment ? seg : `${seg}\n`;
|
|
108
|
+
const trimmed = seg.trim();
|
|
109
|
+
// Only a complete, non-empty line is a Rust-log candidate. A
|
|
110
|
+
// trailing fragment is a partial write — never parse or drop it.
|
|
111
|
+
const entry =
|
|
112
|
+
trimmed && !isTrailingFragment ? parseRustLog(trimmed) : null;
|
|
100
113
|
if (entry) {
|
|
101
114
|
hadRustLog = true;
|
|
102
115
|
for (const channel of channels) {
|
|
@@ -110,7 +123,7 @@ export function createRustLogBridge(channels: LogChannel[]): {
|
|
|
110
123
|
}
|
|
111
124
|
}
|
|
112
125
|
} else {
|
|
113
|
-
|
|
126
|
+
passthrough += original;
|
|
114
127
|
}
|
|
115
128
|
}
|
|
116
129
|
|
|
@@ -119,8 +132,8 @@ export function createRustLogBridge(channels: LogChannel[]): {
|
|
|
119
132
|
return origWrite(chunk as never, ...(args as []));
|
|
120
133
|
}
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
origWrite(
|
|
135
|
+
if (passthrough) {
|
|
136
|
+
origWrite(passthrough);
|
|
124
137
|
}
|
|
125
138
|
|
|
126
139
|
return true;
|
package/src/SpectrumProvider.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConsoleChannel } from "./channels/ConsoleChannel.js";
|
|
2
2
|
import { Logger } from "./Logger.js";
|
|
3
3
|
import { setLogger } from "./services/main.js";
|
|
4
|
-
import type { LogLevel } from "./types.js";
|
|
4
|
+
import type { LogChannel, LogConfig, LogLevel } from "./types.js";
|
|
5
5
|
import { LOG_LEVEL_ORDER } from "./types.js";
|
|
6
6
|
|
|
7
7
|
const VALID_LEVELS = new Set<string>(Object.keys(LOG_LEVEL_ORDER));
|
|
@@ -11,6 +11,11 @@ function resolveLogLevel(raw: string | undefined): LogLevel {
|
|
|
11
11
|
return "info";
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/** A channel that owns a resource (e.g. a FileChannel WriteStream) to release on shutdown. */
|
|
15
|
+
function hasClose(ch: LogChannel): ch is LogChannel & { close(): void } {
|
|
16
|
+
return "close" in ch && typeof ch.close === "function";
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
interface SpectrumContainer {
|
|
15
20
|
singleton(token: unknown, factory: () => unknown): void;
|
|
16
21
|
resolve<T = unknown>(token: unknown): T;
|
|
@@ -26,21 +31,33 @@ export interface SpectrumAppContext {
|
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
export default class SpectrumProvider {
|
|
34
|
+
#channels: LogChannel[] = [];
|
|
35
|
+
|
|
29
36
|
constructor(protected app: SpectrumAppContext) {}
|
|
30
37
|
|
|
31
38
|
register() {
|
|
32
|
-
this.app.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const config = this.app.config.get<Partial<LogConfig>>("logger");
|
|
40
|
+
const level =
|
|
41
|
+
config?.level && VALID_LEVELS.has(config.level)
|
|
42
|
+
? config.level
|
|
43
|
+
: resolveLogLevel(process.env.LOG_LEVEL);
|
|
44
|
+
// Honour the configured channels (the whole point of LogConfig.channels);
|
|
45
|
+
// fall back to a pretty console channel only when none are supplied.
|
|
46
|
+
// Previously this was hardcoded and config.channels was silently ignored.
|
|
47
|
+
this.#channels =
|
|
48
|
+
config?.channels && config.channels.length > 0
|
|
49
|
+
? config.channels
|
|
50
|
+
: [new ConsoleChannel("pretty")];
|
|
51
|
+
const channels = this.#channels;
|
|
43
52
|
|
|
53
|
+
// Forward per-module level overrides (config.logger.modules) — Logger.log
|
|
54
|
+
// gates each module's level off config.modules?.[module]; dropping it here
|
|
55
|
+
// silently disables every per-module override in production.
|
|
56
|
+
const modules = config?.modules;
|
|
57
|
+
this.app.container.singleton(
|
|
58
|
+
Logger,
|
|
59
|
+
() => new Logger({ level, channels, modules }),
|
|
60
|
+
);
|
|
44
61
|
this.app.container.singleton("logger", () => {
|
|
45
62
|
return this.app.container.resolve<Logger>(Logger);
|
|
46
63
|
});
|
|
@@ -49,4 +66,11 @@ export default class SpectrumProvider {
|
|
|
49
66
|
async boot() {
|
|
50
67
|
setLogger(this.app.container.resolve<Logger>(Logger));
|
|
51
68
|
}
|
|
69
|
+
|
|
70
|
+
/** Release channel resources (e.g. FileChannel WriteStreams) on shutdown. */
|
|
71
|
+
async shutdown() {
|
|
72
|
+
for (const channel of this.#channels) {
|
|
73
|
+
if (hasClose(channel)) channel.close();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
52
76
|
}
|
|
@@ -54,6 +54,17 @@ export class FileChannel implements LogChannel {
|
|
|
54
54
|
);
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
+
// A prior failed rotation strands buffered lines while #stream is
|
|
58
|
+
// null (the rotation's #flushPending early-returns on no stream).
|
|
59
|
+
// Now that we've reopened, drain them — in order, before the new
|
|
60
|
+
// line — instead of losing them until the next rotation happens to
|
|
61
|
+
// fire. #flushPending may itself trigger a rotation if a buffered
|
|
62
|
+
// line overflows, so re-check before writing the current line.
|
|
63
|
+
this.#flushPending();
|
|
64
|
+
if (this.#rotating) {
|
|
65
|
+
this.#pending.push(line);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
if (this.#currentSize + bytes > this.#maxSize) {
|
package/src/configure.ts
CHANGED
|
@@ -12,11 +12,15 @@ export async function configure(codemods: Codemods): Promise<void> {
|
|
|
12
12
|
await codemods.addProvider("@c9up/spectrum/provider");
|
|
13
13
|
await codemods.writeFile(
|
|
14
14
|
"config/logger.ts",
|
|
15
|
-
`import { defineConfig } from '@c9up/spectrum'
|
|
15
|
+
`import { ConsoleChannel, defineConfig, type LogLevel } from '@c9up/spectrum'
|
|
16
16
|
|
|
17
17
|
export default defineConfig({
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// LOG_LEVEL is an untyped env string — narrow it to the LogLevel union so the
|
|
19
|
+
// generated config typechecks against defineConfig's strict \`level\`.
|
|
20
|
+
level: (process.env.LOG_LEVEL as LogLevel | undefined) ?? 'info',
|
|
21
|
+
// Channels are LogChannel instances. Add a FileChannel for disk logs:
|
|
22
|
+
// new FileChannel({ path: 'storage/logs/app.log' })
|
|
23
|
+
channels: [new ConsoleChannel('pretty')],
|
|
20
24
|
})
|
|
21
25
|
`,
|
|
22
26
|
);
|
|
@@ -136,5 +136,19 @@ function safeStringify(value: unknown): string {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
function deepClone<T>(value: T): T {
|
|
139
|
-
|
|
139
|
+
try {
|
|
140
|
+
return structuredClone(value);
|
|
141
|
+
} catch {
|
|
142
|
+
// `data` can carry functions / class instances that structuredClone
|
|
143
|
+
// rejects (DataCloneError). For a test capture a perfect clone isn't
|
|
144
|
+
// needed — round-trip through safeStringify (functions → "<function>",
|
|
145
|
+
// circular → "<circular>") so the entry is still CAPTURED and assertable
|
|
146
|
+
// instead of thrown away (the throw propagated into Logger.log's swallow,
|
|
147
|
+
// dropping the entry and making assertLogged fail with "no entry").
|
|
148
|
+
try {
|
|
149
|
+
return JSON.parse(safeStringify(value));
|
|
150
|
+
} catch {
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
140
154
|
}
|