@logtape/logtape 0.11.0-dev.175 → 0.12.0-dev.181

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 (171) hide show
  1. package/config.test.ts +591 -0
  2. package/config.ts +421 -0
  3. package/context.test.ts +187 -0
  4. package/context.ts +55 -0
  5. package/deno.json +36 -0
  6. package/dist/_virtual/rolldown_runtime.cjs +30 -0
  7. package/dist/config.cjs +247 -0
  8. package/dist/config.d.cts +189 -0
  9. package/dist/config.d.cts.map +1 -0
  10. package/dist/config.d.ts +189 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +241 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/context.cjs +30 -0
  15. package/dist/context.d.cts +39 -0
  16. package/dist/context.d.cts.map +1 -0
  17. package/dist/context.d.ts +39 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +31 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/filter.cjs +32 -0
  22. package/dist/filter.d.cts +37 -0
  23. package/dist/filter.d.cts.map +1 -0
  24. package/{types → dist}/filter.d.ts +12 -6
  25. package/dist/filter.d.ts.map +1 -0
  26. package/dist/filter.js +31 -0
  27. package/dist/filter.js.map +1 -0
  28. package/dist/formatter.cjs +281 -0
  29. package/dist/formatter.d.cts +338 -0
  30. package/dist/formatter.d.cts.map +1 -0
  31. package/dist/formatter.d.ts +338 -0
  32. package/dist/formatter.d.ts.map +1 -0
  33. package/dist/formatter.js +275 -0
  34. package/dist/formatter.js.map +1 -0
  35. package/dist/level.cjs +64 -0
  36. package/dist/level.d.cts +34 -0
  37. package/dist/level.d.cts.map +1 -0
  38. package/{types → dist}/level.d.ts +7 -5
  39. package/dist/level.d.ts.map +1 -0
  40. package/dist/level.js +62 -0
  41. package/dist/level.js.map +1 -0
  42. package/dist/logger.cjs +351 -0
  43. package/dist/logger.d.cts +501 -0
  44. package/dist/logger.d.cts.map +1 -0
  45. package/dist/logger.d.ts +501 -0
  46. package/dist/logger.d.ts.map +1 -0
  47. package/dist/logger.js +351 -0
  48. package/dist/logger.js.map +1 -0
  49. package/dist/mod.cjs +33 -0
  50. package/dist/mod.d.cts +9 -0
  51. package/dist/mod.d.ts +9 -0
  52. package/dist/mod.js +9 -0
  53. package/dist/record.d.cts +50 -0
  54. package/dist/record.d.cts.map +1 -0
  55. package/dist/record.d.ts +50 -0
  56. package/dist/record.d.ts.map +1 -0
  57. package/dist/sink.cjs +95 -0
  58. package/dist/sink.d.cts +112 -0
  59. package/dist/sink.d.cts.map +1 -0
  60. package/{types → dist}/sink.d.ts +49 -45
  61. package/dist/sink.d.ts.map +1 -0
  62. package/dist/sink.js +94 -0
  63. package/dist/sink.js.map +1 -0
  64. package/dist/util.cjs +9 -0
  65. package/dist/util.d.cts +12 -0
  66. package/dist/util.d.cts.map +1 -0
  67. package/dist/util.d.ts +12 -0
  68. package/dist/util.d.ts.map +1 -0
  69. package/dist/util.deno.cjs +16 -0
  70. package/dist/util.deno.d.cts +12 -0
  71. package/dist/util.deno.d.cts.map +1 -0
  72. package/dist/util.deno.d.ts +12 -0
  73. package/dist/util.deno.d.ts.map +1 -0
  74. package/dist/util.deno.js +16 -0
  75. package/dist/util.deno.js.map +1 -0
  76. package/dist/util.js +9 -0
  77. package/dist/util.js.map +1 -0
  78. package/dist/util.node.cjs +10 -0
  79. package/dist/util.node.d.cts +12 -0
  80. package/dist/util.node.d.cts.map +1 -0
  81. package/dist/util.node.d.ts +12 -0
  82. package/dist/util.node.d.ts.map +1 -0
  83. package/dist/util.node.js +10 -0
  84. package/dist/util.node.js.map +1 -0
  85. package/filter.test.ts +70 -0
  86. package/filter.ts +57 -0
  87. package/fixtures.ts +30 -0
  88. package/formatter.test.ts +530 -0
  89. package/formatter.ts +724 -0
  90. package/level.test.ts +47 -0
  91. package/level.ts +67 -0
  92. package/logger.test.ts +823 -0
  93. package/logger.ts +1124 -0
  94. package/mod.ts +54 -0
  95. package/package.json +35 -23
  96. package/record.ts +49 -0
  97. package/sink.test.ts +219 -0
  98. package/sink.ts +167 -0
  99. package/tsdown.config.ts +24 -0
  100. package/util.deno.ts +19 -0
  101. package/util.node.ts +12 -0
  102. package/util.ts +11 -0
  103. package/esm/_dnt.shims.js +0 -57
  104. package/esm/config.js +0 -297
  105. package/esm/context.js +0 -23
  106. package/esm/filter.js +0 -42
  107. package/esm/formatter.js +0 -370
  108. package/esm/level.js +0 -59
  109. package/esm/logger.js +0 -517
  110. package/esm/mod.js +0 -8
  111. package/esm/nodeUtil.cjs +0 -20
  112. package/esm/nodeUtil.js +0 -2
  113. package/esm/package.json +0 -3
  114. package/esm/record.js +0 -1
  115. package/esm/sink.js +0 -96
  116. package/script/_dnt.shims.js +0 -60
  117. package/script/config.js +0 -331
  118. package/script/context.js +0 -26
  119. package/script/filter.js +0 -46
  120. package/script/formatter.js +0 -380
  121. package/script/level.js +0 -64
  122. package/script/logger.js +0 -548
  123. package/script/mod.js +0 -36
  124. package/script/nodeUtil.js +0 -20
  125. package/script/package.json +0 -3
  126. package/script/record.js +0 -2
  127. package/script/sink.js +0 -101
  128. package/types/_dnt.shims.d.ts +0 -2
  129. package/types/_dnt.shims.d.ts.map +0 -1
  130. package/types/_dnt.test_shims.d.ts.map +0 -1
  131. package/types/config.d.ts +0 -183
  132. package/types/config.d.ts.map +0 -1
  133. package/types/config.test.d.ts.map +0 -1
  134. package/types/context.d.ts +0 -35
  135. package/types/context.d.ts.map +0 -1
  136. package/types/context.test.d.ts.map +0 -1
  137. package/types/deps/jsr.io/@std/assert/0.222.1/_constants.d.ts.map +0 -1
  138. package/types/deps/jsr.io/@std/assert/0.222.1/_diff.d.ts.map +0 -1
  139. package/types/deps/jsr.io/@std/assert/0.222.1/_format.d.ts.map +0 -1
  140. package/types/deps/jsr.io/@std/assert/0.222.1/assert.d.ts.map +0 -1
  141. package/types/deps/jsr.io/@std/assert/0.222.1/assert_equals.d.ts.map +0 -1
  142. package/types/deps/jsr.io/@std/assert/0.222.1/assert_false.d.ts.map +0 -1
  143. package/types/deps/jsr.io/@std/assert/0.222.1/assert_greater_or_equal.d.ts.map +0 -1
  144. package/types/deps/jsr.io/@std/assert/0.222.1/assert_is_error.d.ts.map +0 -1
  145. package/types/deps/jsr.io/@std/assert/0.222.1/assert_less_or_equal.d.ts.map +0 -1
  146. package/types/deps/jsr.io/@std/assert/0.222.1/assert_rejects.d.ts.map +0 -1
  147. package/types/deps/jsr.io/@std/assert/0.222.1/assert_strict_equals.d.ts.map +0 -1
  148. package/types/deps/jsr.io/@std/assert/0.222.1/assert_throws.d.ts.map +0 -1
  149. package/types/deps/jsr.io/@std/assert/0.222.1/assertion_error.d.ts.map +0 -1
  150. package/types/deps/jsr.io/@std/assert/0.222.1/equal.d.ts.map +0 -1
  151. package/types/deps/jsr.io/@std/async/0.222.1/delay.d.ts.map +0 -1
  152. package/types/deps/jsr.io/@std/fmt/0.222.1/colors.d.ts.map +0 -1
  153. package/types/filter.d.ts.map +0 -1
  154. package/types/filter.test.d.ts.map +0 -1
  155. package/types/fixtures.d.ts.map +0 -1
  156. package/types/formatter.d.ts +0 -332
  157. package/types/formatter.d.ts.map +0 -1
  158. package/types/formatter.test.d.ts.map +0 -1
  159. package/types/level.d.ts.map +0 -1
  160. package/types/level.test.d.ts.map +0 -1
  161. package/types/logger.d.ts +0 -573
  162. package/types/logger.d.ts.map +0 -1
  163. package/types/logger.test.d.ts.map +0 -1
  164. package/types/mod.d.ts +0 -9
  165. package/types/mod.d.ts.map +0 -1
  166. package/types/nodeUtil.d.ts +0 -12
  167. package/types/nodeUtil.d.ts.map +0 -1
  168. package/types/record.d.ts +0 -44
  169. package/types/record.d.ts.map +0 -1
  170. package/types/sink.d.ts.map +0 -1
  171. package/types/sink.test.d.ts.map +0 -1
package/config.test.ts ADDED
@@ -0,0 +1,591 @@
1
+ import { suite } from "@hongminhee/suite";
2
+ import { assertEquals } from "@std/assert/equals";
3
+ import { assertRejects } from "@std/assert/rejects";
4
+ import { assertStrictEquals } from "@std/assert/strict-equals";
5
+ import { assertThrows } from "@std/assert/throws";
6
+ import {
7
+ type Config,
8
+ ConfigError,
9
+ configure,
10
+ configureSync,
11
+ getConfig,
12
+ reset,
13
+ resetSync,
14
+ } from "./config.ts";
15
+ import type { Filter } from "./filter.ts";
16
+ import { getLogger, LoggerImpl } from "./logger.ts";
17
+ import type { LogRecord } from "./record.ts";
18
+ import type { Sink } from "./sink.ts";
19
+
20
+ const test = suite(import.meta);
21
+
22
+ test("configure()", async () => {
23
+ let disposed = 0;
24
+
25
+ try {
26
+ const aLogs: LogRecord[] = [];
27
+ const a: Sink & AsyncDisposable = (record) => aLogs.push(record);
28
+ a[Symbol.asyncDispose] = () => {
29
+ ++disposed;
30
+ return Promise.resolve();
31
+ };
32
+ const bLogs: LogRecord[] = [];
33
+ const b: Sink & Disposable = (record) => bLogs.push(record);
34
+ b[Symbol.dispose] = () => ++disposed;
35
+ const cLogs: LogRecord[] = [];
36
+ const c: Sink = cLogs.push.bind(cLogs);
37
+ const x: Filter & AsyncDisposable = () => true;
38
+ x[Symbol.asyncDispose] = () => {
39
+ ++disposed;
40
+ return Promise.resolve();
41
+ };
42
+ const y: Filter & Disposable = () => true;
43
+ y[Symbol.dispose] = () => ++disposed;
44
+ const config: Config<string, string> = {
45
+ sinks: { a, b, c },
46
+ filters: { x, y, debug: "debug" },
47
+ loggers: [
48
+ {
49
+ category: "my-app",
50
+ sinks: ["a"],
51
+ filters: ["x"],
52
+ },
53
+ {
54
+ category: ["my-app", "foo"],
55
+ sinks: ["b"],
56
+ parentSinks: "override",
57
+ filters: ["y"],
58
+ },
59
+ {
60
+ category: ["my-app", "bar"],
61
+ sinks: ["c"],
62
+ filters: ["debug"],
63
+ level: "info", // deprecated
64
+ lowestLevel: "info",
65
+ },
66
+ ],
67
+ };
68
+ await configure(config);
69
+
70
+ const logger = LoggerImpl.getLogger("my-app");
71
+ assertEquals(logger.sinks, [a]);
72
+ assertEquals(logger.filters, [x]);
73
+ assertEquals(logger.lowestLevel, "debug");
74
+ const foo = LoggerImpl.getLogger(["my-app", "foo"]);
75
+ assertEquals(foo.sinks, [b]);
76
+ assertEquals(foo.filters, [y]);
77
+ assertEquals(foo.lowestLevel, "debug");
78
+ const bar = LoggerImpl.getLogger(["my-app", "bar"]);
79
+ assertEquals(bar.sinks, [c]);
80
+ assertEquals(bar.lowestLevel, "info");
81
+ bar.debug("ignored");
82
+ assertEquals(aLogs, []);
83
+ assertEquals(bLogs, []);
84
+ assertEquals(cLogs, []);
85
+ foo.warn("logged");
86
+ assertEquals(aLogs, []);
87
+ assertEquals(bLogs, [
88
+ {
89
+ level: "warning",
90
+ category: ["my-app", "foo"],
91
+ message: ["logged"],
92
+ rawMessage: "logged",
93
+ properties: {},
94
+ timestamp: bLogs[0].timestamp,
95
+ },
96
+ ]);
97
+ assertEquals(cLogs, []);
98
+ bar.info("logged");
99
+ assertEquals(aLogs, [
100
+ {
101
+ level: "info",
102
+ category: ["my-app", "bar"],
103
+ message: ["logged"],
104
+ rawMessage: "logged",
105
+ properties: {},
106
+ timestamp: cLogs[0].timestamp,
107
+ },
108
+ ]);
109
+ assertEquals(bLogs, [
110
+ {
111
+ level: "warning",
112
+ category: ["my-app", "foo"],
113
+ message: ["logged"],
114
+ rawMessage: "logged",
115
+ properties: {},
116
+ timestamp: bLogs[0].timestamp,
117
+ },
118
+ ]);
119
+ assertEquals(cLogs, [
120
+ {
121
+ level: "info",
122
+ category: ["my-app", "bar"],
123
+ message: ["logged"],
124
+ rawMessage: "logged",
125
+ properties: {},
126
+ timestamp: cLogs[0].timestamp,
127
+ },
128
+ ]);
129
+ assertStrictEquals(getConfig(), config);
130
+
131
+ // reconfigure
132
+ await assertRejects(
133
+ () =>
134
+ configure({
135
+ sinks: {},
136
+ loggers: [{ category: "my-app" }],
137
+ }),
138
+ ConfigError,
139
+ "Already configured",
140
+ );
141
+ assertEquals(disposed, 0);
142
+
143
+ // No exception if reset is true:
144
+ const config2 = {
145
+ sinks: {},
146
+ loggers: [{ category: "my-app" }],
147
+ reset: true,
148
+ };
149
+ await configure(config2);
150
+ assertEquals(disposed, 4);
151
+ assertStrictEquals(getConfig(), config2);
152
+ } finally {
153
+ await reset();
154
+ assertStrictEquals(getConfig(), null);
155
+ }
156
+
157
+ try { // lowestLevel
158
+ const a: LogRecord[] = [];
159
+ const b: LogRecord[] = [];
160
+ const c: LogRecord[] = [];
161
+ await configure({
162
+ sinks: {
163
+ a: a.push.bind(a),
164
+ b: b.push.bind(b),
165
+ c: c.push.bind(c),
166
+ },
167
+ loggers: [
168
+ { category: "foo", sinks: ["a"], lowestLevel: "info" },
169
+ { category: ["foo", "bar"], sinks: ["b"], lowestLevel: "warning" },
170
+ { category: ["foo", "baz"], sinks: ["c"], lowestLevel: "debug" },
171
+ { category: ["logtape", "meta"], sinks: [] },
172
+ ],
173
+ });
174
+
175
+ getLogger(["foo", "bar"]).warn("test");
176
+ assertEquals(a.length, 1);
177
+ assertEquals(b.length, 1);
178
+
179
+ while (a.length > 0) a.pop();
180
+ while (b.length > 0) b.pop();
181
+
182
+ getLogger(["foo", "baz"]).debug("test");
183
+ assertEquals(a.length, 0);
184
+ assertEquals(c.length, 1);
185
+
186
+ while (a.length > 0) a.pop();
187
+ while (c.length > 0) c.pop();
188
+ } finally {
189
+ await reset();
190
+ assertStrictEquals(getConfig(), null);
191
+ }
192
+
193
+ { // misconfiguration
194
+ await assertRejects(
195
+ () =>
196
+ configure({
197
+ // deno-lint-ignore no-explicit-any
198
+ sinks: {} as any,
199
+ loggers: [
200
+ {
201
+ category: "my-app",
202
+ sinks: ["invalid"],
203
+ },
204
+ ],
205
+ reset: true,
206
+ }),
207
+ ConfigError,
208
+ "Sink not found: invalid",
209
+ );
210
+ assertStrictEquals(getConfig(), null);
211
+
212
+ await assertRejects(
213
+ () =>
214
+ configure({
215
+ sinks: {},
216
+ // deno-lint-ignore no-explicit-any
217
+ filters: {} as any,
218
+ loggers: [
219
+ {
220
+ category: "my-app",
221
+ filters: ["invalid"],
222
+ },
223
+ ],
224
+ reset: true,
225
+ }),
226
+ ConfigError,
227
+ "Filter not found: invalid",
228
+ );
229
+ assertStrictEquals(getConfig(), null);
230
+ }
231
+
232
+ { // duplicate logger categories
233
+ await assertRejects(
234
+ () =>
235
+ configure({
236
+ sinks: {},
237
+ loggers: [
238
+ {
239
+ category: "my-app",
240
+ lowestLevel: "info",
241
+ },
242
+ {
243
+ category: ["my-app"],
244
+ lowestLevel: "warning",
245
+ },
246
+ ],
247
+ reset: true,
248
+ }),
249
+ ConfigError,
250
+ 'Duplicate logger configuration for category: ["my-app"]',
251
+ );
252
+ assertStrictEquals(getConfig(), null);
253
+
254
+ await assertRejects(
255
+ () =>
256
+ configure({
257
+ sinks: {},
258
+ loggers: [
259
+ {
260
+ category: ["my-app", "service"],
261
+ lowestLevel: "info",
262
+ },
263
+ {
264
+ category: ["my-app", "service"],
265
+ lowestLevel: "warning",
266
+ },
267
+ ],
268
+ reset: true,
269
+ }),
270
+ ConfigError,
271
+ 'Duplicate logger configuration for category: ["my-app","service"]',
272
+ );
273
+ assertStrictEquals(getConfig(), null);
274
+ }
275
+
276
+ const metaCategories = [[], ["logtape"], ["logtape", "meta"]];
277
+ for (const metaCategory of metaCategories) {
278
+ try { // meta configuration
279
+ const config = {
280
+ sinks: {},
281
+ loggers: [
282
+ {
283
+ category: metaCategory,
284
+ sinks: [],
285
+ filters: [],
286
+ },
287
+ ],
288
+ };
289
+ await configure(config);
290
+
291
+ assertEquals(LoggerImpl.getLogger(["logger", "meta"]).sinks, []);
292
+ assertStrictEquals(getConfig(), config);
293
+ } finally {
294
+ await reset();
295
+ assertStrictEquals(getConfig(), null);
296
+ }
297
+ }
298
+ });
299
+
300
+ test("configureSync()", async () => {
301
+ let disposed = 0;
302
+
303
+ try {
304
+ const bLogs: LogRecord[] = [];
305
+ const b: Sink & Disposable = (record) => bLogs.push(record);
306
+ b[Symbol.dispose] = () => ++disposed;
307
+ const cLogs: LogRecord[] = [];
308
+ const c: Sink = cLogs.push.bind(cLogs);
309
+ const y: Filter & Disposable = () => true;
310
+ y[Symbol.dispose] = () => ++disposed;
311
+ const config: Config<string, string> = {
312
+ sinks: { b, c },
313
+ filters: { y, debug: "debug" },
314
+ loggers: [
315
+ {
316
+ category: ["my-app", "foo"],
317
+ sinks: ["b"],
318
+ parentSinks: "override",
319
+ filters: ["y"],
320
+ },
321
+ {
322
+ category: ["my-app", "bar"],
323
+ sinks: ["c"],
324
+ filters: ["debug"],
325
+ level: "info", // deprecated
326
+ lowestLevel: "info",
327
+ },
328
+ ],
329
+ };
330
+ configureSync(config);
331
+
332
+ const foo = LoggerImpl.getLogger(["my-app", "foo"]);
333
+ assertEquals(foo.sinks, [b]);
334
+ assertEquals(foo.filters, [y]);
335
+ assertEquals(foo.lowestLevel, "debug");
336
+ const bar = LoggerImpl.getLogger(["my-app", "bar"]);
337
+ assertEquals(bar.sinks, [c]);
338
+ assertEquals(bar.lowestLevel, "info");
339
+ bar.debug("ignored");
340
+ assertEquals(bLogs, []);
341
+ assertEquals(cLogs, []);
342
+ foo.warn("logged");
343
+ assertEquals(bLogs, [
344
+ {
345
+ level: "warning",
346
+ category: ["my-app", "foo"],
347
+ message: ["logged"],
348
+ rawMessage: "logged",
349
+ properties: {},
350
+ timestamp: bLogs[0].timestamp,
351
+ },
352
+ ]);
353
+ assertEquals(cLogs, []);
354
+ bar.info("logged");
355
+ assertEquals(bLogs, [
356
+ {
357
+ level: "warning",
358
+ category: ["my-app", "foo"],
359
+ message: ["logged"],
360
+ rawMessage: "logged",
361
+ properties: {},
362
+ timestamp: bLogs[0].timestamp,
363
+ },
364
+ ]);
365
+ assertEquals(cLogs, [
366
+ {
367
+ level: "info",
368
+ category: ["my-app", "bar"],
369
+ message: ["logged"],
370
+ rawMessage: "logged",
371
+ properties: {},
372
+ timestamp: cLogs[0].timestamp,
373
+ },
374
+ ]);
375
+ assertStrictEquals(getConfig(), config);
376
+
377
+ // reconfigure
378
+ assertThrows(
379
+ () =>
380
+ configureSync({
381
+ sinks: {},
382
+ loggers: [{ category: "my-app" }],
383
+ }),
384
+ ConfigError,
385
+ "Already configured",
386
+ );
387
+ assertEquals(disposed, 0);
388
+
389
+ // No exception if reset is true:
390
+ const config2 = {
391
+ sinks: {},
392
+ loggers: [{ category: "my-app" }],
393
+ reset: true,
394
+ };
395
+ configureSync(config2);
396
+ assertEquals(disposed, 2);
397
+ assertStrictEquals(getConfig(), config2);
398
+ } finally {
399
+ resetSync();
400
+ assertStrictEquals(getConfig(), null);
401
+ }
402
+
403
+ { // misconfiguration
404
+ assertThrows(
405
+ () =>
406
+ configureSync({
407
+ // deno-lint-ignore no-explicit-any
408
+ sinks: {} as any,
409
+ loggers: [
410
+ {
411
+ category: "my-app",
412
+ sinks: ["invalid"],
413
+ },
414
+ ],
415
+ reset: true,
416
+ }),
417
+ ConfigError,
418
+ "Sink not found: invalid",
419
+ );
420
+ assertStrictEquals(getConfig(), null);
421
+
422
+ assertThrows(
423
+ () =>
424
+ configureSync({
425
+ sinks: {},
426
+ // deno-lint-ignore no-explicit-any
427
+ filters: {} as any,
428
+ loggers: [
429
+ {
430
+ category: "my-app",
431
+ filters: ["invalid"],
432
+ },
433
+ ],
434
+ reset: true,
435
+ }),
436
+ ConfigError,
437
+ "Filter not found: invalid",
438
+ );
439
+ assertStrictEquals(getConfig(), null);
440
+ }
441
+
442
+ { // duplicate logger categories
443
+ assertThrows(
444
+ () =>
445
+ configureSync({
446
+ sinks: {},
447
+ loggers: [
448
+ {
449
+ category: ["my-app"],
450
+ lowestLevel: "info",
451
+ },
452
+ {
453
+ category: "my-app",
454
+ lowestLevel: "warning",
455
+ },
456
+ ],
457
+ reset: true,
458
+ }),
459
+ ConfigError,
460
+ 'Duplicate logger configuration for category: ["my-app"]',
461
+ );
462
+ assertStrictEquals(getConfig(), null);
463
+
464
+ assertThrows(
465
+ () =>
466
+ configureSync({
467
+ sinks: {},
468
+ loggers: [
469
+ {
470
+ category: ["my-app", "service"],
471
+ lowestLevel: "info",
472
+ },
473
+ {
474
+ category: ["my-app", "service"],
475
+ lowestLevel: "warning",
476
+ },
477
+ ],
478
+ reset: true,
479
+ }),
480
+ ConfigError,
481
+ 'Duplicate logger configuration for category: ["my-app","service"]',
482
+ );
483
+ assertStrictEquals(getConfig(), null);
484
+ }
485
+
486
+ const metaCategories = [[], ["logtape"], ["logtape", "meta"]];
487
+ for (const metaCategory of metaCategories) {
488
+ try { // meta configuration
489
+ const config = {
490
+ sinks: {},
491
+ loggers: [
492
+ {
493
+ category: metaCategory,
494
+ sinks: [],
495
+ filters: [],
496
+ },
497
+ ],
498
+ };
499
+ configureSync(config);
500
+
501
+ assertEquals(LoggerImpl.getLogger(["logger", "meta"]).sinks, []);
502
+ assertStrictEquals(getConfig(), config);
503
+ } finally {
504
+ resetSync();
505
+ assertStrictEquals(getConfig(), null);
506
+ }
507
+ }
508
+
509
+ { // no async sinks
510
+ const aLogs: LogRecord[] = [];
511
+ const a: Sink & AsyncDisposable = (record) => aLogs.push(record);
512
+ a[Symbol.asyncDispose] = () => {
513
+ return Promise.resolve();
514
+ };
515
+ const config: Config<string, string> = {
516
+ sinks: { a },
517
+ loggers: [
518
+ {
519
+ category: "my-app",
520
+ sinks: ["a"],
521
+ },
522
+ ],
523
+ };
524
+
525
+ assertThrows(
526
+ () => configureSync(config),
527
+ ConfigError,
528
+ "Async disposables cannot be used with configureSync()",
529
+ );
530
+ assertStrictEquals(getConfig(), null);
531
+ }
532
+
533
+ { // no async filters
534
+ const aLogs: LogRecord[] = [];
535
+ const a: Sink & Disposable = (record) => aLogs.push(record);
536
+ a[Symbol.dispose] = () => ++disposed;
537
+ const x: Filter & AsyncDisposable = () => true;
538
+ x[Symbol.asyncDispose] = () => {
539
+ ++disposed;
540
+ return Promise.resolve();
541
+ };
542
+ const config: Config<string, string> = {
543
+ sinks: { a },
544
+ filters: { x },
545
+ loggers: [
546
+ {
547
+ category: "my-app",
548
+ sinks: ["a"],
549
+ filters: ["x"],
550
+ },
551
+ ],
552
+ };
553
+
554
+ assertThrows(
555
+ () => configureSync(config),
556
+ ConfigError,
557
+ "Async disposables cannot be used with configureSync()",
558
+ );
559
+ assertStrictEquals(getConfig(), null);
560
+ }
561
+
562
+ try { // cannot reset async disposables
563
+ const aLogs: LogRecord[] = [];
564
+ const a: Sink & AsyncDisposable = (record) => aLogs.push(record);
565
+ a[Symbol.asyncDispose] = () => {
566
+ ++disposed;
567
+ return Promise.resolve();
568
+ };
569
+ await configure({
570
+ sinks: { a },
571
+ loggers: [{ category: "my-app", sinks: ["a"] }],
572
+ });
573
+ assertThrows(
574
+ () =>
575
+ configureSync({
576
+ sinks: {
577
+ a(record) {
578
+ aLogs.push(record);
579
+ },
580
+ },
581
+ loggers: [{ category: "my-app", sinks: ["a"] }],
582
+ reset: true,
583
+ }),
584
+ ConfigError,
585
+ "Previously configured async disposables are still active",
586
+ );
587
+ } finally {
588
+ await reset();
589
+ assertStrictEquals(getConfig(), null);
590
+ }
591
+ });