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