@c9up/spectrum 0.1.3
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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/Logger.d.ts +34 -0
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +72 -0
- package/dist/Logger.js.map +1 -0
- package/dist/RustLogBridge.d.ts +22 -0
- package/dist/RustLogBridge.d.ts.map +1 -0
- package/dist/RustLogBridge.js +124 -0
- package/dist/RustLogBridge.js.map +1 -0
- package/dist/SpectrumProvider.d.ts +19 -0
- package/dist/SpectrumProvider.d.ts.map +1 -0
- package/dist/SpectrumProvider.js +35 -0
- package/dist/SpectrumProvider.js.map +1 -0
- package/dist/channels/ConsoleChannel.d.ts +13 -0
- package/dist/channels/ConsoleChannel.d.ts.map +1 -0
- package/dist/channels/ConsoleChannel.js +89 -0
- package/dist/channels/ConsoleChannel.js.map +1 -0
- package/dist/channels/FileChannel.d.ts +23 -0
- package/dist/channels/FileChannel.d.ts.map +1 -0
- package/dist/channels/FileChannel.js +150 -0
- package/dist/channels/FileChannel.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -0
- package/dist/configure.d.ts +10 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +11 -0
- package/dist/configure.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/services/main.d.ts +18 -0
- package/dist/services/main.d.ts.map +1 -0
- package/dist/services/main.js +31 -0
- package/dist/services/main.js.map +1 -0
- package/dist/testing/FakeLogger.d.ts +28 -0
- package/dist/testing/FakeLogger.d.ts.map +1 -0
- package/dist/testing/FakeLogger.js +111 -0
- package/dist/testing/FakeLogger.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/src/Logger.ts +99 -0
- package/src/RustLogBridge.ts +142 -0
- package/src/SpectrumProvider.ts +52 -0
- package/src/channels/ConsoleChannel.ts +100 -0
- package/src/channels/FileChannel.ts +170 -0
- package/src/config.ts +7 -0
- package/src/configure.ts +23 -0
- package/src/index.ts +13 -0
- package/src/services/main.ts +39 -0
- package/src/testing/FakeLogger.ts +140 -0
- package/src/types.ts +36 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File logging channel — writes log entries to a file as JSON lines.
|
|
3
|
+
*
|
|
4
|
+
* Uses a non-blocking WriteStream with an internal buffer. Rotation is
|
|
5
|
+
* scheduled via queueMicrotask to avoid blocking the event loop on the
|
|
6
|
+
* HTTP hot path.
|
|
7
|
+
*
|
|
8
|
+
* @implements MISS-14, MISS-15
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from "node:fs";
|
|
11
|
+
import * as fsp from "node:fs/promises";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
export class FileChannel {
|
|
14
|
+
name = "file";
|
|
15
|
+
#filePath;
|
|
16
|
+
#maxSize;
|
|
17
|
+
#maxFiles;
|
|
18
|
+
#stream = null;
|
|
19
|
+
#currentSize = 0;
|
|
20
|
+
#dirReady = false;
|
|
21
|
+
#rotating = false;
|
|
22
|
+
#pending = [];
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.#filePath = config.path;
|
|
25
|
+
this.#maxSize = config.maxSizeBytes ?? 10 * 1024 * 1024;
|
|
26
|
+
this.#maxFiles = config.maxFiles ?? 5;
|
|
27
|
+
}
|
|
28
|
+
write(entry) {
|
|
29
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
30
|
+
const bytes = Buffer.byteLength(line, "utf8");
|
|
31
|
+
if (this.#rotating) {
|
|
32
|
+
this.#pending.push(line);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!this.#stream) {
|
|
36
|
+
try {
|
|
37
|
+
this.#openStream();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
process.stderr.write(`[Spectrum] FileChannel: failed to open '${this.#filePath}'\n`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (this.#currentSize + bytes > this.#maxSize) {
|
|
45
|
+
this.#pending.push(line);
|
|
46
|
+
this.#scheduleRotation();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (this.#stream) {
|
|
50
|
+
this.#stream.write(line);
|
|
51
|
+
this.#currentSize += bytes;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
#openStream() {
|
|
55
|
+
// mkdirSync + statSync only on first open (boot) — never on the hot path.
|
|
56
|
+
// The fast write path goes straight through this.#stream.write() (non-blocking).
|
|
57
|
+
if (!this.#dirReady) {
|
|
58
|
+
const dir = path.dirname(this.#filePath);
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
this.#dirReady = true;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
this.#currentSize = fs.statSync(this.#filePath).size;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
this.#currentSize = 0;
|
|
67
|
+
}
|
|
68
|
+
this.#stream = fs.createWriteStream(this.#filePath, { flags: "a" });
|
|
69
|
+
this.#stream.on("error", (err) => {
|
|
70
|
+
process.stderr.write(`[Spectrum] FileChannel stream error: ${err.message}\n`);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
#scheduleRotation() {
|
|
74
|
+
if (this.#rotating)
|
|
75
|
+
return;
|
|
76
|
+
this.#rotating = true;
|
|
77
|
+
queueMicrotask(() => {
|
|
78
|
+
this.#rotate().finally(() => {
|
|
79
|
+
this.#rotating = false;
|
|
80
|
+
this.#flushPending();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async #rotate() {
|
|
85
|
+
try {
|
|
86
|
+
await this.#closeStream();
|
|
87
|
+
const oldest = `${this.#filePath}.${this.#maxFiles - 1}`;
|
|
88
|
+
await fsp.rm(oldest, { force: true });
|
|
89
|
+
for (let i = this.#maxFiles - 2; i >= 1; i--) {
|
|
90
|
+
const from = i === 1 ? this.#filePath : `${this.#filePath}.${i}`;
|
|
91
|
+
const to = `${this.#filePath}.${i + 1}`;
|
|
92
|
+
try {
|
|
93
|
+
await fsp.rename(from, to);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// File doesn't exist — skip
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await fsp.rename(this.#filePath, `${this.#filePath}.1`);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Nothing to rotate
|
|
104
|
+
}
|
|
105
|
+
this.#openStream();
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
try {
|
|
109
|
+
this.#openStream();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
process.stderr.write(`[Spectrum] FileChannel: rotation failed, logging suspended for '${this.#filePath}'\n`);
|
|
113
|
+
this.#stream = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
#flushPending() {
|
|
118
|
+
if (!this.#stream)
|
|
119
|
+
return;
|
|
120
|
+
while (this.#pending.length > 0) {
|
|
121
|
+
const line = this.#pending.shift();
|
|
122
|
+
if (!line)
|
|
123
|
+
continue;
|
|
124
|
+
const bytes = Buffer.byteLength(line, "utf8");
|
|
125
|
+
if (this.#currentSize + bytes > this.#maxSize) {
|
|
126
|
+
this.#pending.unshift(line);
|
|
127
|
+
this.#scheduleRotation();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this.#stream.write(line);
|
|
131
|
+
this.#currentSize += bytes;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async #closeStream() {
|
|
135
|
+
if (!this.#stream)
|
|
136
|
+
return;
|
|
137
|
+
const stream = this.#stream;
|
|
138
|
+
this.#stream = null;
|
|
139
|
+
return new Promise((resolve) => {
|
|
140
|
+
stream.end(() => resolve());
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
close() {
|
|
144
|
+
if (this.#stream) {
|
|
145
|
+
this.#stream.end();
|
|
146
|
+
this.#stream = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=FileChannel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileChannel.js","sourceRoot":"","sources":["../../src/channels/FileChannel.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAEzD;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC7C,OAAO,MAAM,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface Codemods {
|
|
2
|
+
addProvider(importPath: string): Promise<void>;
|
|
3
|
+
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
4
|
+
writeFile(filePath: string, content: string, options?: {
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function configure(codemods: Codemods): Promise<void>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=configure.d.ts.map
|
|
@@ -0,0 +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,CAYjE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function configure(codemods) {
|
|
2
|
+
await codemods.addProvider("@c9up/spectrum/provider");
|
|
3
|
+
await codemods.writeFile("config/logger.ts", `import { defineConfig } from '@c9up/spectrum'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
level: process.env.LOG_LEVEL ?? 'info',
|
|
7
|
+
channels: ['console'],
|
|
8
|
+
})
|
|
9
|
+
`);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=configure.js.map
|
|
@@ -0,0 +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;;;;;;CAMD,CACC,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @c9up/spectrum
|
|
3
|
+
* @description Spectrum — structured logging for the Ream framework
|
|
4
|
+
* @implements FR54, FR55, FR56, FR57, FR58
|
|
5
|
+
*/
|
|
6
|
+
export { ConsoleChannel } from "./channels/ConsoleChannel.js";
|
|
7
|
+
export { FileChannel } from "./channels/FileChannel.js";
|
|
8
|
+
export { defineConfig } from "./config.js";
|
|
9
|
+
export { configure } from "./configure.js";
|
|
10
|
+
export { Logger, type LogLevel } from "./Logger.js";
|
|
11
|
+
export { createRustLogBridge, parseRustLog } from "./RustLogBridge.js";
|
|
12
|
+
export type { LogChannel, LogConfig, LogEntry } from "./types.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @c9up/spectrum
|
|
3
|
+
* @description Spectrum — structured logging for the Ream framework
|
|
4
|
+
* @implements FR54, FR55, FR56, FR57, FR58
|
|
5
|
+
*/
|
|
6
|
+
export { ConsoleChannel } from "./channels/ConsoleChannel.js";
|
|
7
|
+
export { FileChannel } from "./channels/FileChannel.js";
|
|
8
|
+
export { defineConfig } from "./config.js";
|
|
9
|
+
export { configure } from "./configure.js";
|
|
10
|
+
export { Logger } from "./Logger.js";
|
|
11
|
+
export { createRustLogBridge, parseRustLog } from "./RustLogBridge.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default `Logger` singleton — mirror of Adonis's
|
|
3
|
+
* `import logger from '@adonisjs/core/services/logger'` shape.
|
|
4
|
+
*
|
|
5
|
+
* import logger from '@c9up/spectrum/services/main'
|
|
6
|
+
*
|
|
7
|
+
* logger.info({ userId }, 'user logged in')
|
|
8
|
+
*
|
|
9
|
+
* Populated by `SpectrumProvider.boot()`.
|
|
10
|
+
*/
|
|
11
|
+
import type { Logger } from "../Logger.js";
|
|
12
|
+
/** @internal Bind the singleton (called by SpectrumProvider). */
|
|
13
|
+
export declare function setLogger(value: Logger): void;
|
|
14
|
+
/** @internal Read the singleton (or `undefined` pre-boot). */
|
|
15
|
+
export declare function getLogger(): Logger | undefined;
|
|
16
|
+
declare const logger: Logger;
|
|
17
|
+
export default logger;
|
|
18
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAI3C,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED,QAAA,MAAM,MAAM,EAAE,MAWZ,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default `Logger` singleton — mirror of Adonis's
|
|
3
|
+
* `import logger from '@adonisjs/core/services/logger'` shape.
|
|
4
|
+
*
|
|
5
|
+
* import logger from '@c9up/spectrum/services/main'
|
|
6
|
+
*
|
|
7
|
+
* logger.info({ userId }, 'user logged in')
|
|
8
|
+
*
|
|
9
|
+
* Populated by `SpectrumProvider.boot()`.
|
|
10
|
+
*/
|
|
11
|
+
let instance;
|
|
12
|
+
/** @internal Bind the singleton (called by SpectrumProvider). */
|
|
13
|
+
export function setLogger(value) {
|
|
14
|
+
instance = value;
|
|
15
|
+
}
|
|
16
|
+
/** @internal Read the singleton (or `undefined` pre-boot). */
|
|
17
|
+
export function getLogger() {
|
|
18
|
+
return instance;
|
|
19
|
+
}
|
|
20
|
+
const logger = new Proxy({}, {
|
|
21
|
+
get(_target, prop) {
|
|
22
|
+
if (!instance) {
|
|
23
|
+
throw new Error("[spectrum] Logger singleton accessed before SpectrumProvider.boot() ran. " +
|
|
24
|
+
"Check that `@c9up/spectrum/provider` is listed in your reamrc.ts providers.");
|
|
25
|
+
}
|
|
26
|
+
const value = Reflect.get(instance, prop, instance);
|
|
27
|
+
return typeof value === "function" ? value.bind(instance) : value;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
export default logger;
|
|
31
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,IAAI,QAA4B,CAAC;AAEjC,iEAAiE;AACjE,MAAM,UAAU,SAAS,CAAC,KAAa;IACtC,QAAQ,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,SAAS;IACxB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,MAAM,GAAW,IAAI,KAAK,CAAC,EAAY,EAAE;IAC9C,GAAG,CAAC,OAAO,EAAE,IAAI;QAChB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACd,2EAA2E;gBAC1E,6EAA6E,CAC9E,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;CACD,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory `LogChannel` for tests — captures every `write(entry)`
|
|
3
|
+
* and exposes Adonis/Laravel-style `assertLogged` /
|
|
4
|
+
* `assertNotLogged` helpers in the same shape as Rover's
|
|
5
|
+
* `FakeMail` and Bay's `FakeQueue`.
|
|
6
|
+
*
|
|
7
|
+
* Not re-exported from the main barrel; reach via
|
|
8
|
+
* `@c9up/spectrum/testing`.
|
|
9
|
+
*/
|
|
10
|
+
import type { LogChannel, LogEntry, LogLevel } from "../types.js";
|
|
11
|
+
export interface FakeLoggerPredicate {
|
|
12
|
+
/** Substring match against `entry.message`. */
|
|
13
|
+
containing?: string;
|
|
14
|
+
/** Custom predicate against `entry.data`. */
|
|
15
|
+
dataMatches?: (data: Record<string, unknown> | undefined) => boolean;
|
|
16
|
+
}
|
|
17
|
+
export type FakeLoggerPredicateArg = FakeLoggerPredicate | ((entry: LogEntry) => boolean);
|
|
18
|
+
export declare class FakeLogger implements LogChannel {
|
|
19
|
+
#private;
|
|
20
|
+
readonly name = "fake";
|
|
21
|
+
write(entry: LogEntry): void;
|
|
22
|
+
/** Defensive snapshot of every captured entry. */
|
|
23
|
+
getLogged(): LogEntry[];
|
|
24
|
+
reset(): void;
|
|
25
|
+
assertLogged(level: LogLevel, predicate?: FakeLoggerPredicateArg): void;
|
|
26
|
+
assertNotLogged(level: LogLevel, predicate?: FakeLoggerPredicateArg): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=FakeLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeLogger.d.ts","sourceRoot":"","sources":["../../src/testing/FakeLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,mBAAmB;IACnC,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,OAAO,CAAC;CACrE;AAED,MAAM,MAAM,sBAAsB,GAC/B,mBAAmB,GACnB,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC;AAElC,qBAAa,UAAW,YAAW,UAAU;;IAC5C,QAAQ,CAAC,IAAI,UAAU;IAGvB,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAU5B,kDAAkD;IAClD,SAAS,IAAI,QAAQ,EAAE;IAOvB,KAAK,IAAI,IAAI;IAIb,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,sBAAsB,GAAG,IAAI;IAQvE,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,sBAAsB,GAAG,IAAI;CAO1E"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory `LogChannel` for tests — captures every `write(entry)`
|
|
3
|
+
* and exposes Adonis/Laravel-style `assertLogged` /
|
|
4
|
+
* `assertNotLogged` helpers in the same shape as Rover's
|
|
5
|
+
* `FakeMail` and Bay's `FakeQueue`.
|
|
6
|
+
*
|
|
7
|
+
* Not re-exported from the main barrel; reach via
|
|
8
|
+
* `@c9up/spectrum/testing`.
|
|
9
|
+
*/
|
|
10
|
+
export class FakeLogger {
|
|
11
|
+
name = "fake";
|
|
12
|
+
#captured = [];
|
|
13
|
+
write(entry) {
|
|
14
|
+
// Deep-clone via `structuredClone` so nested objects in `data`
|
|
15
|
+
// are isolated — a shallow `{ ...entry.data }` would leak
|
|
16
|
+
// mutations of nested fields back into the captured entry.
|
|
17
|
+
this.#captured.push({
|
|
18
|
+
...entry,
|
|
19
|
+
data: entry.data ? deepClone(entry.data) : undefined,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Defensive snapshot of every captured entry. */
|
|
23
|
+
getLogged() {
|
|
24
|
+
return this.#captured.map((e) => ({
|
|
25
|
+
...e,
|
|
26
|
+
data: e.data ? deepClone(e.data) : undefined,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
reset() {
|
|
30
|
+
this.#captured = [];
|
|
31
|
+
}
|
|
32
|
+
assertLogged(level, predicate) {
|
|
33
|
+
const match = makeMatcher(level, predicate);
|
|
34
|
+
if (this.#captured.some(match))
|
|
35
|
+
return;
|
|
36
|
+
throw new Error(`logger.assertLogged('${level}'${describePredicate(predicate)}) failed — no captured entry matches.\n${describeCaptured(this.#captured)}`);
|
|
37
|
+
}
|
|
38
|
+
assertNotLogged(level, predicate) {
|
|
39
|
+
const match = makeMatcher(level, predicate);
|
|
40
|
+
if (!this.#captured.some(match))
|
|
41
|
+
return;
|
|
42
|
+
throw new Error(`logger.assertNotLogged('${level}'${describePredicate(predicate)}) failed — at least one captured entry matches.\n${describeCaptured(this.#captured)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function makeMatcher(level, predicate) {
|
|
46
|
+
if (typeof predicate === "function") {
|
|
47
|
+
return (e) => e.level === level && predicate(e);
|
|
48
|
+
}
|
|
49
|
+
if (predicate === undefined) {
|
|
50
|
+
return (e) => e.level === level;
|
|
51
|
+
}
|
|
52
|
+
// Validate the predicate AT CONSTRUCTION, not inside the closure —
|
|
53
|
+
// Array.some short-circuits on an empty array, so a check inside
|
|
54
|
+
// the matcher would silently pass when nothing was captured.
|
|
55
|
+
if (predicate.containing === "") {
|
|
56
|
+
throw new Error("FakeLogger: `containing` predicate cannot be an empty string — it would match every captured message.");
|
|
57
|
+
}
|
|
58
|
+
return (e) => {
|
|
59
|
+
if (e.level !== level)
|
|
60
|
+
return false;
|
|
61
|
+
if (predicate.containing !== undefined &&
|
|
62
|
+
!e.message.includes(predicate.containing)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (predicate.dataMatches && !predicate.dataMatches(e.data)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function describePredicate(predicate) {
|
|
72
|
+
if (predicate === undefined)
|
|
73
|
+
return "";
|
|
74
|
+
if (typeof predicate === "function")
|
|
75
|
+
return ", <function predicate>";
|
|
76
|
+
if (Object.keys(predicate).length === 0)
|
|
77
|
+
return ", <empty predicate (level-only)>";
|
|
78
|
+
return `, ${safeStringify(predicate)}`;
|
|
79
|
+
}
|
|
80
|
+
function describeCaptured(captured) {
|
|
81
|
+
if (captured.length === 0)
|
|
82
|
+
return "Captured: (none)";
|
|
83
|
+
const lines = captured.map((e, i) => ` [${i}] ${e.level} module="${e.module}" message="${e.message}"`);
|
|
84
|
+
return `Captured (${captured.length}):\n${lines.join("\n")}`;
|
|
85
|
+
}
|
|
86
|
+
/** `JSON.stringify` with circular-ref + function-field handling.
|
|
87
|
+
* Functions render as `<function>`, circular refs as `<circular>`,
|
|
88
|
+
* unstringifiable values as `<unstringifiable>` — so an assertion
|
|
89
|
+
* failure message never gets eaten by a JSON throw. */
|
|
90
|
+
function safeStringify(value) {
|
|
91
|
+
const seen = new WeakSet();
|
|
92
|
+
try {
|
|
93
|
+
return JSON.stringify(value, (_key, v) => {
|
|
94
|
+
if (typeof v === "function")
|
|
95
|
+
return "<function>";
|
|
96
|
+
if (typeof v === "object" && v !== null) {
|
|
97
|
+
if (seen.has(v))
|
|
98
|
+
return "<circular>";
|
|
99
|
+
seen.add(v);
|
|
100
|
+
}
|
|
101
|
+
return v;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return "<unstringifiable>";
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function deepClone(value) {
|
|
109
|
+
return structuredClone(value);
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=FakeLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeLogger.js","sourceRoot":"","sources":["../../src/testing/FakeLogger.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spectrum types.
|
|
3
|
+
* @implements FR54, FR57
|
|
4
|
+
*/
|
|
5
|
+
export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
6
|
+
export declare const LOG_LEVEL_ORDER: Record<LogLevel, number>;
|
|
7
|
+
export interface LogEntry {
|
|
8
|
+
level: LogLevel;
|
|
9
|
+
message: string;
|
|
10
|
+
module: string;
|
|
11
|
+
correlationId?: string;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
data?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface LogChannel {
|
|
16
|
+
name: string;
|
|
17
|
+
write(entry: LogEntry): void;
|
|
18
|
+
}
|
|
19
|
+
export interface LogConfig {
|
|
20
|
+
level: LogLevel;
|
|
21
|
+
channels: LogChannel[];
|
|
22
|
+
/** Per-module log level overrides */
|
|
23
|
+
modules?: Record<string, LogLevel>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAOpD,CAAC;AAEF,MAAM,WAAW,QAAQ;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACnC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,eAAe,GAA6B;IACxD,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACR,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@c9up/spectrum",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Spectrum — structured logging for the Ream framework",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./provider": {
|
|
15
|
+
"types": "./dist/SpectrumProvider.d.ts",
|
|
16
|
+
"import": "./dist/SpectrumProvider.js"
|
|
17
|
+
},
|
|
18
|
+
"./services/main": {
|
|
19
|
+
"types": "./dist/services/main.d.ts",
|
|
20
|
+
"import": "./dist/services/main.js"
|
|
21
|
+
},
|
|
22
|
+
"./configure": {
|
|
23
|
+
"types": "./dist/configure.d.ts",
|
|
24
|
+
"import": "./dist/configure.js"
|
|
25
|
+
},
|
|
26
|
+
"./testing": {
|
|
27
|
+
"types": "./dist/testing/FakeLogger.d.ts",
|
|
28
|
+
"import": "./dist/testing/FakeLogger.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@c9up/ream": "^0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.19.15",
|
|
36
|
+
"typescript": "^6.0.2",
|
|
37
|
+
"vitest": "^4.1.2"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22.0.0"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"src",
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"@c9up/ream": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/C9up/spectrum.git"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsc -p tsconfig.build.json",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"lint": "biome check src/",
|
|
64
|
+
"test:coverage": "vitest run --coverage",
|
|
65
|
+
"typecheck": "tsc --noEmit"
|
|
66
|
+
}
|
|
67
|
+
}
|