@monochromatic-dev/module-logger 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +58 -12
- package/dist/final/neutral/browser.d.mts +60 -0
- package/dist/final/neutral/browser.mjs +1 -0
- package/dist/final/neutral/index.d.mts +366 -572
- package/dist/final/neutral/index.mjs +2 -3
- package/dist/final/neutral/indexed-db-hsIfv7Cv.mjs +2 -0
- package/dist/final/neutral/types-BkkBXgY3.d.mts +76 -0
- package/dist/final/node/file-CRGb1hDK.mjs +1 -0
- package/dist/final/node/index.d.mts +366 -572
- package/dist/final/node/index.mjs +3 -3
- package/dist/final/node/node.d.mts +103 -0
- package/dist/final/node/node.mjs +1 -0
- package/dist/final/node/types-BkkBXgY3.d.mts +76 -0
- package/package.json +19 -5
- package/src/artifact-platform-split.unit.test.ts +140 -0
- package/src/browser.ts +14 -0
- package/src/create-logger.ts +249 -151
- package/src/create-logger.unit.test.ts +527 -75
- package/src/default-sinks.neutral.ts +34 -0
- package/src/default-sinks.node.ts +32 -0
- package/src/error-format.ts +23 -23
- package/src/index.ts +2 -0
- package/src/logger.ts +23 -50
- package/src/node.ts +23 -0
- package/src/sink/console-control-chars.ts +64 -64
- package/src/sink/console-control-chars.unit.test.ts +14 -14
- package/src/sink/console.ts +194 -194
- package/src/sink/console.unit.test.ts +18 -18
- package/src/sink/file.ts +136 -140
- package/src/sink/file.unit.test.ts +19 -26
- package/src/sink/index.ts +4 -7
- package/src/sink/indexed-db-util.ts +42 -42
- package/src/sink/indexed-db.browser.test.ts +7 -7
- package/src/sink/indexed-db.ts +109 -109
- package/src/sink/indexed-db.unit.test.ts +5 -13
- package/src/sink/local-storage-key.ts +73 -73
- package/src/sink/local-storage-key.unit.test.ts +8 -8
- package/src/sink/local-storage-quota.ts +37 -37
- package/src/sink/local-storage-quota.unit.test.ts +8 -8
- package/src/sink/local-storage-store.ts +113 -113
- package/src/sink/local-storage-store.unit.test.ts +35 -35
- package/src/sink/local-storage.ts +72 -72
- package/src/sink/local-storage.unit.test.ts +27 -27
- package/src/sink/noop.ts +20 -20
- package/src/sink/noop.unit.test.ts +1 -1
- package/src/sink/opfs.browser.test.ts +7 -7
- package/src/sink/opfs.ts +62 -62
- package/src/sink/opfs.unit.test.ts +5 -13
- package/src/sink/record-buffer.ts +84 -84
- package/src/sink/record-buffer.unit.test.ts +20 -20
- package/src/sink/session-storage-quota.ts +34 -34
- package/src/sink/session-storage-quota.unit.test.ts +8 -8
- package/src/sink/session-storage-store.ts +72 -72
- package/src/sink/session-storage.ts +48 -48
- package/src/sink/session-storage.unit.test.ts +39 -39
- package/src/sink/web-storage-quota-error.ts +22 -22
- package/src/sink/web-storage-quota-error.unit.test.ts +2 -2
- package/src/sink/web-storage-runtime.ts +24 -24
- package/src/startup.unit.test.ts +18 -18
- package/src/tagged.ts +35 -35
- package/src/tagged.unit.test.ts +8 -8
- package/src/types.ts +39 -39
package/src/sink/console.ts
CHANGED
|
@@ -8,20 +8,20 @@ import type {
|
|
|
8
8
|
} from '../types.ts';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
Sentinel for an uncomputed `verboseCache` slot. A unique `Symbol` rather
|
|
12
|
+
than `null`: the `no-nullish-union` rule bans a nullish "absent" arm, and
|
|
13
|
+
a real `boolean` value is the computed state this must stay distinct from.
|
|
14
14
|
*/
|
|
15
15
|
const VERBOSE_UNCOMPUTED = Symbol('logger:verbose-detection-uncomputed',);
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
Levels silenced by default unless verbose mode is active.
|
|
19
|
+
|
|
20
|
+
@example
|
|
21
|
+
```ts
|
|
22
|
+
SILENT_LEVELS.has('trace'); // true
|
|
23
|
+
SILENT_LEVELS.has('info'); // false
|
|
24
|
+
```
|
|
25
25
|
*/
|
|
26
26
|
const SILENT_LEVELS: ReadonlySet<string> = new Set([
|
|
27
27
|
'debug',
|
|
@@ -29,28 +29,28 @@ const SILENT_LEVELS: ReadonlySet<string> = new Set([
|
|
|
29
29
|
],);
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
32
|
+
Detects verbose mode from environment variables, process arguments,
|
|
33
|
+
and runtime environment.
|
|
34
|
+
Checks `process.env.MONOCHROMATIC_VERBOSE`, `process.argv` for `--verbose`,
|
|
35
|
+
and whether the runtime is a browser.
|
|
36
|
+
Browser environments enable verbose by default because DevTools
|
|
37
|
+
already provides its own log-level filtering, making logger-side
|
|
38
|
+
suppression redundant. Each check is individually guarded
|
|
39
|
+
so unavailable globals never cause throws.
|
|
40
|
+
|
|
41
|
+
@returns Whether verbose output is enabled.
|
|
42
|
+
|
|
43
|
+
@example
|
|
44
|
+
```ts
|
|
45
|
+
// With MONOCHROMATIC_VERBOSE=true in environment
|
|
46
|
+
detectVerbose(); // true
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
@example
|
|
50
|
+
```ts
|
|
51
|
+
// In a browser environment (window is defined)
|
|
52
|
+
detectVerbose(); // true
|
|
53
|
+
```
|
|
54
54
|
*/
|
|
55
55
|
function detectVerbose(): boolean {
|
|
56
56
|
try {
|
|
@@ -101,22 +101,22 @@ function detectVerbose(): boolean {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
104
|
+
Detects explicit warn suppression via the `MONOCHROMATIC_WARN` environment
|
|
105
|
+
variable.
|
|
106
|
+
|
|
107
|
+
Setting `MONOCHROMATIC_WARN=false` drops `warn`-level records, for machine-protocol
|
|
108
|
+
consumers (such as a stdin/stdout codec) whose output streams must stay clean
|
|
109
|
+
on success. Only the exact string `'false'` suppresses; any other value, or an
|
|
110
|
+
absent variable, leaves `warn` enabled. Read on each call (not memoized) so a
|
|
111
|
+
host can toggle it between logs.
|
|
112
|
+
|
|
113
|
+
@returns Whether `warn`-level records are suppressed.
|
|
114
|
+
|
|
115
|
+
@example
|
|
116
|
+
```ts
|
|
117
|
+
// With MONOCHROMATIC_WARN=false in environment
|
|
118
|
+
isWarnSuppressed(); // true
|
|
119
|
+
```
|
|
120
120
|
*/
|
|
121
121
|
function isWarnSuppressed(): boolean {
|
|
122
122
|
try {
|
|
@@ -134,11 +134,11 @@ function isWarnSuppressed(): boolean {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
Maps log levels to the name of the console method that handles them.
|
|
138
|
+
Names rather than function references so tests (and other hot patches)
|
|
139
|
+
that replace `console.info` etc. after module load still see their
|
|
140
|
+
replacement when the sink flushes. `debug` uses this mapping only when
|
|
141
|
+
process stderr is unavailable, preserving browser `console.debug` output.
|
|
142
142
|
*/
|
|
143
143
|
const LEVEL_TO_CONSOLE_METHOD: Record<Level,
|
|
144
144
|
'debug' | 'error' | 'info' | 'trace' | 'warn'> = {
|
|
@@ -151,19 +151,19 @@ const LEVEL_TO_CONSOLE_METHOD: Record<Level,
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
154
|
+
Formats a single log record into the display string used by console output.
|
|
155
|
+
The message passes through {@link neutralizeControlCharacters} first, so a
|
|
156
|
+
terminal never receives a control sequence smuggled inside log text.
|
|
157
|
+
|
|
158
|
+
@param record - Record to format.
|
|
159
|
+
|
|
160
|
+
@returns Formatted line of the shape `[level] [iso] message`.
|
|
161
|
+
|
|
162
|
+
@example
|
|
163
|
+
```ts
|
|
164
|
+
formatRecord({ level: 'info', message: 'hi', timestamp: 0 });
|
|
165
|
+
// => '[info] [1970-01-01T00:00:00.000Z] hi'
|
|
166
|
+
```
|
|
167
167
|
*/
|
|
168
168
|
function formatRecord(record: LogRecord,): string {
|
|
169
169
|
return `[${record.level}] [${
|
|
@@ -173,17 +173,17 @@ function formatRecord(record: LogRecord,): string {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
176
|
+
Detects whether process stderr can receive debug records directly. Kept
|
|
177
|
+
separate from writing so availability checks can still require
|
|
178
|
+
`console.debug` when stderr is unavailable and browser fallback is needed.
|
|
179
|
+
|
|
180
|
+
@returns Whether process stderr exposes a callable `write` method.
|
|
181
|
+
|
|
182
|
+
@example
|
|
183
|
+
```ts
|
|
184
|
+
hasProcessStderr();
|
|
185
|
+
// => true in Node.js and Bun processes
|
|
186
|
+
```
|
|
187
187
|
*/
|
|
188
188
|
function hasProcessStderr(): boolean {
|
|
189
189
|
try {
|
|
@@ -204,19 +204,19 @@ function hasProcessStderr(): boolean {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
207
|
+
Writes a formatted debug run to process stderr when the host exposes a
|
|
208
|
+
process stream. Falling back to `console.debug` keeps browser and restricted
|
|
209
|
+
runtimes working when `process` is absent or unusable.
|
|
210
|
+
|
|
211
|
+
@param text - Formatted debug run text that should stay off stdout.
|
|
212
|
+
|
|
213
|
+
@returns Whether process stderr accepted the debug run.
|
|
214
|
+
|
|
215
|
+
@example
|
|
216
|
+
```ts
|
|
217
|
+
writeDebugRunToProcessStderr('[debug] [1970-01-01T00:00:00.000Z] hi');
|
|
218
|
+
// => true when process.stderr.write is available
|
|
219
|
+
```
|
|
220
220
|
*/
|
|
221
221
|
function writeDebugRunToProcessStderr(text: string,): boolean {
|
|
222
222
|
try {
|
|
@@ -237,20 +237,20 @@ function writeDebugRunToProcessStderr(text: string,): boolean {
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
/**
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
240
|
+
Emits a contiguous run of same-level records as a single console call,
|
|
241
|
+
joining formatted lines with `\n`. Debug records write to process stderr
|
|
242
|
+
when `process.stderr.write` is available, keeping stdout clean in CLI hosts.
|
|
243
|
+
|
|
244
|
+
@param records - Records that all share `level`.
|
|
245
|
+
|
|
246
|
+
@param level - Shared severity level whose mapped `console.*` receives
|
|
247
|
+
the joined text.
|
|
248
|
+
|
|
249
|
+
@example
|
|
250
|
+
```ts
|
|
251
|
+
emitRun({ records: [{ level: 'info', message: 'a', timestamp: 0 }], level: 'info' });
|
|
252
|
+
// calls console.info('[info] [1970-01-01T00:00:00.000Z] a')
|
|
253
|
+
```
|
|
254
254
|
*/
|
|
255
255
|
function emitRun(
|
|
256
256
|
{
|
|
@@ -262,7 +262,7 @@ function emitRun(
|
|
|
262
262
|
},
|
|
263
263
|
): void {
|
|
264
264
|
/**
|
|
265
|
-
|
|
265
|
+
Joined run text; one `\n`-separated string per console call so a long run becomes a single grouped entry rather than N separate ones.
|
|
266
266
|
*/
|
|
267
267
|
const text = records
|
|
268
268
|
.map(function formatOne(r,) {
|
|
@@ -273,11 +273,11 @@ function emitRun(
|
|
|
273
273
|
return;
|
|
274
274
|
try {
|
|
275
275
|
/**
|
|
276
|
-
|
|
276
|
+
Name (not the function reference) of the matching `console.*` method; resolved lazily so post-import hot patches still apply.
|
|
277
277
|
*/
|
|
278
278
|
const method = LEVEL_TO_CONSOLE_METHOD[level];
|
|
279
279
|
/**
|
|
280
|
-
|
|
280
|
+
Resolved console method looked up by name; may be missing or non-callable in stripped runtimes, which the guard handles.
|
|
281
281
|
*/
|
|
282
282
|
const consoleFn = console[method];
|
|
283
283
|
if ((typeof consoleFn) === 'function') {
|
|
@@ -296,9 +296,9 @@ function emitRun(
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
A contiguous slice of buffered records that share one level. Built by
|
|
300
|
+
{@link groupRuns} and consumed by {@link flushBuffer} to emit one
|
|
301
|
+
`console.*` call per slice.
|
|
302
302
|
*/
|
|
303
303
|
type Run = {
|
|
304
304
|
level: Level;
|
|
@@ -306,24 +306,24 @@ type Run = {
|
|
|
306
306
|
};
|
|
307
307
|
|
|
308
308
|
/**
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
309
|
+
Groups a record sequence into contiguous same-level runs. Each input
|
|
310
|
+
record is appended to the trailing run when its level matches, otherwise
|
|
311
|
+
a new run is opened. A reduce-based collapse keeps the cursor (run head
|
|
312
|
+
and span) out of mutable function-body locals.
|
|
313
|
+
|
|
314
|
+
@param records - Buffered records in arrival order.
|
|
315
|
+
|
|
316
|
+
@returns Ordered list of runs covering every input record exactly once.
|
|
317
|
+
|
|
318
|
+
@example
|
|
319
|
+
```ts
|
|
320
|
+
groupRuns([
|
|
321
|
+
{ level: 'debug', message: 'a', timestamp: 0 },
|
|
322
|
+
{ level: 'debug', message: 'b', timestamp: 0 },
|
|
323
|
+
{ level: 'warn', message: 'c', timestamp: 0 },
|
|
324
|
+
]);
|
|
325
|
+
// => [{ level: 'debug', records: [a, b] }, { level: 'warn', records: [c] }]
|
|
326
|
+
```
|
|
327
327
|
*/
|
|
328
328
|
function groupRuns(records: readonly LogRecord[],): Run[] {
|
|
329
329
|
return records.reduce<Run[]>(
|
|
@@ -332,7 +332,7 @@ function groupRuns(records: readonly LogRecord[],): Run[] {
|
|
|
332
332
|
record,
|
|
333
333
|
) {
|
|
334
334
|
/**
|
|
335
|
-
|
|
335
|
+
Trailing run being extended; new same-level records append onto it, otherwise a fresh run is opened.
|
|
336
336
|
*/
|
|
337
337
|
const tail = runs.at(-1,);
|
|
338
338
|
if ((tail !== undefined) && (tail.level
|
|
@@ -353,21 +353,21 @@ function groupRuns(records: readonly LogRecord[],): Run[] {
|
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
/**
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
356
|
+
Verifies console is available and microtask scheduling is supported.
|
|
357
|
+
`queueMicrotask` is the batching primitive; without it there is no
|
|
358
|
+
ordering guarantee that preserves "end of current sync frame" semantics,
|
|
359
|
+
so the sink reports itself unavailable instead of falling back to an
|
|
360
|
+
inferior scheduler. Stateless: the logger calls this once and owns the
|
|
361
|
+
resulting availability.
|
|
362
|
+
|
|
363
|
+
@returns Whether console logging is available.
|
|
364
|
+
|
|
365
|
+
@example
|
|
366
|
+
```ts
|
|
367
|
+
if (await verifyConsole()) {
|
|
368
|
+
// console usable
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
371
|
*/
|
|
372
372
|
function verifyConsole(): Promise<boolean> {
|
|
373
373
|
try {
|
|
@@ -375,8 +375,8 @@ function verifyConsole(): Promise<boolean> {
|
|
|
375
375
|
return Promise.resolve(false,);
|
|
376
376
|
|
|
377
377
|
/**
|
|
378
|
-
|
|
379
|
-
|
|
378
|
+
Sample console method used only to check that debug has an output path:
|
|
379
|
+
process runtimes use stderr, while fallback runtimes need `console.debug`.
|
|
380
380
|
*/
|
|
381
381
|
const testFn = hasProcessStderr() ? console.info : console.debug;
|
|
382
382
|
if ((typeof testFn) !== 'function')
|
|
@@ -397,29 +397,29 @@ function verifyConsole(): Promise<boolean> {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
/**
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
400
|
+
Builds a microtask-batched console sink. The pending buffer, schedule flag,
|
|
401
|
+
and memoized verbose detection live in this instance's closure (no
|
|
402
|
+
module-global state), so independent loggers and tests stay isolated with
|
|
403
|
+
no reset hook. Collapses contiguous same-level runs into single `console.*`
|
|
404
|
+
calls, sharply reducing console-panel overhead when an instrumented path
|
|
405
|
+
emits many records per sync frame.
|
|
406
|
+
|
|
407
|
+
@returns Sink that writes formatted lines to `console.*`, except
|
|
408
|
+
process-hosted debug records write to stderr.
|
|
409
|
+
|
|
410
|
+
@example
|
|
411
|
+
```ts
|
|
412
|
+
const { logger } = createLogger({ sinks: [createConsoleSink()] });
|
|
413
|
+
logger.info('server started');
|
|
414
|
+
```
|
|
415
415
|
*/
|
|
416
416
|
export function createConsoleSink(): Sink {
|
|
417
417
|
/**
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
418
|
+
Instance-local console-sink state. `buffer` holds records awaiting the
|
|
419
|
+
next microtask flush; `scheduled` guards against redundant
|
|
420
|
+
`queueMicrotask` calls within one sync frame; `verboseCache` memoizes
|
|
421
|
+
verbose detection (the sentinel means not yet computed) so a host can
|
|
422
|
+
mutate `process.env.MONOCHROMATIC_VERBOSE` before the first log and still be seen.
|
|
423
423
|
*/
|
|
424
424
|
const state: {
|
|
425
425
|
buffer: LogRecord[];
|
|
@@ -432,22 +432,22 @@ export function createConsoleSink(): Sink {
|
|
|
432
432
|
};
|
|
433
433
|
|
|
434
434
|
/**
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
435
|
+
Reads the memoized verbose flag, evaluating via {@link detectVerbose} on
|
|
436
|
+
first call. Lazy rather than at construction so tests (and hosts) can
|
|
437
|
+
mutate `process.env.MONOCHROMATIC_VERBOSE` between construction and first log without a
|
|
438
|
+
stale cache.
|
|
439
|
+
|
|
440
|
+
@returns Whether verbose logging is enabled for this process.
|
|
441
441
|
*/
|
|
442
442
|
function getVerbose(): boolean {
|
|
443
443
|
/**
|
|
444
|
-
|
|
444
|
+
Cached verbose flag; the sentinel means detection has not run yet.
|
|
445
445
|
*/
|
|
446
446
|
const cached = state.verboseCache;
|
|
447
447
|
if (cached !== VERBOSE_UNCOMPUTED)
|
|
448
448
|
return cached;
|
|
449
449
|
/**
|
|
450
|
-
|
|
450
|
+
Computed verbose flag, stored so subsequent reads skip detection.
|
|
451
451
|
*/
|
|
452
452
|
const computed = detectVerbose();
|
|
453
453
|
state.verboseCache = computed;
|
|
@@ -455,13 +455,13 @@ export function createConsoleSink(): Sink {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
458
|
+
Drains the buffer, collapsing contiguous same-level runs (via
|
|
459
|
+
{@link groupRuns}) into single console calls emitted by {@link emitRun}.
|
|
460
|
+
A sequence `[debug, debug, warn, debug]` becomes three calls:
|
|
461
|
+
`process.stderr.write` (two lines joined), `console.warn`, then
|
|
462
|
+
`process.stderr.write` under process runtimes. Typical instrumented
|
|
463
|
+
functions use a single level throughout, so most flushes collapse to one
|
|
464
|
+
call.
|
|
465
465
|
*/
|
|
466
466
|
function flushBuffer(): void {
|
|
467
467
|
state.scheduled = false;
|
|
@@ -471,10 +471,10 @@ export function createConsoleSink(): Sink {
|
|
|
471
471
|
return;
|
|
472
472
|
|
|
473
473
|
/**
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
474
|
+
Snapshot of buffered records drained before the loop.
|
|
475
|
+
|
|
476
|
+
Using `splice(0)` empties the buffer atomically so any record enqueued
|
|
477
|
+
during emission lands in the next flush rather than this one.
|
|
478
478
|
*/
|
|
479
479
|
const records = state.buffer
|
|
480
480
|
.splice(0,);
|
|
@@ -487,12 +487,12 @@ export function createConsoleSink(): Sink {
|
|
|
487
487
|
}
|
|
488
488
|
|
|
489
489
|
/**
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
490
|
+
Enqueues a record for microtask-batched emission. Silently discards
|
|
491
|
+
`debug`/`trace` unless {@link getVerbose} reports verbose mode is active
|
|
492
|
+
(via `MONOCHROMATIC_VERBOSE=true` env var, `--verbose` argv, or browser environment), and
|
|
493
|
+
drops `warn` when {@link isWarnSuppressed}.
|
|
494
|
+
|
|
495
|
+
@param record - Log record to write.
|
|
496
496
|
*/
|
|
497
497
|
function write(record: LogRecord,): Promise<void> {
|
|
498
498
|
if ((!getVerbose()) && SILENT_LEVELS
|
|
@@ -514,9 +514,9 @@ export function createConsoleSink(): Sink {
|
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
/**
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
517
|
+
Forces any buffered records through to the console immediately via
|
|
518
|
+
{@link flushBuffer}. Returns an already-resolved promise so call sites
|
|
519
|
+
await uniformly with async sinks. Safe to call when the buffer is empty.
|
|
520
520
|
*/
|
|
521
521
|
function flush(): Promise<void> {
|
|
522
522
|
flushBuffer();
|
|
@@ -9,17 +9,17 @@ import {
|
|
|
9
9
|
} from '@monochromatic-dev/module-logger';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
|
|
12
|
+
Sink factories under test, read from the built artifact's `sinks` namespace.
|
|
13
13
|
*/
|
|
14
14
|
const {
|
|
15
15
|
createConsoleSink,
|
|
16
16
|
} = sinks;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
Awaits two microtask hops so any pending `queueMicrotask(flushBuffer)`
|
|
20
|
+
has definitely fired and the buffer is drained before the next assertion.
|
|
21
|
+
One hop would often be enough, but two is cheap insurance against timing
|
|
22
|
+
skew from the harness itself.
|
|
23
23
|
*/
|
|
24
24
|
async function waitForFlush(): Promise<void> {
|
|
25
25
|
await Promise.resolve();
|
|
@@ -27,14 +27,14 @@ async function waitForFlush(): Promise<void> {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
Builds a `LogRecord` with a fixed timestamp so the formatted output
|
|
31
|
+
is stable across test runs.
|
|
32
|
+
|
|
33
|
+
@param level - Severity level.
|
|
34
|
+
|
|
35
|
+
@param message - Message body.
|
|
36
|
+
|
|
37
|
+
@returns A complete `LogRecord`.
|
|
38
38
|
*/
|
|
39
39
|
function record(
|
|
40
40
|
{
|
|
@@ -53,11 +53,11 @@ function record(
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
Appends `--verbose` to `process.argv` and removes it again when the returned
|
|
57
|
+
value goes out of `using` scope, so a verbose-detection test cannot leak the
|
|
58
|
+
flag into the sibling test that asserts the silenced default.
|
|
59
|
+
|
|
60
|
+
@returns Disposable that restores `process.argv` on scope exit.
|
|
61
61
|
*/
|
|
62
62
|
function withVerboseArgv(): Disposable {
|
|
63
63
|
process.argv
|