@monochromatic-dev/module-logger 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +53 -13
  3. package/dist/final/neutral/browser.d.mts +60 -0
  4. package/dist/final/neutral/browser.mjs +1 -0
  5. package/dist/final/neutral/index.d.mts +359 -596
  6. package/dist/final/neutral/index.mjs +2 -3
  7. package/dist/final/neutral/indexed-db-hsIfv7Cv.mjs +2 -0
  8. package/dist/final/neutral/types-BkkBXgY3.d.mts +76 -0
  9. package/dist/final/node/file-CRGb1hDK.mjs +1 -0
  10. package/dist/final/node/index.d.mts +359 -596
  11. package/dist/final/node/index.mjs +3 -3
  12. package/dist/final/node/node.d.mts +103 -0
  13. package/dist/final/node/node.mjs +1 -0
  14. package/dist/final/node/types-BkkBXgY3.d.mts +76 -0
  15. package/package.json +19 -4
  16. package/src/artifact-platform-split.unit.test.ts +140 -0
  17. package/src/browser.ts +14 -0
  18. package/src/create-logger.ts +183 -183
  19. package/src/create-logger.unit.test.ts +112 -112
  20. package/src/default-sinks.neutral.ts +47 -0
  21. package/src/default-sinks.node.ts +43 -0
  22. package/src/error-format.ts +23 -23
  23. package/src/index.ts +1 -4
  24. package/src/logger.ts +76 -51
  25. package/src/node.ts +23 -0
  26. package/src/restricted-global-scope.unit.test.ts +101 -0
  27. package/src/sink/console-control-chars.ts +64 -64
  28. package/src/sink/console-control-chars.unit.test.ts +14 -14
  29. package/src/sink/console.ts +194 -194
  30. package/src/sink/console.unit.test.ts +18 -18
  31. package/src/sink/file.ts +136 -140
  32. package/src/sink/file.unit.test.ts +19 -26
  33. package/src/sink/index.ts +4 -7
  34. package/src/sink/indexed-db-util.ts +42 -42
  35. package/src/sink/indexed-db.browser.test.ts +7 -7
  36. package/src/sink/indexed-db.ts +109 -109
  37. package/src/sink/indexed-db.unit.test.ts +5 -13
  38. package/src/sink/local-storage-key.ts +73 -73
  39. package/src/sink/local-storage-key.unit.test.ts +8 -8
  40. package/src/sink/local-storage-quota.ts +37 -37
  41. package/src/sink/local-storage-quota.unit.test.ts +8 -8
  42. package/src/sink/local-storage-store.ts +113 -113
  43. package/src/sink/local-storage-store.unit.test.ts +35 -35
  44. package/src/sink/local-storage.ts +72 -72
  45. package/src/sink/local-storage.unit.test.ts +27 -27
  46. package/src/sink/noop.ts +20 -20
  47. package/src/sink/noop.unit.test.ts +1 -1
  48. package/src/sink/opfs.browser.test.ts +7 -7
  49. package/src/sink/opfs.ts +62 -62
  50. package/src/sink/opfs.unit.test.ts +5 -13
  51. package/src/sink/record-buffer.ts +84 -84
  52. package/src/sink/record-buffer.unit.test.ts +20 -20
  53. package/src/sink/session-storage-quota.ts +34 -34
  54. package/src/sink/session-storage-quota.unit.test.ts +8 -8
  55. package/src/sink/session-storage-store.ts +72 -72
  56. package/src/sink/session-storage.ts +48 -48
  57. package/src/sink/session-storage.unit.test.ts +39 -39
  58. package/src/sink/web-storage-quota-error.ts +22 -22
  59. package/src/sink/web-storage-quota-error.unit.test.ts +2 -2
  60. package/src/sink/web-storage-runtime.ts +24 -24
  61. package/src/startup.unit.test.ts +18 -18
  62. package/src/tagged.ts +35 -35
  63. package/src/tagged.unit.test.ts +8 -8
  64. package/src/types.ts +39 -39
@@ -16,55 +16,55 @@ import {
16
16
  } from '@monochromatic-dev/module-logger';
17
17
 
18
18
  /**
19
- * Milliseconds a slow write parks before recording, long enough that the
20
- * record is provably still pending when a synchronous assertion runs but the
21
- * draining `flush()` must wait for it.
19
+ Milliseconds a slow write parks before recording, long enough that the
20
+ record is provably still pending when a synchronous assertion runs but the
21
+ draining `flush()` must wait for it.
22
22
  */
23
23
  const SLOW_WRITE_MS = 25;
24
24
 
25
25
  /**
26
- * Flush deadline the deadline tests inject: short enough to keep the suite
27
- * fast, long enough that timer granularity cannot fire it early.
26
+ Flush deadline the deadline tests inject: short enough to keep the suite
27
+ fast, long enough that timer granularity cannot fire it early.
28
28
  */
29
29
  const SHORT_DEADLINE_MS = 60;
30
30
 
31
31
  /**
32
- * Timer slack subtracted from the deadline when asserting a flush waited it
33
- * out, covering setTimeout clamping and scheduler jitter.
32
+ Timer slack subtracted from the deadline when asserting a flush waited it
33
+ out, covering setTimeout clamping and scheduler jitter.
34
34
  */
35
35
  const DEADLINE_TOLERANCE_MS = 15;
36
36
 
37
37
  /**
38
- * Upper bound on a flush that must not wait out the deadline again; well
39
- * under `SHORT_DEADLINE_MS` so a regression that re-waits is caught.
38
+ Upper bound on a flush that must not wait out the deadline again; well
39
+ under `SHORT_DEADLINE_MS` so a regression that re-waits is caught.
40
40
  */
41
41
  const FAST_FLUSH_MS = 40;
42
42
 
43
43
  /**
44
- * Harness timeout for the deadline tests: a regression that hangs forever
45
- * fails here instead of stalling the suite.
44
+ Harness timeout for the deadline tests: a regression that hangs forever
45
+ fails here instead of stalling the suite.
46
46
  */
47
47
  const DEADLINE_TEST_TIMEOUT_MS = 2_000;
48
48
 
49
49
  /**
50
- * Promise that never settles, standing in for a wedged sink operation.
51
- *
52
- * @returns Pending promise whose resolver is unreachable.
50
+ Promise that never settles, standing in for a wedged sink operation.
51
+
52
+ @returns Pending promise whose resolver is unreachable.
53
53
  */
54
54
  function neverSettles(): Promise<never> {
55
55
  return Promise.withResolvers<never>().promise;
56
56
  }
57
57
 
58
58
  /**
59
- * Times one `flush()` call.
60
- *
61
- * @param flush - Flush function to time.
62
- *
63
- * @returns Elapsed milliseconds.
59
+ Times one `flush()` call.
60
+
61
+ @param flush - Flush function to time.
62
+
63
+ @returns Elapsed milliseconds.
64
64
  */
65
65
  async function timeFlush({ flush, }: { readonly flush: () => Promise<void>; },): Promise<number> {
66
66
  /**
67
- * Start timestamp.
67
+ Start timestamp.
68
68
  */
69
69
  const start = performance.now();
70
70
  await flush();
@@ -72,23 +72,23 @@ async function timeFlush({ flush, }: { readonly flush: () => Promise<void>; },):
72
72
  }
73
73
 
74
74
  /**
75
- * Structural view of a sinon stub: only the recorded calls matter here, and
76
- * naming the shape keeps the test free of a direct sinon type import.
75
+ Structural view of a sinon stub: only the recorded calls matter here, and
76
+ naming the shape keeps the test free of a direct sinon type import.
77
77
  */
78
78
  type RecordedCalls = {
79
79
  readonly getCalls: () => readonly { readonly args: readonly unknown[]; }[];
80
80
  };
81
81
 
82
82
  /**
83
- * Collects the console.warn messages containing `needle`. Sibling tests in
84
- * this file run concurrently and emit their own internal-error reports
85
- * through the same console, so a raw call count would be noise.
86
- *
87
- * @param warn - Stubbed console.warn.
88
- *
89
- * @param needle - Substring identifying the breadcrumb family.
90
- *
91
- * @returns Matching messages, in call order.
83
+ Collects the console.warn messages containing `needle`. Sibling tests in
84
+ this file run concurrently and emit their own internal-error reports
85
+ through the same console, so a raw call count would be noise.
86
+
87
+ @param warn - Stubbed console.warn.
88
+
89
+ @param needle - Substring identifying the breadcrumb family.
90
+
91
+ @returns Matching messages, in call order.
92
92
  */
93
93
  function breadcrumbMessages(
94
94
  {
@@ -109,11 +109,11 @@ function breadcrumbMessages(
109
109
  }
110
110
 
111
111
  /**
112
- * Collects the flush-deadline breadcrumbs, see {@link breadcrumbMessages}.
113
- *
114
- * @param warn - Stubbed console.warn.
115
- *
116
- * @returns Flush-deadline breadcrumb messages observed, in call order.
112
+ Collects the flush-deadline breadcrumbs, see {@link breadcrumbMessages}.
113
+
114
+ @param warn - Stubbed console.warn.
115
+
116
+ @returns Flush-deadline breadcrumb messages observed, in call order.
117
117
  */
118
118
  function deadlineBreadcrumbMessages({ warn, }: { readonly warn: RecordedCalls; },): string[] {
119
119
  return breadcrumbMessages({
@@ -123,12 +123,12 @@ function deadlineBreadcrumbMessages({ warn, }: { readonly warn: RecordedCalls; }
123
123
  }
124
124
 
125
125
  /**
126
- * Counts the sink-verification breadcrumbs (a verify that rejected, threw, or
127
- * ran past the verify time limit).
128
- *
129
- * @param warn - Stubbed console.warn.
130
- *
131
- * @returns Number of verification breadcrumbs observed.
126
+ Counts the sink-verification breadcrumbs (a verify that rejected, threw, or
127
+ ran past the verify time limit).
128
+
129
+ @param warn - Stubbed console.warn.
130
+
131
+ @returns Number of verification breadcrumbs observed.
132
132
  */
133
133
  function verifyBreadcrumbs({ warn, }: { readonly warn: RecordedCalls; },): number {
134
134
  return breadcrumbMessages({
@@ -138,11 +138,11 @@ function verifyBreadcrumbs({ warn, }: { readonly warn: RecordedCalls; },): numbe
138
138
  }
139
139
 
140
140
  /**
141
- * Builds a verifier that answers `true` after a delay.
142
- *
143
- * @param delayMs - Milliseconds before the verifier resolves.
144
- *
145
- * @returns Verify function resolving `true` after the delay.
141
+ Builds a verifier that answers `true` after a delay.
142
+
143
+ @param delayMs - Milliseconds before the verifier resolves.
144
+
145
+ @returns Verify function resolving `true` after the delay.
146
146
  */
147
147
  function verifyTrueAfter({ delayMs, }: { readonly delayMs: number; },): Verify {
148
148
  return async function verifyLater(): Promise<boolean> {
@@ -152,20 +152,20 @@ function verifyTrueAfter({ delayMs, }: { readonly delayMs: number; },): Verify {
152
152
  }
153
153
 
154
154
  /**
155
- * Counts the flush-deadline breadcrumbs, see {@link deadlineBreadcrumbMessages}.
156
- *
157
- * @param warn - Stubbed console.warn.
158
- *
159
- * @returns Number of flush-deadline breadcrumbs observed.
155
+ Counts the flush-deadline breadcrumbs, see {@link deadlineBreadcrumbMessages}.
156
+
157
+ @param warn - Stubbed console.warn.
158
+
159
+ @returns Number of flush-deadline breadcrumbs observed.
160
160
  */
161
161
  function deadlineBreadcrumbs({ warn, }: { readonly warn: RecordedCalls; },): number {
162
162
  return deadlineBreadcrumbMessages({ warn, },).length;
163
163
  }
164
164
 
165
165
  /**
166
- * Builds a verified sink whose every write never settles.
167
- *
168
- * @returns Sink standing in for a wedged backend.
166
+ Builds a verified sink whose every write never settles.
167
+
168
+ @returns Sink standing in for a wedged backend.
169
169
  */
170
170
  function wedgedWriteSink(): Sink {
171
171
  return {
@@ -179,8 +179,8 @@ function wedgedWriteSink(): Sink {
179
179
  }
180
180
 
181
181
  /**
182
- * Recording sink plus the array it appends every written record to, so a test
183
- * can assert exactly which records crossed the seam.
182
+ Recording sink plus the array it appends every written record to, so a test
183
+ can assert exactly which records crossed the seam.
184
184
  */
185
185
  type RecordingSink = {
186
186
  readonly records: LogRecord[];
@@ -188,18 +188,18 @@ type RecordingSink = {
188
188
  };
189
189
 
190
190
  /**
191
- * Builds a fake sink that records every record it receives. The seam under
192
- * test is `Sink`, so the whole orchestration (verify, replay, fan-out, flush)
193
- * is exercised through one self-contained adapter with no globals to reset.
194
- *
195
- * @param verify - Backend availability check; defaults to synchronously available.
196
- *
197
- * @param flush - Optional flush hook the logger should drain.
198
- *
199
- * @param writeDelayMs - Milliseconds each write parks before recording, to
200
- * keep a record pending across a `flush()`.
201
- *
202
- * @returns Sink adapter paired with its recorded-record array.
191
+ Builds a fake sink that records every record it receives. The seam under
192
+ test is `Sink`, so the whole orchestration (verify, replay, fan-out, flush)
193
+ is exercised through one self-contained adapter with no globals to reset.
194
+
195
+ @param verify - Backend availability check; defaults to synchronously available.
196
+
197
+ @param flush - Optional flush hook the logger should drain.
198
+
199
+ @param writeDelayMs - Milliseconds each write parks before recording, to
200
+ keep a record pending across a `flush()`.
201
+
202
+ @returns Sink adapter paired with its recorded-record array.
203
203
  */
204
204
  function recordingSink(
205
205
  {
@@ -215,14 +215,14 @@ function recordingSink(
215
215
  } = {},
216
216
  ): RecordingSink {
217
217
  /**
218
- * Records this sink has received, in arrival order.
218
+ Records this sink has received, in arrival order.
219
219
  */
220
220
  const records: LogRecord[] = [];
221
221
 
222
222
  /**
223
- * Records every received record after the optional delay.
224
- *
225
- * @param record - Record handed to the sink.
223
+ Records every received record after the optional delay.
224
+
225
+ @param record - Record handed to the sink.
226
226
  */
227
227
  async function write(record: LogRecord,): Promise<void> {
228
228
  if (writeDelayMs > 0)
@@ -244,11 +244,11 @@ function recordingSink(
244
244
  }
245
245
 
246
246
  /**
247
- * Maps recorded records down to their messages for concise assertions.
248
- *
249
- * @param recording - Recording sink whose messages to read.
250
- *
251
- * @returns Messages in arrival order.
247
+ Maps recorded records down to their messages for concise assertions.
248
+
249
+ @param recording - Recording sink whose messages to read.
250
+
251
+ @returns Messages in arrival order.
252
252
  */
253
253
  function messages({ recording, }: { readonly recording: RecordingSink; },): string[] {
254
254
  return recording.records
@@ -258,38 +258,38 @@ function messages({ recording, }: { readonly recording: RecordingSink; },): stri
258
258
  }
259
259
 
260
260
  /**
261
- * Recording sink whose first write parks on a promise the test settles, so a
262
- * `flush()` can abandon that write at the deadline and the test can then
263
- * settle it late, after the logger has stopped tracking it.
261
+ Recording sink whose first write parks on a promise the test settles, so a
262
+ `flush()` can abandon that write at the deadline and the test can then
263
+ settle it late, after the logger has stopped tracking it.
264
264
  */
265
265
  type ParkedWriteSink = RecordingSink & {
266
266
  readonly settleParked: PromiseWithResolvers<void>;
267
267
  };
268
268
 
269
269
  /**
270
- * Builds a verified sink whose first write waits on `settleParked` and whose
271
- * later writes record immediately.
272
- *
273
- * @returns Sink, its record array, and the resolvers for the parked write.
270
+ Builds a verified sink whose first write waits on `settleParked` and whose
271
+ later writes record immediately.
272
+
273
+ @returns Sink, its record array, and the resolvers for the parked write.
274
274
  */
275
275
  function parkedFirstWriteSink(): ParkedWriteSink {
276
276
  /**
277
- * Records this sink has received, in arrival order.
277
+ Records this sink has received, in arrival order.
278
278
  */
279
279
  const records: LogRecord[] = [];
280
280
  /**
281
- * Resolvers the test uses to settle the parked write.
281
+ Resolvers the test uses to settle the parked write.
282
282
  */
283
283
  const settleParked = Promise.withResolvers<void>();
284
284
  /**
285
- * Whether the parked write has been handed out; only the first write parks.
285
+ Whether the parked write has been handed out; only the first write parks.
286
286
  */
287
287
  const handedOut = { parked: false, };
288
288
 
289
289
  /**
290
- * Parks the first write on `settleParked`, records every later one.
291
- *
292
- * @param record - Record handed to the sink.
290
+ Parks the first write on `settleParked`, records every later one.
291
+
292
+ @param record - Record handed to the sink.
293
293
  */
294
294
  async function write(record: LogRecord,): Promise<void> {
295
295
  if (!handedOut.parked) {
@@ -312,8 +312,8 @@ function parkedFirstWriteSink(): ParkedWriteSink {
312
312
  }
313
313
 
314
314
  /**
315
- * Unhandled-rejection reasons observed while the capture is alive, plus the
316
- * disposer that detaches the listener.
315
+ Unhandled-rejection reasons observed while the capture is alive, plus the
316
+ disposer that detaches the listener.
317
317
  */
318
318
  type UnhandledCapture = {
319
319
  readonly reasons: readonly unknown[];
@@ -321,22 +321,22 @@ type UnhandledCapture = {
321
321
  };
322
322
 
323
323
  /**
324
- * Listens for `unhandledRejection` on the process until disposed. A listener
325
- * also stops Node from treating the rejection as fatal, so the assertion on
326
- * `reasons` is what enforces the property.
327
- *
328
- * @returns Capture whose `reasons` grows with every unhandled rejection.
324
+ Listens for `unhandledRejection` on the process until disposed. A listener
325
+ also stops Node from treating the rejection as fatal, so the assertion on
326
+ `reasons` is what enforces the property.
327
+
328
+ @returns Capture whose `reasons` grows with every unhandled rejection.
329
329
  */
330
330
  function captureUnhandledRejections(): UnhandledCapture {
331
331
  /**
332
- * Reasons observed so far.
332
+ Reasons observed so far.
333
333
  */
334
334
  const reasons: unknown[] = [];
335
335
 
336
336
  /**
337
- * Listener appended to the process.
338
- *
339
- * @param reason - Rejection reason Node reports.
337
+ Listener appended to the process.
338
+
339
+ @param reason - Rejection reason Node reports.
340
340
  */
341
341
  function record(reason: unknown,): void {
342
342
  reasons.push(reason,);
@@ -517,8 +517,8 @@ await describe({
517
517
  name: 'a rejecting write does not retire the sink',
518
518
  fn: async () => {
519
519
  /**
520
- * Write-attempt counter; a retired sink would stop receiving writes,
521
- * so a second attempt proves the rejection left the backend available.
520
+ Write-attempt counter; a retired sink would stop receiving writes,
521
+ so a second attempt proves the rejection left the backend available.
522
522
  */
523
523
  const counters: { attempts: number; } = { attempts: 0, };
524
524
  const flaky: Sink = {
@@ -572,7 +572,7 @@ await describe({
572
572
  name: 'flush runs every available sink flush hook',
573
573
  fn: async () => {
574
574
  /**
575
- * Hook-invocation counter proving `flush()` reached the sink's own hook.
575
+ Hook-invocation counter proving `flush()` reached the sink's own hook.
576
576
  */
577
577
  const counters: { flushes: number; } = { flushes: 0, };
578
578
  const hooked = recordingSink({
@@ -661,8 +661,8 @@ await describe({
661
661
  name: 'a synchronously-throwing write does not retire the sink',
662
662
  fn: async () => {
663
663
  /**
664
- * Write-attempt counter; a retired sink would stop receiving writes, so
665
- * a second attempt proves the synchronous throw left it available.
664
+ Write-attempt counter; a retired sink would stop receiving writes, so
665
+ a second attempt proves the synchronous throw left it available.
666
666
  */
667
667
  const counters: { attempts: number; } = { attempts: 0, };
668
668
  const flaky: Sink = {
@@ -702,8 +702,8 @@ await describe({
702
702
  name: 'does not run the flush hook of a sink that failed verification',
703
703
  fn: async () => {
704
704
  /**
705
- * Flush-hook counter; stays zero because an unavailable sink's hook
706
- * must be skipped by `flushAll`.
705
+ Flush-hook counter; stays zero because an unavailable sink's hook
706
+ must be skipped by `flushAll`.
707
707
  */
708
708
  const counters: { flushes: number; } = { flushes: 0, };
709
709
  const off = recordingSink({
@@ -1150,12 +1150,12 @@ await describe({
1150
1150
  timeout: DEADLINE_TEST_TIMEOUT_MS,
1151
1151
  fn: async () => {
1152
1152
  /**
1153
- * Records logged before the sink verifies: the cap plus a few extra
1154
- * that must push the oldest ones out.
1153
+ Records logged before the sink verifies: the cap plus a few extra
1154
+ that must push the oldest ones out.
1155
1155
  */
1156
1156
  const extra = 3;
1157
1157
  /**
1158
- * Total records in the burst; the last one is index `burstSize - 1`.
1158
+ Total records in the burst; the last one is index `burstSize - 1`.
1159
1159
  */
1160
1160
  const burstSize = STARTUP_BUFFER_CAP + extra;
1161
1161
  const late = recordingSink({ verify: verifyTrueAfter({ delayMs: SLOW_WRITE_MS, },), },);
@@ -0,0 +1,47 @@
1
+ import { createConsoleSink, } from './sink/console.ts';
2
+ import { createIndexedDbSink, } from './sink/indexed-db.ts';
3
+ import { createLocalStorageSink, } from './sink/local-storage.ts';
4
+ import { createSessionStorageSink, } from './sink/session-storage.ts';
5
+
6
+ import type { Sink, } from './types.ts';
7
+
8
+ /**
9
+ Builds the default sink backends the platform-neutral artifact attempts, in
10
+ priority order. Chosen at bundle time: `package.json` maps `#default-sinks`
11
+ to this module under the `default` condition, so every non-Node resolution
12
+ (browsers, Deno, Bun, workers) inlines this list without a runtime
13
+ platform probe. Called on the default logger's first use, never at import,
14
+ so a runtime that forbids timers and I/O in global scope (Cloudflare
15
+ Workers, issue #493) constructs and verifies its sinks inside the handler
16
+ that logs first. Each runtime keeps only the sinks whose `verify` confirms
17
+ platform probe. Each runtime keeps only the sinks whose `verify` confirms
18
+ its backend: {@link createConsoleSink} everywhere,
19
+ {@link createIndexedDbSink} in browsers, {@link createSessionStorageSink}
20
+ wherever web storage round-trips (browsers, Deno),
21
+ {@link createLocalStorageSink} wherever `localStorage` round-trips
22
+ (browsers, Deno). The noop sink is intentionally absent: the console sink
23
+ verifies wherever `console` and `queueMicrotask` exist, so the default
24
+ logger has a backend in every supported runtime, and a custom
25
+ `createLogger` whose sinks all fail verification surfaces the "No logging
26
+ backends available" error instead of silently discarding. The file sink
27
+ is absent because its static `node:fs/promises` import cannot load outside
28
+ Node; it ships through the `./node` subpath and the Node default list
29
+ instead. The OPFS sink is exported from `./browser` but not a default:
30
+ its stream stages writes until a close that a crash never performs, so
31
+ IndexedDB holds the persistent-browser slot; see `DECISIONS.md`.
32
+
33
+ @returns Fresh default sinks in priority order.
34
+
35
+ @example
36
+ ```ts
37
+ const { logger } = createLogger({ sinks: createDefaultSinks() });
38
+ ```
39
+ */
40
+ export function createDefaultSinks(): readonly Sink[] {
41
+ return [
42
+ createConsoleSink(),
43
+ createIndexedDbSink(),
44
+ createSessionStorageSink(),
45
+ createLocalStorageSink(),
46
+ ];
47
+ }
@@ -0,0 +1,43 @@
1
+ import { createConsoleSink, } from './sink/console.ts';
2
+ import { createFileSink, } from './sink/file.ts';
3
+ import { createLocalStorageSink, } from './sink/local-storage.ts';
4
+ import { createSessionStorageSink, } from './sink/session-storage.ts';
5
+
6
+ import type { Sink, } from './types.ts';
7
+
8
+ /**
9
+ Builds the default sink backends the Node artifact attempts, in priority
10
+ order. Chosen at bundle time: `package.json` maps `#default-sinks` to this
11
+ module under the `node` condition, so `logger.ts` inlines this list without
12
+ a runtime platform probe. Called on the default logger's first use, never
13
+ at import, so no sink is constructed in global scope (issue #493). Each
14
+ runtime keeps only the sinks whose `verify`
15
+ confirms its backend: {@link createConsoleSink} everywhere,
16
+ {@link createSessionStorageSink} wherever web storage round-trips (Node
17
+ 22+, Deno), {@link createLocalStorageSink} wherever `localStorage`
18
+ round-trips (Deno, Node launched with `--localstorage-file`), and
19
+ {@link createFileSink} wherever an ancestor `node_modules` exists. The
20
+ noop sink is intentionally absent: the console sink verifies wherever
21
+ `console` and `queueMicrotask` exist, so the default logger has a backend
22
+ in every supported runtime, and a custom `createLogger` whose sinks all
23
+ fail verification surfaces the "No logging backends available" error
24
+ instead of silently discarding. The IndexedDB and OPFS sinks are absent
25
+ because Node exposes neither `indexedDB` nor `navigator.storage`; they
26
+ ship through the `./browser` subpath instead, keeping their probes and
27
+ code out of this artifact.
28
+
29
+ @returns Fresh default sinks in priority order.
30
+
31
+ @example
32
+ ```ts
33
+ const { logger } = createLogger({ sinks: createDefaultSinks() });
34
+ ```
35
+ */
36
+ export function createDefaultSinks(): readonly Sink[] {
37
+ return [
38
+ createConsoleSink(),
39
+ createSessionStorageSink(),
40
+ createLocalStorageSink(),
41
+ createFileSink(),
42
+ ];
43
+ }
@@ -1,32 +1,32 @@
1
1
  /**
2
- * Internal logger error reporting helpers.
3
- *
4
- * Logger internals cannot report failures through the logger itself without
5
- * risking recursion, so these helpers format caught values and write directly
6
- * to the host console.
7
- *
8
- * @module
2
+ Internal logger error reporting helpers.
3
+
4
+ Logger internals cannot report failures through the logger itself without
5
+ risking recursion, so these helpers format caught values and write directly
6
+ to the host console.
7
+
8
+ @module
9
9
  */
10
10
 
11
11
  import { caughtValueText, } from '@monochromatic-dev/module-caught-value/ts';
12
12
 
13
13
  /**
14
- * Reports a logger-internal caught value without going back through logger
15
- * sinks, formatting it via {@link caughtValueText}.
16
- *
17
- * @param context - Human-readable operation that caught the value.
18
- *
19
- * @param error - Caught value to include in the diagnostic.
20
- *
21
- * @mutates error - `caughtValueText` may invoke string-conversion hooks.
22
- *
23
- * @example
24
- * ```ts
25
- * reportLoggerInternalError({
26
- * context: 'console sink verify failed',
27
- * error: new Error('blocked'),
28
- * });
29
- * ```
14
+ Reports a logger-internal caught value without going back through logger
15
+ sinks, formatting it via {@link caughtValueText}.
16
+
17
+ @param context - Human-readable operation that caught the value.
18
+
19
+ @param error - Caught value to include in the diagnostic.
20
+
21
+ @mutates error - `caughtValueText` may invoke string-conversion hooks.
22
+
23
+ @example
24
+ ```ts
25
+ reportLoggerInternalError({
26
+ context: 'console sink verify failed',
27
+ error: new Error('blocked'),
28
+ });
29
+ ```
30
30
  */
31
31
  export function reportLoggerInternalError(
32
32
  {
package/src/index.ts CHANGED
@@ -4,10 +4,7 @@ export {
4
4
  DEFAULT_VERIFY_TIMEOUT_MS,
5
5
  STARTUP_BUFFER_CAP,
6
6
  } from './create-logger.ts';
7
- export {
8
- initPromise,
9
- logger,
10
- } from './logger.ts';
7
+ export { logger, } from './logger.ts';
11
8
  export * as sinks from './sink/index.ts';
12
9
  export { tagged, } from './tagged.ts';
13
10