@monochromatic-dev/module-logger 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +33 -8
- package/dist/final/neutral/browser.d.mts +60 -0
- package/dist/final/neutral/browser.mjs +1 -0
- package/dist/final/neutral/index.d.mts +360 -594
- package/dist/final/neutral/index.mjs +2 -3
- package/dist/final/neutral/indexed-db-hsIfv7Cv.mjs +2 -0
- package/dist/final/neutral/types-BkkBXgY3.d.mts +76 -0
- package/dist/final/node/file-CRGb1hDK.mjs +1 -0
- package/dist/final/node/index.d.mts +360 -594
- package/dist/final/node/index.mjs +3 -3
- package/dist/final/node/node.d.mts +103 -0
- package/dist/final/node/node.mjs +1 -0
- package/dist/final/node/types-BkkBXgY3.d.mts +76 -0
- package/package.json +18 -4
- package/src/artifact-platform-split.unit.test.ts +140 -0
- package/src/browser.ts +14 -0
- package/src/create-logger.ts +183 -183
- package/src/create-logger.unit.test.ts +112 -112
- package/src/default-sinks.neutral.ts +34 -0
- package/src/default-sinks.node.ts +32 -0
- package/src/error-format.ts +23 -23
- package/src/logger.ts +23 -50
- package/src/node.ts +23 -0
- package/src/sink/console-control-chars.ts +64 -64
- package/src/sink/console-control-chars.unit.test.ts +14 -14
- package/src/sink/console.ts +194 -194
- package/src/sink/console.unit.test.ts +18 -18
- package/src/sink/file.ts +136 -140
- package/src/sink/file.unit.test.ts +19 -26
- package/src/sink/index.ts +4 -7
- package/src/sink/indexed-db-util.ts +42 -42
- package/src/sink/indexed-db.browser.test.ts +7 -7
- package/src/sink/indexed-db.ts +109 -109
- package/src/sink/indexed-db.unit.test.ts +5 -13
- package/src/sink/local-storage-key.ts +73 -73
- package/src/sink/local-storage-key.unit.test.ts +8 -8
- package/src/sink/local-storage-quota.ts +37 -37
- package/src/sink/local-storage-quota.unit.test.ts +8 -8
- package/src/sink/local-storage-store.ts +113 -113
- package/src/sink/local-storage-store.unit.test.ts +35 -35
- package/src/sink/local-storage.ts +72 -72
- package/src/sink/local-storage.unit.test.ts +27 -27
- package/src/sink/noop.ts +20 -20
- package/src/sink/noop.unit.test.ts +1 -1
- package/src/sink/opfs.browser.test.ts +7 -7
- package/src/sink/opfs.ts +62 -62
- package/src/sink/opfs.unit.test.ts +5 -13
- package/src/sink/record-buffer.ts +84 -84
- package/src/sink/record-buffer.unit.test.ts +20 -20
- package/src/sink/session-storage-quota.ts +34 -34
- package/src/sink/session-storage-quota.unit.test.ts +8 -8
- package/src/sink/session-storage-store.ts +72 -72
- package/src/sink/session-storage.ts +48 -48
- package/src/sink/session-storage.unit.test.ts +39 -39
- package/src/sink/web-storage-quota-error.ts +22 -22
- package/src/sink/web-storage-quota-error.unit.test.ts +2 -2
- package/src/sink/web-storage-runtime.ts +24 -24
- package/src/startup.unit.test.ts +18 -18
- package/src/tagged.ts +35 -35
- package/src/tagged.unit.test.ts +8 -8
- package/src/types.ts +39 -39
|
@@ -1,161 +1,85 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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,152 @@ export declare function createLogger({ sinks, flushDeadlineMs, verifyTimeoutMs }
|
|
|
167
91
|
//#endregion
|
|
168
92
|
//#region src/logger.d.ts
|
|
169
93
|
/**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
+
*/
|
|
174
98
|
export declare const initPromise: Promise<void>;
|
|
175
99
|
/**
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
+
*/
|
|
189
113
|
export declare const logger: Logger;
|
|
190
114
|
//#endregion
|
|
191
115
|
//#region src/sink/console.d.ts
|
|
192
116
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
+
*/
|
|
209
133
|
declare function createConsoleSink(): Sink;
|
|
210
134
|
//#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
135
|
//#region src/sink/local-storage.d.ts
|
|
345
136
|
/**
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
+
*/
|
|
368
159
|
declare function createLocalStorageSink(): Sink;
|
|
369
160
|
//#endregion
|
|
370
161
|
//#region src/sink/noop.d.ts
|
|
371
162
|
/**
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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
|
+
*/
|
|
386
177
|
declare function createNoopSink(): Sink;
|
|
387
178
|
//#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
179
|
//#region src/sink/session-storage.d.ts
|
|
414
180
|
/**
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
+
*/
|
|
432
198
|
declare function createSessionStorageSink(): Sink;
|
|
433
199
|
declare namespace index_d_exports {
|
|
434
|
-
export {
|
|
200
|
+
export { createConsoleSink, createLocalStorageSink, createNoopSink, createSessionStorageSink };
|
|
435
201
|
}
|
|
436
202
|
//#endregion
|
|
437
203
|
//#region src/tagged.d.ts
|
|
438
204
|
/**
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
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
|
+
*/
|
|
474
240
|
export declare function tagged({ tag, l }: {
|
|
475
241
|
readonly l?: Logger;
|
|
476
242
|
readonly tag: string;
|
|
@@ -478,31 +244,31 @@ export declare function tagged({ tag, l }: {
|
|
|
478
244
|
//#endregion
|
|
479
245
|
//#region src/sink/console-control-chars.d.ts
|
|
480
246
|
/**
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
+
*/
|
|
499
265
|
declare function neutralizeControlCharacters(text: string): string;
|
|
500
266
|
//#endregion
|
|
501
267
|
//#region src/sink/local-storage-key.d.ts
|
|
502
268
|
/**
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
269
|
+
Parsed identity of one owned localStorage entry, used to order eviction
|
|
270
|
+
across runs.
|
|
271
|
+
*/
|
|
506
272
|
type ParsedLogKey = {
|
|
507
273
|
readonly key: string;
|
|
508
274
|
readonly stamp: number;
|
|
@@ -510,64 +276,64 @@ type ParsedLogKey = {
|
|
|
510
276
|
readonly index: number;
|
|
511
277
|
};
|
|
512
278
|
/**
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
+
*/
|
|
528
294
|
declare function buildLogKey({ stamp, nonce, index }: {
|
|
529
295
|
readonly stamp: number;
|
|
530
296
|
readonly nonce: string;
|
|
531
297
|
readonly index: number;
|
|
532
298
|
}): string;
|
|
533
299
|
/**
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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
|
+
*/
|
|
550
316
|
declare function parseLogKey(key: string): {
|
|
551
317
|
readonly parsed?: ParsedLogKey;
|
|
552
318
|
};
|
|
553
319
|
/**
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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
|
+
*/
|
|
571
337
|
declare function compareLogKeys({ first, second }: {
|
|
572
338
|
readonly first: ParsedLogKey;
|
|
573
339
|
readonly second: ParsedLogKey;
|
|
@@ -575,86 +341,86 @@ declare function compareLogKeys({ first, second }: {
|
|
|
575
341
|
//#endregion
|
|
576
342
|
//#region src/sink/local-storage-quota.d.ts
|
|
577
343
|
/**
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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
|
+
*/
|
|
589
355
|
declare function detectLocalStorageQuotaChars(): number;
|
|
590
356
|
//#endregion
|
|
591
357
|
//#region src/sink/local-storage-store.d.ts
|
|
592
358
|
/**
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
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
|
+
*/
|
|
625
391
|
declare function createLocalStorageStore(): {
|
|
626
392
|
readonly persist: (batch: string) => void;
|
|
627
393
|
};
|
|
628
394
|
//#endregion
|
|
629
395
|
//#region src/sink/record-buffer.d.ts
|
|
630
396
|
/**
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
+
*/
|
|
658
424
|
declare function createRecordBuffer({ onFlush }: {
|
|
659
425
|
readonly onFlush: (batch: string) => void;
|
|
660
426
|
}): {
|
|
@@ -667,35 +433,35 @@ declare function createRecordBuffer({ onFlush }: {
|
|
|
667
433
|
//#endregion
|
|
668
434
|
//#region src/sink/session-storage-quota.d.ts
|
|
669
435
|
/**
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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
|
+
*/
|
|
681
447
|
declare function detectSessionStorageQuotaChars(): number;
|
|
682
448
|
//#endregion
|
|
683
449
|
//#region src/sink/web-storage-quota-error.d.ts
|
|
684
450
|
/**
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
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
|
+
*/
|
|
699
465
|
declare function isQuotaExceededError(error: unknown): boolean;
|
|
700
466
|
//#endregion
|
|
701
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 };
|