@monochromatic-dev/module-logger 0.2.0 → 0.4.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +53 -13
  3. package/dist/final/neutral/browser.d.mts +60 -0
  4. package/dist/final/neutral/browser.mjs +1 -0
  5. package/dist/final/neutral/index.d.mts +359 -596
  6. package/dist/final/neutral/index.mjs +2 -3
  7. package/dist/final/neutral/indexed-db-hsIfv7Cv.mjs +2 -0
  8. package/dist/final/neutral/types-BkkBXgY3.d.mts +76 -0
  9. package/dist/final/node/file-CRGb1hDK.mjs +1 -0
  10. package/dist/final/node/index.d.mts +359 -596
  11. package/dist/final/node/index.mjs +3 -3
  12. package/dist/final/node/node.d.mts +103 -0
  13. package/dist/final/node/node.mjs +1 -0
  14. package/dist/final/node/types-BkkBXgY3.d.mts +76 -0
  15. package/package.json +19 -4
  16. package/src/artifact-platform-split.unit.test.ts +140 -0
  17. package/src/browser.ts +14 -0
  18. package/src/create-logger.ts +183 -183
  19. package/src/create-logger.unit.test.ts +112 -112
  20. package/src/default-sinks.neutral.ts +47 -0
  21. package/src/default-sinks.node.ts +43 -0
  22. package/src/error-format.ts +23 -23
  23. package/src/index.ts +1 -4
  24. package/src/logger.ts +76 -51
  25. package/src/node.ts +23 -0
  26. package/src/restricted-global-scope.unit.test.ts +101 -0
  27. package/src/sink/console-control-chars.ts +64 -64
  28. package/src/sink/console-control-chars.unit.test.ts +14 -14
  29. package/src/sink/console.ts +194 -194
  30. package/src/sink/console.unit.test.ts +18 -18
  31. package/src/sink/file.ts +136 -140
  32. package/src/sink/file.unit.test.ts +19 -26
  33. package/src/sink/index.ts +4 -7
  34. package/src/sink/indexed-db-util.ts +42 -42
  35. package/src/sink/indexed-db.browser.test.ts +7 -7
  36. package/src/sink/indexed-db.ts +109 -109
  37. package/src/sink/indexed-db.unit.test.ts +5 -13
  38. package/src/sink/local-storage-key.ts +73 -73
  39. package/src/sink/local-storage-key.unit.test.ts +8 -8
  40. package/src/sink/local-storage-quota.ts +37 -37
  41. package/src/sink/local-storage-quota.unit.test.ts +8 -8
  42. package/src/sink/local-storage-store.ts +113 -113
  43. package/src/sink/local-storage-store.unit.test.ts +35 -35
  44. package/src/sink/local-storage.ts +72 -72
  45. package/src/sink/local-storage.unit.test.ts +27 -27
  46. package/src/sink/noop.ts +20 -20
  47. package/src/sink/noop.unit.test.ts +1 -1
  48. package/src/sink/opfs.browser.test.ts +7 -7
  49. package/src/sink/opfs.ts +62 -62
  50. package/src/sink/opfs.unit.test.ts +5 -13
  51. package/src/sink/record-buffer.ts +84 -84
  52. package/src/sink/record-buffer.unit.test.ts +20 -20
  53. package/src/sink/session-storage-quota.ts +34 -34
  54. package/src/sink/session-storage-quota.unit.test.ts +8 -8
  55. package/src/sink/session-storage-store.ts +72 -72
  56. package/src/sink/session-storage.ts +48 -48
  57. package/src/sink/session-storage.unit.test.ts +39 -39
  58. package/src/sink/web-storage-quota-error.ts +22 -22
  59. package/src/sink/web-storage-quota-error.unit.test.ts +2 -2
  60. package/src/sink/web-storage-runtime.ts +24 -24
  61. package/src/startup.unit.test.ts +18 -18
  62. package/src/tagged.ts +35 -35
  63. package/src/tagged.unit.test.ts +8 -8
  64. package/src/types.ts +39 -39
@@ -1,161 +1,85 @@
1
- import { stat as stat$1 } from "node:fs/promises";
2
- import { dirname as dirname$1, join as join$1 } from "node:path";
3
- //#region src/types.d.ts
4
- /**
5
- * Log severity levels ordered from least to most severe.
6
- */
7
- type Level = "debug" | "error" | "fatal" | "info" | "trace" | "warn";
8
- /**
9
- * Structured log record written to sinks.
10
- */
11
- type LogRecord = {
12
- readonly level: Level;
13
- readonly message: string;
14
- readonly timestamp: number;
15
- };
16
- /**
17
- * Optional drain hook for sinks that buffer records internally.
18
- * Called via logger-level {@link Logger.flush} to force buffered work
19
- * through before a process exit, critical error boundary, or assertion.
20
- *
21
- * Always async: sinks whose drain is synchronous return an
22
- * already-resolved promise so callers `await` uniformly. A `void` arm is
23
- * not used; under the `no-optional-escape` rule `T | void` is a banned
24
- * fake-optional encoding, and there is no real synchronous value to carry.
25
- */
26
- type SinkFlush = () => Promise<void>;
27
- /**
28
- * Verification function that checks if a sink backend is available.
29
- * May run setup side effects (resolving a log path, opening a writable
30
- * stream) and reports whether the backend is usable. A sink whose
31
- * verification resolves `false` (or rejects) is dropped by the logger and
32
- * receives no further records.
33
- *
34
- * Always async, matching `write` and `flush`: a synchronous check returns an
35
- * already-resolved promise (`Promise.resolve(check)`) so the logger awaits
36
- * verification uniformly with no sync/async branch.
37
- */
38
- type Verify = () => Promise<boolean>;
39
- /**
40
- * Sink that receives log records. A sink is a self-describing adapter: it
41
- * carries everything the logger must know to use it, namely how to
42
- * `verify` its backend is available, how to `write` a record, and
43
- * optionally how to `flush` buffered work. Holding `verify` on the sink
44
- * (rather than as a sibling export the logger pairs by hand) lets the
45
- * logger treat a registry as a plain `Sink[]` and lets a test supply one
46
- * self-contained fake.
47
- *
48
- * Sinks that buffer records (e.g. microtask-batched console) may
49
- * expose a `flush` hook so callers can force emission on demand.
50
- *
51
- * `write` is always async: a synchronous sink does its work eagerly and
52
- * returns an already-resolved promise, so the logger observes a uniform
53
- * `Promise<void>`. A rejected write is handled per sink and does not
54
- * disable the backend; only a failed `verify` drops a sink. A `void` arm
55
- * is not used, for the reason stated on {@link SinkFlush}.
56
- */
57
- type Sink = {
58
- readonly flush?: SinkFlush;
59
- readonly verify: Verify;
60
- readonly write: (record: LogRecord) => Promise<void>;
61
- };
62
- /**
63
- * Logger interface with 6 log levels plus `flush` for startup and sink drains.
64
- * `flush()` resolves once startup verification has completed, tracked sink
65
- * writes have settled, and every available sink's own {@link SinkFlush} hook
66
- * has settled. Safe to call even when no sink buffers.
67
- */
68
- type Logger = {
69
- readonly debug: (message: string) => void;
70
- readonly error: (message: string) => void;
71
- readonly fatal: (message: string) => void;
72
- readonly flush: () => Promise<void>;
73
- readonly info: (message: string) => void;
74
- readonly trace: (message: string) => void;
75
- readonly warn: (message: string) => void;
76
- };
77
- //#endregion
1
+ import { a as SinkFlush, i as Sink, n as LogRecord, o as Verify, r as Logger, t as Level } from "./types-BkkBXgY3.mjs";
78
2
  //#region src/create-logger.d.ts
79
3
  /**
80
- * Default `flush()` deadline in milliseconds. Measured on 2026-09-06: a
81
- * default logger flushing 100 records through the console and file sinks
82
- * settles in about 2 ms locally, so this leaves three orders of magnitude for
83
- * a slow but working backend while still bounding shutdown on a wedged one.
84
- * Override per logger through the `flushDeadlineMs` option of
85
- * {@link createLogger}.
86
- */
4
+ Default `flush()` deadline in milliseconds. Measured on 2026-09-06: a
5
+ default logger flushing 100 records through the console and file sinks
6
+ settles in about 2 ms locally, so this leaves three orders of magnitude for
7
+ a slow but working backend while still bounding shutdown on a wedged one.
8
+ Override per logger through the `flushDeadlineMs` option of
9
+ {@link createLogger}.
10
+ */
87
11
  export declare const DEFAULT_FLUSH_DEADLINE_MS = 5e3;
88
12
  /**
89
- * Default per-sink `verify()` time limit in milliseconds. Measured on
90
- * 2026-09-06: the default logger's five shipped verifies complete together in
91
- * about 2.4 ms locally, so this leaves three orders of magnitude for a slow
92
- * but working backend probe (a network filesystem, a busy IndexedDB) while a
93
- * verify that never answers (a hung mount, an IndexedDB open blocked by
94
- * another tab) can no longer stall startup. Override per logger through the
95
- * `verifyTimeoutMs` option of {@link createLogger}.
96
- */
13
+ Default per-sink `verify()` time limit in milliseconds. Measured on
14
+ 2026-09-06: the default logger's five shipped verifies complete together in
15
+ about 2.4 ms locally, so this leaves three orders of magnitude for a slow
16
+ but working backend probe (a network filesystem, a busy IndexedDB) while a
17
+ verify that never answers (a hung mount, an IndexedDB open blocked by
18
+ another tab) can no longer stall startup. Override per logger through the
19
+ `verifyTimeoutMs` option of {@link createLogger}.
20
+ */
97
21
  export declare const DEFAULT_VERIFY_TIMEOUT_MS = 5e3;
98
22
  /**
99
- * Most records the logger buffers before its sinks have verified. Startup
100
- * lasts at most {@link DEFAULT_VERIFY_TIMEOUT_MS}, so this bounds the memory a
101
- * burst during that window can claim; on overflow the oldest buffered record
102
- * is dropped so the newest (usually most diagnostic) context survives, and
103
- * one synthetic `warn` record naming the dropped count is written to every
104
- * available sink once initialization completes.
105
- */
23
+ Most records the logger buffers before its sinks have verified. Startup
24
+ lasts at most {@link DEFAULT_VERIFY_TIMEOUT_MS}, so this bounds the memory a
25
+ burst during that window can claim; on overflow the oldest buffered record
26
+ is dropped so the newest (usually most diagnostic) context survives, and
27
+ one synthetic `warn` record naming the dropped count is written to every
28
+ available sink once initialization completes.
29
+ */
106
30
  export declare const STARTUP_BUFFER_CAP = 1e4;
107
31
  /**
108
- * Builds a multi-sink logger over the supplied sink adapters. All
109
- * orchestration (per-sink availability, startup buffering and replay,
110
- * in-flight write tracking, and flush) lives here; the exported default
111
- * `logger` is just this factory applied to the default sink set, and tests
112
- * apply it to fake sinks to exercise the orchestration directly.
113
- *
114
- * Verification runs eagerly at construction and never blocks callers:
115
- * records emitted while an async sink is still verifying buffer internally
116
- * and replay to that sink the moment it verifies. Every sink verifies
117
- * concurrently under its own time limit (`verifyTimeoutMs`, default
118
- * {@link DEFAULT_VERIFY_TIMEOUT_MS}), so one backend that never answers
119
- * cannot starve the others or keep the logger from initializing. A sink
120
- * whose `verify` resolves `false`, throws, or runs past the limit is dropped
121
- * and receives no records; an answer that arrives after the limit is
122
- * ignored. A rejected `write` is the sink's own concern and does not disable
123
- * the backend.
124
- *
125
- * `flush()` always resolves: one deadline (`flushDeadlineMs`, default
126
- * {@link DEFAULT_FLUSH_DEADLINE_MS}) wraps startup verification, the
127
- * in-flight write drain, and every sink flush hook together. When it elapses
128
- * the logger reports one breadcrumb, abandons the tracked writes from its
129
- * view (the sinks expose no cancellation, so the underlying work continues),
130
- * and resolves, so a wedged backend cannot hang a shutdown.
131
- *
132
- * @param sinks - Sink adapters to fan each record out to, in priority order.
133
- *
134
- * @param flushDeadlineMs - Milliseconds one `flush()` may take before it
135
- * resolves anyway; raise it for slow but working backends such as network
136
- * filesystems.
137
- *
138
- * @param verifyTimeoutMs - Milliseconds one sink's `verify()` may take before
139
- * the sink counts as unavailable; raise it for a slow but working probe.
140
- *
141
- * @returns Logger plus its eager `initPromise`; callers need not await
142
- * `initPromise` before logging, since startup records replay on verify.
143
- *
144
- * @example
145
- * ```ts
146
- * const { logger } = createLogger({ sinks: [createConsoleSink()] });
147
- * logger.info('ready');
148
- * await logger.flush();
149
- * ```
150
- *
151
- * @example
152
- * ```ts
153
- * const { logger } = createLogger({
154
- * sinks: [createFileSink()],
155
- * flushDeadlineMs: 30_000,
156
- * });
157
- * ```
158
- */
32
+ Builds a multi-sink logger over the supplied sink adapters. All
33
+ orchestration (per-sink availability, startup buffering and replay,
34
+ in-flight write tracking, and flush) lives here; the exported default
35
+ `logger` is just this factory applied to the default sink set, and tests
36
+ apply it to fake sinks to exercise the orchestration directly.
37
+
38
+ Verification runs eagerly at construction and never blocks callers:
39
+ records emitted while an async sink is still verifying buffer internally
40
+ and replay to that sink the moment it verifies. Every sink verifies
41
+ concurrently under its own time limit (`verifyTimeoutMs`, default
42
+ {@link DEFAULT_VERIFY_TIMEOUT_MS}), so one backend that never answers
43
+ cannot starve the others or keep the logger from initializing. A sink
44
+ whose `verify` resolves `false`, throws, or runs past the limit is dropped
45
+ and receives no records; an answer that arrives after the limit is
46
+ ignored. A rejected `write` is the sink's own concern and does not disable
47
+ the backend.
48
+
49
+ `flush()` always resolves: one deadline (`flushDeadlineMs`, default
50
+ {@link DEFAULT_FLUSH_DEADLINE_MS}) wraps startup verification, the
51
+ in-flight write drain, and every sink flush hook together. When it elapses
52
+ the logger reports one breadcrumb, abandons the tracked writes from its
53
+ view (the sinks expose no cancellation, so the underlying work continues),
54
+ and resolves, so a wedged backend cannot hang a shutdown.
55
+
56
+ @param sinks - Sink adapters to fan each record out to, in priority order.
57
+
58
+ @param flushDeadlineMs - Milliseconds one `flush()` may take before it
59
+ resolves anyway; raise it for slow but working backends such as network
60
+ filesystems.
61
+
62
+ @param verifyTimeoutMs - Milliseconds one sink's `verify()` may take before
63
+ the sink counts as unavailable; raise it for a slow but working probe.
64
+
65
+ @returns Logger plus its eager `initPromise`; callers need not await
66
+ `initPromise` before logging, since startup records replay on verify.
67
+
68
+ @example
69
+ ```ts
70
+ const { logger } = createLogger({ sinks: [createConsoleSink()] });
71
+ logger.info('ready');
72
+ await logger.flush();
73
+ ```
74
+
75
+ @example
76
+ ```ts
77
+ const { logger } = createLogger({
78
+ sinks: [createFileSink()],
79
+ flushDeadlineMs: 30_000,
80
+ });
81
+ ```
82
+ */
159
83
  export declare function createLogger({ sinks, flushDeadlineMs, verifyTimeoutMs }: {
160
84
  readonly sinks: readonly Sink[];
161
85
  readonly flushDeadlineMs?: number;
@@ -167,310 +91,149 @@ export declare function createLogger({ sinks, flushDeadlineMs, verifyTimeoutMs }
167
91
  //#endregion
168
92
  //#region src/logger.d.ts
169
93
  /**
170
- * Eager readiness promise. Consumers do not need to await this before logging;
171
- * {@link Logger.flush} awaits it internally, and startup records replay to
172
- * async sinks as they become available.
173
- */
174
- export declare const initPromise: Promise<void>;
175
- /**
176
- * Multi-sink logger that writes to all available backends.
177
- * Startup records replay to async sinks that verify after the log call.
178
- * Log calls throw only when initialization proves no backend is available,
179
- * which the console sink prevents in every supported runtime.
180
- *
181
- * @example
182
- * ```ts
183
- * import { logger, } from '\@monochromatic-dev/module-logger/logger';
184
- *
185
- * logger.error('unexpected shutdown',);
186
- * await logger.flush();
187
- * ```
188
- */
94
+ Multi-sink logger that writes to all available backends, built lazily on
95
+ the first call. Startup records replay to async sinks that verify after
96
+ the log call. Log calls throw only when initialization proves no backend is
97
+ available, which the console sink prevents in every supported runtime.
98
+ `flush()` awaits verification internally, so no readiness promise is
99
+ exported: awaiting one at module top level was the mistake this design
100
+ removes.
101
+
102
+ @example
103
+ ```ts
104
+ import { logger, } from '\@monochromatic-dev/module-logger';
105
+
106
+ logger.error('unexpected shutdown',);
107
+ await logger.flush();
108
+ ```
109
+ */
189
110
  export declare const logger: Logger;
190
111
  //#endregion
191
112
  //#region src/sink/console.d.ts
192
113
  /**
193
- * Builds a microtask-batched console sink. The pending buffer, schedule flag,
194
- * and memoized verbose detection live in this instance's closure (no
195
- * module-global state), so independent loggers and tests stay isolated with
196
- * no reset hook. Collapses contiguous same-level runs into single `console.*`
197
- * calls, sharply reducing console-panel overhead when an instrumented path
198
- * emits many records per sync frame.
199
- *
200
- * @returns Sink that writes formatted lines to `console.*`, except
201
- * process-hosted debug records write to stderr.
202
- *
203
- * @example
204
- * ```ts
205
- * const { logger } = createLogger({ sinks: [createConsoleSink()] });
206
- * logger.info('server started');
207
- * ```
208
- */
114
+ Builds a microtask-batched console sink. The pending buffer, schedule flag,
115
+ and memoized verbose detection live in this instance's closure (no
116
+ module-global state), so independent loggers and tests stay isolated with
117
+ no reset hook. Collapses contiguous same-level runs into single `console.*`
118
+ calls, sharply reducing console-panel overhead when an instrumented path
119
+ emits many records per sync frame.
120
+
121
+ @returns Sink that writes formatted lines to `console.*`, except
122
+ process-hosted debug records write to stderr.
123
+
124
+ @example
125
+ ```ts
126
+ const { logger } = createLogger({ sinks: [createConsoleSink()] });
127
+ logger.info('server started');
128
+ ```
129
+ */
209
130
  declare function createConsoleSink(): Sink;
210
131
  //#endregion
211
- //#region src/error-format.d.ts
212
- /**
213
- * Reports a logger-internal caught value without going back through logger
214
- * sinks, formatting it via {@link caughtValueText}.
215
- *
216
- * @param context - Human-readable operation that caught the value.
217
- *
218
- * @param error - Caught value to include in the diagnostic.
219
- *
220
- * @mutates error - `caughtValueText` may invoke string-conversion hooks.
221
- *
222
- * @example
223
- * ```ts
224
- * reportLoggerInternalError({
225
- * context: 'console sink verify failed',
226
- * error: new Error('blocked'),
227
- * });
228
- * ```
229
- */
230
- declare function reportLoggerInternalError({ context, error }: {
231
- readonly context: string;
232
- readonly error: unknown;
233
- }): void;
234
- //#endregion
235
- //#region src/sink/file.d.ts
236
- /**
237
- * Sentinel returned by {@link findNodeModulesUp} when no ancestor directory
238
- * contains a `node_modules`. A unique symbol so it never collides with a real
239
- * path string the walk might otherwise return, keeping the result free of a
240
- * banned `string | undefined` union.
241
- *
242
- * @example
243
- * ```ts
244
- * const dir = await findNodeModulesUp({ cwd, stat, dirname, join });
245
- * if (dir === NO_NODE_MODULES_FOUND) {
246
- * // no ancestor project root
247
- * }
248
- * ```
249
- */
250
- declare const NO_NODE_MODULES_FOUND: unique symbol;
251
- /**
252
- * Walks up from `cwd` to find the nearest ancestor directory containing a
253
- * `node_modules` subdirectory, returning that subdirectory's absolute path.
254
- *
255
- * Using find-up rather than cwd-relative placement keeps log directories
256
- * anchored to the project the caller actually belongs to. Without this,
257
- * scripts invoked from build output (e.g. `dist/`) or other stray cwds
258
- * would create `node_modules/.monochromatic/` inside those trees, polluting
259
- * shipped artifacts.
260
- *
261
- * Exported primarily so `index.unit.test.ts` can exercise both the hit
262
- * and miss paths directly with an injected `stat`.
263
- *
264
- * @param cwd - starting directory for the upward search
265
- *
266
- * @param stat - `node:fs/promises` stat (injected so the dynamic
267
- * import stays in one place)
268
- *
269
- * @param dirname - `node:path` dirname
270
- *
271
- * @param join - `node:path` join
272
- *
273
- * @param reportError - logger fault reporter injected for deterministic tests
274
- *
275
- * @returns absolute path to the nearest ancestor `node_modules`, or
276
- * {@link NO_NODE_MODULES_FOUND} when no ancestor contains one
277
- *
278
- * @example
279
- * ```ts
280
- * const dir = await findNodeModulesUp({ cwd: process.cwd(), stat, dirname, join });
281
- * ```
282
- */
283
- declare function findNodeModulesUp({ cwd, stat, dirname, join, reportError }: {
284
- readonly cwd: string;
285
- readonly stat: typeof stat$1;
286
- readonly dirname: typeof dirname$1;
287
- readonly join: typeof join$1;
288
- readonly reportError?: typeof reportLoggerInternalError;
289
- }): Promise<string | typeof NO_NODE_MODULES_FOUND>;
290
- /**
291
- * Builds a file sink that appends JSONL records to the nearest ancestor
292
- * `node_modules/.monochromatic/{timestamp}.log.jsonl` (resolved once during
293
- * verification). The resolved path, the cached `appendFile`, and the
294
- * verification memo live in this instance's closure (no module-global state),
295
- * so independent loggers and tests never share a log file or need a reset
296
- * hook. No `flush` hook: each `write` awaits `appendFile` directly, so there
297
- * is no buffered state to drain.
298
- *
299
- * @returns Sink backed by `node:fs/promises`.
300
- *
301
- * @example
302
- * ```ts
303
- * const { logger } = createLogger({ sinks: [createFileSink()] });
304
- * logger.error('unhandled rejection');
305
- * await logger.flush();
306
- * ```
307
- */
308
- declare function createFileSink(): Sink;
309
- //#endregion
310
- //#region src/sink/indexed-db.d.ts
311
- /**
312
- * Builds an IndexedDB sink that buffers serialized records through the shared
313
- * {@link createRecordBuffer} policy and persists each newline-joined JSONL
314
- * batch as one string value per transaction, measured at 0.15 µs of
315
- * main-thread enqueue per record on headless Chromium 149 (one `add` per
316
- * 32 KiB batch). The connection lives in this instance's closure (no
317
- * module-global state), so independent loggers and tests never share a
318
- * handle or need a reset hook.
319
- *
320
- * Records are readable the moment their transaction settles (DevTools
321
- * Application tab included), survive tab close and browser restart, and
322
- * auto-incremented keys serialize across tabs, so no run-scoped naming is
323
- * needed. Retention trims oldest-first past {@link MAX_STORED_BATCHES}.
324
- * Transactions use the default relaxed durability: relaxed commits reach the
325
- * browser's storage backend promptly and survive renderer crashes, and the
326
- * OS-crash window `durability: 'strict'` would close is the rarest failure
327
- * class, not worth an fsync per batch.
328
- *
329
- * Flush triggers (32 KiB in-write cap, `warn`-or-worse severity, 250 ms
330
- * quiet-period deadline, page lifecycle, and the `flush` hook) are the
331
- * buffer's; see {@link createRecordBuffer}. The sink's `flush` hook awaits
332
- * every issued batch transaction before resolving.
333
- *
334
- * @returns Sink backed by IndexedDB.
335
- *
336
- * @example
337
- * ```ts
338
- * const { logger } = createLogger({ sinks: [createIndexedDbSink()] });
339
- * logger.warn('quota nearing limit');
340
- * ```
341
- */
342
- declare function createIndexedDbSink(): Sink;
343
- //#endregion
344
132
  //#region src/sink/local-storage.d.ts
345
133
  /**
346
- * Builds a localStorage sink that buffers serialized records through the
347
- * shared {@link createRecordBuffer} policy and persists each newline-joined
348
- * JSONL batch under a run-scoped counter-incremented key through
349
- * {@link createLocalStorageStore}. One uniform write path runs on every
350
- * runtime; no per-runtime mode exists. Flush triggers (32 KiB in-write cap,
351
- * `warn`-or-worse severity, 250 ms quiet-period deadline, page lifecycle,
352
- * and the `flush` hook) are the buffer's; see {@link createRecordBuffer}.
353
- *
354
- * Unlike the sessionStorage sink, whose store dies with the tab, this sink's
355
- * batches survive tab close and browser restart, bounded by oldest-first
356
- * eviction at half the localStorage quota; that makes it the web storage sink
357
- * whose records remain inspectable after a full crash-and-restart.
358
- *
359
- * @returns Sink backed by web `localStorage`.
360
- *
361
- * @example
362
- * ```ts
363
- * const { logger } = createLogger({ sinks: [createLocalStorageSink()] });
364
- * logger.info('user signed in'); // buffered
365
- * logger.warn('quota near'); // flushes both records in one batch
366
- * ```
367
- */
134
+ Builds a localStorage sink that buffers serialized records through the
135
+ shared {@link createRecordBuffer} policy and persists each newline-joined
136
+ JSONL batch under a run-scoped counter-incremented key through
137
+ {@link createLocalStorageStore}. One uniform write path runs on every
138
+ runtime; no per-runtime mode exists. Flush triggers (32 KiB in-write cap,
139
+ `warn`-or-worse severity, 250 ms quiet-period deadline, page lifecycle,
140
+ and the `flush` hook) are the buffer's; see {@link createRecordBuffer}.
141
+
142
+ Unlike the sessionStorage sink, whose store dies with the tab, this sink's
143
+ batches survive tab close and browser restart, bounded by oldest-first
144
+ eviction at half the localStorage quota; that makes it the web storage sink
145
+ whose records remain inspectable after a full crash-and-restart.
146
+
147
+ @returns Sink backed by web `localStorage`.
148
+
149
+ @example
150
+ ```ts
151
+ const { logger } = createLogger({ sinks: [createLocalStorageSink()] });
152
+ logger.info('user signed in'); // buffered
153
+ logger.warn('quota near'); // flushes both records in one batch
154
+ ```
155
+ */
368
156
  declare function createLocalStorageSink(): Sink;
369
157
  //#endregion
370
158
  //#region src/sink/noop.d.ts
371
159
  /**
372
- * Builds a noop sink that discards every record and always verifies as
373
- * available. Stateless, so the returned adapters share the same functions;
374
- * the factory shape merely matches the other sinks. Useful as a stand-in
375
- * that disables logging without removing log calls.
376
- *
377
- * @returns Sink that discards all records and exposes no `flush` (nothing
378
- * is buffered).
379
- *
380
- * @example
381
- * ```ts
382
- * const { logger } = createLogger({ sinks: [createNoopSink()] });
383
- * logger.info('goes nowhere');
384
- * ```
385
- */
160
+ Builds a noop sink that discards every record and always verifies as
161
+ available. Stateless, so the returned adapters share the same functions;
162
+ the factory shape merely matches the other sinks. Useful as a stand-in
163
+ that disables logging without removing log calls.
164
+
165
+ @returns Sink that discards all records and exposes no `flush` (nothing
166
+ is buffered).
167
+
168
+ @example
169
+ ```ts
170
+ const { logger } = createLogger({ sinks: [createNoopSink()] });
171
+ logger.info('goes nowhere');
172
+ ```
173
+ */
386
174
  declare function createNoopSink(): Sink;
387
175
  //#endregion
388
- //#region src/sink/opfs.d.ts
389
- /**
390
- * Builds an OPFS sink that buffers serialized records through the shared
391
- * {@link createRecordBuffer} policy and appends each newline-joined JSONL
392
- * batch to a per-session file in the Origin Private File System with one
393
- * stream write per batch. The kept-open writable stream lives in this
394
- * instance's closure (no module-global state), so independent loggers and
395
- * tests never share a handle or need a reset hook.
396
- *
397
- * Flush triggers (32 KiB in-write cap, `warn`-or-worse severity, 250 ms
398
- * quiet-period deadline, page lifecycle, and the `flush` hook) are the
399
- * buffer's; see {@link createRecordBuffer}. Batch writes queue on the stream
400
- * in issue order, so ordering holds at the batch boundary, and the sink's
401
- * `flush` hook awaits every issued batch before resolving.
402
- *
403
- * @returns Sink backed by OPFS.
404
- *
405
- * @example
406
- * ```ts
407
- * const { logger } = createLogger({ sinks: [createOpfsSink()] });
408
- * logger.warn('quota nearing limit');
409
- * ```
410
- */
411
- declare function createOpfsSink(): Sink;
412
- //#endregion
413
176
  //#region src/sink/session-storage.d.ts
414
177
  /**
415
- * Builds a sessionStorage sink that buffers serialized records through the
416
- * shared {@link createRecordBuffer} policy and persists each newline-joined
417
- * JSONL batch under a counter-incremented key through
418
- * {@link createSessionStorageStore}. One uniform write path runs on every
419
- * runtime; no per-runtime mode exists. Flush triggers (32 KiB in-write cap,
420
- * `warn`-or-worse severity, 250 ms quiet-period deadline, page lifecycle,
421
- * and the `flush` hook) are the buffer's; see {@link createRecordBuffer}.
422
- *
423
- * @returns Sink backed by web `sessionStorage`.
424
- *
425
- * @example
426
- * ```ts
427
- * const { logger } = createLogger({ sinks: [createSessionStorageSink()] });
428
- * logger.info('user signed in'); // buffered
429
- * logger.warn('quota near'); // flushes both records in one batch
430
- * ```
431
- */
178
+ Builds a sessionStorage sink that buffers serialized records through the
179
+ shared {@link createRecordBuffer} policy and persists each newline-joined
180
+ JSONL batch under a counter-incremented key through
181
+ {@link createSessionStorageStore}. One uniform write path runs on every
182
+ runtime; no per-runtime mode exists. Flush triggers (32 KiB in-write cap,
183
+ `warn`-or-worse severity, 250 ms quiet-period deadline, page lifecycle,
184
+ and the `flush` hook) are the buffer's; see {@link createRecordBuffer}.
185
+
186
+ @returns Sink backed by web `sessionStorage`.
187
+
188
+ @example
189
+ ```ts
190
+ const { logger } = createLogger({ sinks: [createSessionStorageSink()] });
191
+ logger.info('user signed in'); // buffered
192
+ logger.warn('quota near'); // flushes both records in one batch
193
+ ```
194
+ */
432
195
  declare function createSessionStorageSink(): Sink;
433
196
  declare namespace index_d_exports {
434
- export { NO_NODE_MODULES_FOUND, createConsoleSink, createFileSink, createIndexedDbSink, createLocalStorageSink, createNoopSink, createOpfsSink, createSessionStorageSink, findNodeModulesUp };
197
+ export { createConsoleSink, createLocalStorageSink, createNoopSink, createSessionStorageSink };
435
198
  }
436
199
  //#endregion
437
200
  //#region src/tagged.d.ts
438
201
  /**
439
- * Wraps a logger so every message is prefixed with `[tag] `.
440
- * Callers typically pass `myFn.name` as tag to keep prefixes
441
- * in sync with refactors.
442
- *
443
- * @param tag - Prefix string inserted before each message
444
- *
445
- * @param l - Base logger to wrap; defaults to the module-level {@link logger}
446
- * singleton
447
- *
448
- * @returns Logger whose methods prepend `[tag] ` to every message
449
- *
450
- * @example
451
- * ```ts
452
- * import { tagged } from '\@monochromatic-dev/module-logger/tagged';
453
- *
454
- * function handleRequest({ l }: { l: Logger }): void {
455
- * l.info('received');
456
- * }
457
- *
458
- * handleRequest({ l: tagged({ tag: handleRequest.name }) });
459
- * // logs: [handleRequest] received
460
- * ```
461
- *
462
- * @example
463
- * ```ts
464
- * // Composing tags: the outermost wrap (`l2` here) prepends to the message
465
- * // last, so its tag ends up rightmost. The innermost wrap (`l1`) hits the
466
- * // underlying logger first, so its tag is leftmost. The chain reads
467
- * // root-first: outer wrap = inner tag position.
468
- * const l1 = tagged({ tag: 'http' });
469
- * const l2 = tagged({ tag: 'retry', l: l1 });
470
- * l2.info('attempt 3');
471
- * // logs: [http] [retry] attempt 3
472
- * ```
473
- */
202
+ Wraps a logger so every message is prefixed with `[tag] `.
203
+ Callers typically pass `myFn.name` as tag to keep prefixes
204
+ in sync with refactors.
205
+
206
+ @param tag - Prefix string inserted before each message
207
+
208
+ @param l - Base logger to wrap; defaults to the module-level {@link logger}
209
+ singleton
210
+
211
+ @returns Logger whose methods prepend `[tag] ` to every message
212
+
213
+ @example
214
+ ```ts
215
+ import { tagged } from '\@monochromatic-dev/module-logger/tagged';
216
+
217
+ function handleRequest({ l }: { l: Logger }): void {
218
+ l.info('received');
219
+ }
220
+
221
+ handleRequest({ l: tagged({ tag: handleRequest.name }) });
222
+ // logs: [handleRequest] received
223
+ ```
224
+
225
+ @example
226
+ ```ts
227
+ // Composing tags: the outermost wrap (`l2` here) prepends to the message
228
+ // last, so its tag ends up rightmost. The innermost wrap (`l1`) hits the
229
+ // underlying logger first, so its tag is leftmost. The chain reads
230
+ // root-first: outer wrap = inner tag position.
231
+ const l1 = tagged({ tag: 'http' });
232
+ const l2 = tagged({ tag: 'retry', l: l1 });
233
+ l2.info('attempt 3');
234
+ // logs: [http] [retry] attempt 3
235
+ ```
236
+ */
474
237
  export declare function tagged({ tag, l }: {
475
238
  readonly l?: Logger;
476
239
  readonly tag: string;
@@ -478,31 +241,31 @@ export declare function tagged({ tag, l }: {
478
241
  //#endregion
479
242
  //#region src/sink/console-control-chars.d.ts
480
243
  /**
481
- * Neutralizes terminal control characters in console-bound text. One linear
482
- * pass over the code points: each neutralized control becomes a `\uXXXX`
483
- * escape, everything else is copied through, and newline and tab pass
484
- * untouched. Well-formed and malformed escape sequences get no
485
- * special treatment because the introducer byte itself is neutralized, so a
486
- * trailing lone ESC, an unterminated OSC, and a nested ESC all lose their
487
- * teeth the same way.
488
- *
489
- * @param text - Message text destined for `console.*` or `process.stderr`.
490
- *
491
- * @returns Text with every neutralized control rendered as `\uXXXX`.
492
- *
493
- * @example
494
- * ```ts
495
- * neutralizeControlCharacters('title:\u001B]0;x\u0007 ok\n\tnext');
496
- * // => 'title:\\u001B]0;x\\u0007 ok\n\tnext'
497
- * ```
498
- */
244
+ Neutralizes terminal control characters in console-bound text. One linear
245
+ pass over the code points: each neutralized control becomes a `\uXXXX`
246
+ escape, everything else is copied through, and newline and tab pass
247
+ untouched. Well-formed and malformed escape sequences get no
248
+ special treatment because the introducer byte itself is neutralized, so a
249
+ trailing lone ESC, an unterminated OSC, and a nested ESC all lose their
250
+ teeth the same way.
251
+
252
+ @param text - Message text destined for `console.*` or `process.stderr`.
253
+
254
+ @returns Text with every neutralized control rendered as `\uXXXX`.
255
+
256
+ @example
257
+ ```ts
258
+ neutralizeControlCharacters('title:\u001B]0;x\u0007 ok\n\tnext');
259
+ // => 'title:\\u001B]0;x\\u0007 ok\n\tnext'
260
+ ```
261
+ */
499
262
  declare function neutralizeControlCharacters(text: string): string;
500
263
  //#endregion
501
264
  //#region src/sink/local-storage-key.d.ts
502
265
  /**
503
- * Parsed identity of one owned localStorage entry, used to order eviction
504
- * across runs.
505
- */
266
+ Parsed identity of one owned localStorage entry, used to order eviction
267
+ across runs.
268
+ */
506
269
  type ParsedLogKey = {
507
270
  readonly key: string;
508
271
  readonly stamp: number;
@@ -510,64 +273,64 @@ type ParsedLogKey = {
510
273
  readonly index: number;
511
274
  };
512
275
  /**
513
- * Builds the namespaced localStorage key for one batch slot of one run.
514
- *
515
- * @param stamp - Run creation time ordering runs oldest-first.
516
- *
517
- * @param nonce - Same-millisecond disambiguator between concurrent tabs.
518
- *
519
- * @param index - Zero-based batch slot within the run.
520
- *
521
- * @returns Key such as `monochromatic.log.1753000000000.a1b2.3`.
522
- *
523
- * @example
524
- * ```ts
525
- * buildLogKey({ stamp: 1753000000000, nonce: 'a1b2', index: 3 });
526
- * ```
527
- */
276
+ Builds the namespaced localStorage key for one batch slot of one run.
277
+
278
+ @param stamp - Run creation time ordering runs oldest-first.
279
+
280
+ @param nonce - Same-millisecond disambiguator between concurrent tabs.
281
+
282
+ @param index - Zero-based batch slot within the run.
283
+
284
+ @returns Key such as `monochromatic.log.1753000000000.a1b2.3`.
285
+
286
+ @example
287
+ ```ts
288
+ buildLogKey({ stamp: 1753000000000, nonce: 'a1b2', index: 3 });
289
+ ```
290
+ */
528
291
  declare function buildLogKey({ stamp, nonce, index }: {
529
292
  readonly stamp: number;
530
293
  readonly nonce: string;
531
294
  readonly index: number;
532
295
  }): string;
533
296
  /**
534
- * Parses a localStorage key back into its run identity, or reports it foreign
535
- * by leaving `parsed` absent. Parsing is strict (exact prefix, exactly the
536
- * identity segment count, digit-shaped stamp and index, non-empty nonce)
537
- * because eviction trusts this to never classify a host application's key, or
538
- * the sessionStorage sink's flat `monochromatic.log.{n}` shape, as evictable.
539
- *
540
- * @param key - Candidate localStorage key.
541
- *
542
- * @returns Wrapper whose `parsed` property is present only for an owned key.
543
- *
544
- * @example
545
- * ```ts
546
- * parseLogKey('monochromatic.log.1753000000000.a1b2.3').parsed; // ParsedLogKey
547
- * parseLogKey('monochromatic.log.5').parsed; // undefined: sessionStorage shape
548
- * ```
549
- */
297
+ Parses a localStorage key back into its run identity, or reports it foreign
298
+ by leaving `parsed` absent. Parsing is strict (exact prefix, exactly the
299
+ identity segment count, digit-shaped stamp and index, non-empty nonce)
300
+ because eviction trusts this to never classify a host application's key, or
301
+ the sessionStorage sink's flat `monochromatic.log.{n}` shape, as evictable.
302
+
303
+ @param key - Candidate localStorage key.
304
+
305
+ @returns Wrapper whose `parsed` property is present only for an owned key.
306
+
307
+ @example
308
+ ```ts
309
+ parseLogKey('monochromatic.log.1753000000000.a1b2.3').parsed; // ParsedLogKey
310
+ parseLogKey('monochromatic.log.5').parsed; // undefined: sessionStorage shape
311
+ ```
312
+ */
550
313
  declare function parseLogKey(key: string): {
551
314
  readonly parsed?: ParsedLogKey;
552
315
  };
553
316
  /**
554
- * Orders parsed keys oldest-first for eviction: by run stamp, then by nonce
555
- * (an arbitrary but stable tiebreak between same-millisecond runs), then by
556
- * batch index within the run.
557
- *
558
- * @param first - Parsed key compared first.
559
- *
560
- * @param second - Parsed key compared second.
561
- *
562
- * @returns Negative when `first` is older, positive when newer, zero on ties.
563
- *
564
- * @example
565
- * ```ts
566
- * entries.toSorted(function byOldestFirst(first, second) {
567
- * return compareLogKeys({ first, second });
568
- * });
569
- * ```
570
- */
317
+ Orders parsed keys oldest-first for eviction: by run stamp, then by nonce
318
+ (an arbitrary but stable tiebreak between same-millisecond runs), then by
319
+ batch index within the run.
320
+
321
+ @param first - Parsed key compared first.
322
+
323
+ @param second - Parsed key compared second.
324
+
325
+ @returns Negative when `first` is older, positive when newer, zero on ties.
326
+
327
+ @example
328
+ ```ts
329
+ entries.toSorted(function byOldestFirst(first, second) {
330
+ return compareLogKeys({ first, second });
331
+ });
332
+ ```
333
+ */
571
334
  declare function compareLogKeys({ first, second }: {
572
335
  readonly first: ParsedLogKey;
573
336
  readonly second: ParsedLogKey;
@@ -575,86 +338,86 @@ declare function compareLogKeys({ first, second }: {
575
338
  //#endregion
576
339
  //#region src/sink/local-storage-quota.d.ts
577
340
  /**
578
- * Detects the current runtime's default localStorage quota in UTF-16 code
579
- * units, or `Number.POSITIVE_INFINITY` when the runtime is unrecognized so the
580
- * caller leaves its footprint uncapped and relies on reactive eviction alone.
581
- *
582
- * @returns Total quota in code units, or `Number.POSITIVE_INFINITY` if unknown.
583
- *
584
- * @example
585
- * ```ts
586
- * const capChars = detectLocalStorageQuotaChars() / 2; // half the total
587
- * ```
588
- */
341
+ Detects the current runtime's default localStorage quota in UTF-16 code
342
+ units, or `Number.POSITIVE_INFINITY` when the runtime is unrecognized so the
343
+ caller leaves its footprint uncapped and relies on reactive eviction alone.
344
+
345
+ @returns Total quota in code units, or `Number.POSITIVE_INFINITY` if unknown.
346
+
347
+ @example
348
+ ```ts
349
+ const capChars = detectLocalStorageQuotaChars() / 2; // half the total
350
+ ```
351
+ */
589
352
  declare function detectLocalStorageQuotaChars(): number;
590
353
  //#endregion
591
354
  //#region src/sink/local-storage-store.d.ts
592
355
  /**
593
- * Builds the persistence engine behind the localStorage sink: each `persist`
594
- * lands one already-serialized batch under a run-scoped counter-incremented
595
- * key, with proactive and reactive quota eviction. Run identity and counters
596
- * live in this instance's closure (no module-global state), so independent
597
- * sinks and tests never share keys or need a reset hook.
598
- *
599
- * Unlike sessionStorage, localStorage is shared by every tab of the origin and
600
- * survives restarts, so this engine differs from the sessionStorage engine in
601
- * two ways. Keys carry a run identity (see `local-storage-key.ts`), so
602
- * concurrent tabs never collide on a counter. And on its first persist the
603
- * engine adopts every strictly-parsed entry left by other runs into its
604
- * footprint tally, evicting those oldest-first before its own entries;
605
- * without that, leftovers from dead sessions would fill the store until no
606
- * run could ever write again. Adoption is deferred to first persist rather
607
- * than construction so building the default sink set never touches
608
- * `globalThis.localStorage` on runtimes where the sink never verifies (plain
609
- * Node warns on mere access). Keys that fail the strict parse, including the
610
- * host application's, are never counted and never evicted.
611
- *
612
- * The engine caps its own footprint (adopted entries included) at half the
613
- * runtime's localStorage quota, proactively dropping oldest-first, and
614
- * reactively drops again if the real store still overflows; see
615
- * {@link createLocalStorageStore.persist}.
616
- *
617
- * @returns Engine exposing `persist` for one batch value per call.
618
- *
619
- * @example
620
- * ```ts
621
- * const store = createLocalStorageStore();
622
- * store.persist('{"level":"info","message":"hi","timestamp":0}');
623
- * ```
624
- */
356
+ Builds the persistence engine behind the localStorage sink: each `persist`
357
+ lands one already-serialized batch under a run-scoped counter-incremented
358
+ key, with proactive and reactive quota eviction. Run identity and counters
359
+ live in this instance's closure (no module-global state), so independent
360
+ sinks and tests never share keys or need a reset hook.
361
+
362
+ Unlike sessionStorage, localStorage is shared by every tab of the origin and
363
+ survives restarts, so this engine differs from the sessionStorage engine in
364
+ two ways. Keys carry a run identity (see `local-storage-key.ts`), so
365
+ concurrent tabs never collide on a counter. And on its first persist the
366
+ engine adopts every strictly-parsed entry left by other runs into its
367
+ footprint tally, evicting those oldest-first before its own entries;
368
+ without that, leftovers from dead sessions would fill the store until no
369
+ run could ever write again. Adoption is deferred to first persist rather
370
+ than construction so building the default sink set never touches
371
+ `globalThis.localStorage` on runtimes where the sink never verifies (plain
372
+ Node warns on mere access). Keys that fail the strict parse, including the
373
+ host application's, are never counted and never evicted.
374
+
375
+ The engine caps its own footprint (adopted entries included) at half the
376
+ runtime's localStorage quota, proactively dropping oldest-first, and
377
+ reactively drops again if the real store still overflows; see
378
+ {@link createLocalStorageStore.persist}.
379
+
380
+ @returns Engine exposing `persist` for one batch value per call.
381
+
382
+ @example
383
+ ```ts
384
+ const store = createLocalStorageStore();
385
+ store.persist('{"level":"info","message":"hi","timestamp":0}');
386
+ ```
387
+ */
625
388
  declare function createLocalStorageStore(): {
626
389
  readonly persist: (batch: string) => void;
627
390
  };
628
391
  //#endregion
629
392
  //#region src/sink/record-buffer.d.ts
630
393
  /**
631
- * Builds the buffering stage shared by batch-persisting sinks: serialized
632
- * records accumulate and leave as one newline-joined JSONL batch through
633
- * `onFlush`. One uniform policy runs on every runtime; no per-runtime mode
634
- * exists.
635
- *
636
- * A batch flushes synchronously from inside `add` when it reaches
637
- * {@link FLUSH_BUFFER_CAP_CHARS} or when the record's severity is `warn` or
638
- * worse, by timer after {@link FLUSH_DEADLINE_MS} of quiet, on `pagehide`
639
- * and on the document becoming hidden (where those events exist), and on
640
- * `drain`. The byte-cap and severity flushes run on the caller's stack, so
641
- * neither a synchronous workload nor a wedged main thread can accumulate
642
- * more than one cap of unhanded records. When an addition would breach the
643
- * cap, the existing entries flush first so an oversized record's downstream
644
- * failure can only ever drop that record, never its batch-mates.
645
- *
646
- * @param onFlush - Backend handoff receiving each newline-joined batch;
647
- * called synchronously from whichever trigger fires, in record order.
648
- *
649
- * @returns Buffer exposing `add` for records and `drain` for forced flushes.
650
- *
651
- * @example
652
- * ```ts
653
- * const buffer = createRecordBuffer({ onFlush: (batch) => store.persist(batch) });
654
- * buffer.add({ level: 'info', serialized: JSON.stringify(record) });
655
- * buffer.drain();
656
- * ```
657
- */
394
+ Builds the buffering stage shared by batch-persisting sinks: serialized
395
+ records accumulate and leave as one newline-joined JSONL batch through
396
+ `onFlush`. One uniform policy runs on every runtime; no per-runtime mode
397
+ exists.
398
+
399
+ A batch flushes synchronously from inside `add` when it reaches
400
+ {@link FLUSH_BUFFER_CAP_CHARS} or when the record's severity is `warn` or
401
+ worse, by timer after {@link FLUSH_DEADLINE_MS} of quiet, on `pagehide`
402
+ and on the document becoming hidden (where those events exist), and on
403
+ `drain`. The byte-cap and severity flushes run on the caller's stack, so
404
+ neither a synchronous workload nor a wedged main thread can accumulate
405
+ more than one cap of unhanded records. When an addition would breach the
406
+ cap, the existing entries flush first so an oversized record's downstream
407
+ failure can only ever drop that record, never its batch-mates.
408
+
409
+ @param onFlush - Backend handoff receiving each newline-joined batch;
410
+ called synchronously from whichever trigger fires, in record order.
411
+
412
+ @returns Buffer exposing `add` for records and `drain` for forced flushes.
413
+
414
+ @example
415
+ ```ts
416
+ const buffer = createRecordBuffer({ onFlush: (batch) => store.persist(batch) });
417
+ buffer.add({ level: 'info', serialized: JSON.stringify(record) });
418
+ buffer.drain();
419
+ ```
420
+ */
658
421
  declare function createRecordBuffer({ onFlush }: {
659
422
  readonly onFlush: (batch: string) => void;
660
423
  }): {
@@ -667,35 +430,35 @@ declare function createRecordBuffer({ onFlush }: {
667
430
  //#endregion
668
431
  //#region src/sink/session-storage-quota.d.ts
669
432
  /**
670
- * Detects the current runtime's default sessionStorage quota in UTF-16 code
671
- * units, or `Number.POSITIVE_INFINITY` when the runtime is unrecognized so the
672
- * caller leaves its footprint uncapped and relies on reactive eviction alone.
673
- *
674
- * @returns Total quota in code units, or `Number.POSITIVE_INFINITY` if unknown.
675
- *
676
- * @example
677
- * ```ts
678
- * const capChars = detectSessionStorageQuotaChars() / 2; // half the total
679
- * ```
680
- */
433
+ Detects the current runtime's default sessionStorage quota in UTF-16 code
434
+ units, or `Number.POSITIVE_INFINITY` when the runtime is unrecognized so the
435
+ caller leaves its footprint uncapped and relies on reactive eviction alone.
436
+
437
+ @returns Total quota in code units, or `Number.POSITIVE_INFINITY` if unknown.
438
+
439
+ @example
440
+ ```ts
441
+ const capChars = detectSessionStorageQuotaChars() / 2; // half the total
442
+ ```
443
+ */
681
444
  declare function detectSessionStorageQuotaChars(): number;
682
445
  //#endregion
683
446
  //#region src/sink/web-storage-quota-error.d.ts
684
447
  /**
685
- * Reports whether a caught `setItem` value is a storage quota overflow, so
686
- * eviction reclaims space only for a full store and never for an unrelated
687
- * write fault such as a disabled-storage `SecurityError`.
688
- *
689
- * @param error - Caught value from a `setItem` failure.
690
- *
691
- * @returns Whether `error` names a quota overflow.
692
- *
693
- * @example
694
- * ```ts
695
- * try { sessionStorage.setItem(k, v); }
696
- * catch (error: unknown) { if (isQuotaExceededError(error)) evictOldest(); }
697
- * ```
698
- */
448
+ Reports whether a caught `setItem` value is a storage quota overflow, so
449
+ eviction reclaims space only for a full store and never for an unrelated
450
+ write fault such as a disabled-storage `SecurityError`.
451
+
452
+ @param error - Caught value from a `setItem` failure.
453
+
454
+ @returns Whether `error` names a quota overflow.
455
+
456
+ @example
457
+ ```ts
458
+ try { sessionStorage.setItem(k, v); }
459
+ catch (error: unknown) { if (isQuotaExceededError(error)) evictOldest(); }
460
+ ```
461
+ */
699
462
  declare function isQuotaExceededError(error: unknown): boolean;
700
463
  //#endregion
701
464
  export { type Level, type LogRecord, type Logger, type Sink, type SinkFlush, type Verify, buildLogKey as _buildLogKey, compareLogKeys as _compareLogKeys, createLocalStorageStore as _createLocalStorageStore, createRecordBuffer as _createRecordBuffer, detectLocalStorageQuotaChars as _detectLocalStorageQuotaChars, detectSessionStorageQuotaChars as _detectSessionStorageQuotaChars, isQuotaExceededError as _isQuotaExceededError, neutralizeControlCharacters as _neutralizeControlCharacters, parseLogKey as _parseLogKey, index_d_exports as sinks };