@logtape/logtape 2.3.0-dev.791 → 2.3.0-dev.793

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/dist/mod.cjs CHANGED
@@ -38,5 +38,7 @@ exports.reset = require_config.reset;
38
38
  exports.resetSync = require_config.resetSync;
39
39
  exports.toFilter = require_filter.toFilter;
40
40
  exports.withCategoryPrefix = require_context.withCategoryPrefix;
41
+ exports.withConfig = require_config.withConfig;
42
+ exports.withConfigSync = require_config.withConfigSync;
41
43
  exports.withContext = require_context.withContext;
42
44
  exports.withFilter = require_sink.withFilter;
package/dist/mod.d.cts CHANGED
@@ -4,6 +4,6 @@ import { LogRecord } from "./record.cjs";
4
4
  import { Filter, FilterLike, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, getLevelFilter, getThrottlingFilter, toFilter } from "./filter.cjs";
5
5
  import { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, ConsoleFormatter, FormattedValues, JsonLinesFormatterOptions, LogfmtFormatterOptions, TextFormatter, TextFormatterOptions, ansiColorFormatter, defaultConsoleFormatter, defaultTextFormatter, getAnsiColorFormatter, getJsonLinesFormatter, getLogfmtFormatter, getTextFormatter, jsonLinesFormatter, logfmtFormatter } from "./formatter.cjs";
6
6
  import { AsyncSink, ConsoleSinkOptions, FingersCrossedOptions, Sink, StreamSinkOptions, fingersCrossed, fromAsyncSink, getConsoleSink, getStreamSink, withFilter } from "./sink.cjs";
7
- import { Config, ConfigError, LoggerConfig, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync } from "./config.cjs";
7
+ import { Config, ConfigError, LoggerConfig, ScopedConfig, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync, withConfig, withConfigSync } from "./config.cjs";
8
8
  import { Lazy, LogMethod, Logger, getLogger, isLazy, lazy } from "./logger.cjs";
9
- export { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, AsyncSink, Config, ConfigError, ConsoleFormatter, ConsoleSinkOptions, ContextLocalStorage, Filter, FilterLike, FingersCrossedOptions, FormattedValues, JsonLinesFormatterOptions, Lazy, LogLevel, LogMethod, LogRecord, LogfmtFormatterOptions, Logger, LoggerConfig, Sink, StreamSinkOptions, TextFormatter, TextFormatterOptions, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withContext, withFilter };
9
+ export { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, AsyncSink, Config, ConfigError, ConsoleFormatter, ConsoleSinkOptions, ContextLocalStorage, Filter, FilterLike, FingersCrossedOptions, FormattedValues, JsonLinesFormatterOptions, Lazy, LogLevel, LogMethod, LogRecord, LogfmtFormatterOptions, Logger, LoggerConfig, ScopedConfig, Sink, StreamSinkOptions, TextFormatter, TextFormatterOptions, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withConfig, withConfigSync, withContext, withFilter };
package/dist/mod.d.ts CHANGED
@@ -4,6 +4,6 @@ import { LogRecord } from "./record.js";
4
4
  import { Filter, FilterLike, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, getLevelFilter, getThrottlingFilter, toFilter } from "./filter.js";
5
5
  import { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, ConsoleFormatter, FormattedValues, JsonLinesFormatterOptions, LogfmtFormatterOptions, TextFormatter, TextFormatterOptions, ansiColorFormatter, defaultConsoleFormatter, defaultTextFormatter, getAnsiColorFormatter, getJsonLinesFormatter, getLogfmtFormatter, getTextFormatter, jsonLinesFormatter, logfmtFormatter } from "./formatter.js";
6
6
  import { AsyncSink, ConsoleSinkOptions, FingersCrossedOptions, Sink, StreamSinkOptions, fingersCrossed, fromAsyncSink, getConsoleSink, getStreamSink, withFilter } from "./sink.js";
7
- import { Config, ConfigError, LoggerConfig, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync } from "./config.js";
7
+ import { Config, ConfigError, LoggerConfig, ScopedConfig, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync, withConfig, withConfigSync } from "./config.js";
8
8
  import { Lazy, LogMethod, Logger, getLogger, isLazy, lazy } from "./logger.js";
9
- export { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, AsyncSink, Config, ConfigError, ConsoleFormatter, ConsoleSinkOptions, ContextLocalStorage, Filter, FilterLike, FingersCrossedOptions, FormattedValues, JsonLinesFormatterOptions, Lazy, LogLevel, LogMethod, LogRecord, LogfmtFormatterOptions, Logger, LoggerConfig, Sink, StreamSinkOptions, TextFormatter, TextFormatterOptions, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withContext, withFilter };
9
+ export { AnsiColor, AnsiColorFormatterOptions, AnsiStyle, AsyncSink, Config, ConfigError, ConsoleFormatter, ConsoleSinkOptions, ContextLocalStorage, Filter, FilterLike, FingersCrossedOptions, FormattedValues, JsonLinesFormatterOptions, Lazy, LogLevel, LogMethod, LogRecord, LogfmtFormatterOptions, Logger, LoggerConfig, ScopedConfig, Sink, StreamSinkOptions, TextFormatter, TextFormatterOptions, ThrottlingFilterOptions, ThrottlingFilterSummary, ThrottlingFilterSummaryOptions, ThrottlingSummaryLogger, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withConfig, withConfigSync, withContext, withFilter };
package/dist/mod.js CHANGED
@@ -4,6 +4,6 @@ import { compareLogLevel, getLogLevels, isLogLevel, parseLogLevel } from "./leve
4
4
  import { getLogger, isLazy, lazy } from "./logger.js";
5
5
  import { ansiColorFormatter, defaultConsoleFormatter, defaultTextFormatter, getAnsiColorFormatter, getJsonLinesFormatter, getLogfmtFormatter, getTextFormatter, jsonLinesFormatter, logfmtFormatter } from "./formatter.js";
6
6
  import { fingersCrossed, fromAsyncSink, getConsoleSink, getStreamSink, withFilter } from "./sink.js";
7
- import { ConfigError, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync } from "./config.js";
7
+ import { ConfigError, configure, configureSync, dispose, disposeSync, getConfig, reset, resetSync, withConfig, withConfigSync } from "./config.js";
8
8
 
9
- export { ConfigError, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withContext, withFilter };
9
+ export { ConfigError, ansiColorFormatter, compareLogLevel, configure, configureSync, defaultConsoleFormatter, defaultTextFormatter, dispose, disposeSync, fingersCrossed, fromAsyncSink, getAnsiColorFormatter, getConfig, getConsoleSink, getJsonLinesFormatter, getLevelFilter, getLogLevels, getLogfmtFormatter, getLogger, getStreamSink, getTextFormatter, getThrottlingFilter, isLazy, isLogLevel, jsonLinesFormatter, lazy, logfmtFormatter, parseLogLevel, reset, resetSync, toFilter, withCategoryPrefix, withConfig, withConfigSync, withContext, withFilter };
@@ -0,0 +1,227 @@
1
+ const require_filter = require('./filter.cjs');
2
+ const require_level = require('./level.cjs');
3
+
4
+ //#region src/scoped-config.ts
5
+ const scopedConfigSymbol = Symbol.for("logtape.scopedConfig");
6
+ const defaultScopedLogger = {
7
+ filters: [],
8
+ lowestLevel: "trace",
9
+ parentSinks: "inherit",
10
+ sinks: []
11
+ };
12
+ function compileScopedConfig(config, allowAsync, createError) {
13
+ const nodes = /* @__PURE__ */ new Map();
14
+ const configuredCategories = /* @__PURE__ */ new Set();
15
+ for (const logger of config.loggers) {
16
+ const category = normalizeCategory(logger.category);
17
+ const key = categoryKey(category);
18
+ if (configuredCategories.has(key)) throw createError(`Duplicate logger configuration for category: ${key}. Each category can only be configured once.`);
19
+ configuredCategories.add(key);
20
+ const sinks = [];
21
+ for (const sinkId of logger.sinks ?? []) {
22
+ const sink = config.sinks[sinkId];
23
+ if (!sink) throw createError(`Sink not found: ${sinkId}.`);
24
+ sinks.push(sink);
25
+ }
26
+ const filters = [];
27
+ for (const filterId of logger.filters ?? []) {
28
+ const filter = config.filters?.[filterId];
29
+ if (filter === void 0) throw createError(`Filter not found: ${filterId}.`);
30
+ filters.push(require_filter.toFilter(filter));
31
+ }
32
+ nodes.set(key, {
33
+ filters,
34
+ lowestLevel: logger.lowestLevel === void 0 ? "trace" : logger.lowestLevel,
35
+ parentSinks: logger.parentSinks ?? "inherit",
36
+ sinks
37
+ });
38
+ }
39
+ const syncFilters = /* @__PURE__ */ new Set();
40
+ const asyncFilters = /* @__PURE__ */ new Set();
41
+ const syncSinks = /* @__PURE__ */ new Set();
42
+ const asyncSinks = /* @__PURE__ */ new Set();
43
+ for (const sink of Object.values(config.sinks)) {
44
+ if (Symbol.asyncDispose in sink) {
45
+ if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
46
+ asyncSinks.add(sink);
47
+ }
48
+ if (Symbol.dispose in sink) syncSinks.add(sink);
49
+ }
50
+ for (const filter of Object.values(config.filters ?? {})) {
51
+ if (filter == null || typeof filter === "string") continue;
52
+ if (Symbol.asyncDispose in filter) {
53
+ if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
54
+ asyncFilters.add(filter);
55
+ asyncSinks.delete(filter);
56
+ }
57
+ if (Symbol.dispose in filter) {
58
+ syncFilters.add(filter);
59
+ syncSinks.delete(filter);
60
+ }
61
+ }
62
+ return {
63
+ asyncFilters,
64
+ asyncSinks,
65
+ disposed: false,
66
+ nodes,
67
+ parent: void 0,
68
+ syncFilters,
69
+ syncSinks
70
+ };
71
+ }
72
+ function getCurrentScopedConfig(contextLocalStorage) {
73
+ const store = contextLocalStorage?.getStore();
74
+ const scopedConfig = store?.[scopedConfigSymbol];
75
+ return isCompiledScopedConfig(scopedConfig) ? getActiveScopedConfig(scopedConfig) : void 0;
76
+ }
77
+ function runWithScopedConfig(contextLocalStorage, scopedConfig, callback) {
78
+ const parentStore = contextLocalStorage.getStore() ?? {};
79
+ scopedConfig.parent = getCurrentScopedConfig(contextLocalStorage);
80
+ return contextLocalStorage.run({
81
+ ...parentStore,
82
+ [scopedConfigSymbol]: scopedConfig
83
+ }, callback);
84
+ }
85
+ function scopedConfigHasSink(scopedConfig, category, level) {
86
+ return getScopedSinkDispatchPlan(scopedConfig, category, level).kind !== "none";
87
+ }
88
+ function emitWithScopedConfig(scopedConfig, record, bypassSinks, emitToSink) {
89
+ const plan = getScopedSinkDispatchPlan(scopedConfig, record.category, record.level);
90
+ if (plan.kind === "none") return;
91
+ if (!filterScopedRecord(scopedConfig, record.category, record)) return;
92
+ if (plan.kind === "one") {
93
+ if (!bypassSinks?.has(plan.sink)) emitToSink(plan.sink, bypassSinks);
94
+ return;
95
+ }
96
+ for (const sink of plan.sinks) {
97
+ if (bypassSinks?.has(sink)) continue;
98
+ emitToSink(sink, bypassSinks);
99
+ }
100
+ }
101
+ async function disposeScopedConfig(scopedConfig) {
102
+ scopedConfig.disposed = true;
103
+ const errors = [];
104
+ try {
105
+ disposeSyncDisposables(scopedConfig.syncFilters);
106
+ } catch (error) {
107
+ errors.push(error);
108
+ }
109
+ try {
110
+ await disposeAsyncDisposables(scopedConfig.asyncFilters);
111
+ } catch (error) {
112
+ errors.push(error);
113
+ }
114
+ try {
115
+ disposeSyncDisposables(scopedConfig.syncSinks);
116
+ } catch (error) {
117
+ errors.push(error);
118
+ }
119
+ try {
120
+ await disposeAsyncDisposables(scopedConfig.asyncSinks);
121
+ } catch (error) {
122
+ errors.push(error);
123
+ }
124
+ throwDisposeErrors(errors);
125
+ }
126
+ function disposeScopedConfigSync(scopedConfig) {
127
+ scopedConfig.disposed = true;
128
+ const errors = [];
129
+ try {
130
+ disposeSyncDisposables(scopedConfig.syncFilters);
131
+ } catch (error) {
132
+ errors.push(error);
133
+ }
134
+ try {
135
+ disposeSyncDisposables(scopedConfig.syncSinks);
136
+ } catch (error) {
137
+ errors.push(error);
138
+ }
139
+ throwDisposeErrors(errors);
140
+ }
141
+ function throwCombinedErrors(primary, secondary) {
142
+ throw new AggregateError(flattenErrors(primary, secondary), "Multiple errors occurred while running LogTape scoped configuration.");
143
+ }
144
+ function isCompiledScopedConfig(value) {
145
+ return value != null && typeof value === "object" && "nodes" in value;
146
+ }
147
+ function getActiveScopedConfig(scopedConfig) {
148
+ let activeConfig = scopedConfig;
149
+ while (activeConfig?.disposed) activeConfig = activeConfig.parent;
150
+ return activeConfig;
151
+ }
152
+ function normalizeCategory(category) {
153
+ return typeof category === "string" ? [category] : [...category];
154
+ }
155
+ function categoryKey(category) {
156
+ return JSON.stringify(category);
157
+ }
158
+ function getScopedSinkDispatchPlan(scopedConfig, category, level) {
159
+ return getScopedSinkDispatchPlanForPrefix(scopedConfig, category, category.length, level);
160
+ }
161
+ function getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length, level) {
162
+ const prefix = category.slice(0, length);
163
+ const logger = scopedConfig.nodes.get(categoryKey(prefix)) ?? defaultScopedLogger;
164
+ if (logger.lowestLevel === null || require_level.compareLogLevel(level, logger.lowestLevel) < 0) return { kind: "none" };
165
+ const parentPlan = length > 0 && logger.parentSinks === "inherit" ? getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length - 1, level) : { kind: "none" };
166
+ let firstSink;
167
+ let sinks;
168
+ const appendSink = (sink) => {
169
+ if (sinks != null) sinks.push(sink);
170
+ else if (firstSink == null) firstSink = sink;
171
+ else sinks = [firstSink, sink];
172
+ };
173
+ if (parentPlan.kind === "one") appendSink(parentPlan.sink);
174
+ else if (parentPlan.kind === "many") for (const sink of parentPlan.sinks) appendSink(sink);
175
+ for (const sink of logger.sinks) appendSink(sink);
176
+ if (sinks != null) return {
177
+ kind: "many",
178
+ sinks
179
+ };
180
+ if (firstSink != null) return {
181
+ kind: "one",
182
+ sink: firstSink
183
+ };
184
+ return { kind: "none" };
185
+ }
186
+ function filterScopedRecord(scopedConfig, category, record) {
187
+ for (let length = category.length; length >= 0; length--) {
188
+ const logger = scopedConfig.nodes.get(categoryKey(category.slice(0, length)));
189
+ if (logger == null || logger.filters.length < 1) continue;
190
+ return logger.filters.every((filter) => filter(record));
191
+ }
192
+ return true;
193
+ }
194
+ function disposeSyncDisposables(disposables) {
195
+ const errors = [];
196
+ for (const disposable of disposables) try {
197
+ disposable[Symbol.dispose]();
198
+ } catch (error) {
199
+ errors.push(error);
200
+ }
201
+ throwDisposeErrors(errors);
202
+ }
203
+ async function disposeAsyncDisposables(disposables) {
204
+ const results = await Promise.allSettled(Array.from(disposables, (disposable) => Promise.resolve().then(() => disposable[Symbol.asyncDispose]())));
205
+ throwDisposeErrors(results.filter((result) => result.status === "rejected").map((result) => result.reason));
206
+ }
207
+ function throwDisposeErrors(errors) {
208
+ if (errors.length < 1) return;
209
+ if (errors.length === 1) throw errors[0];
210
+ throw new AggregateError(errors, "Multiple errors occurred while disposing LogTape scoped resources.");
211
+ }
212
+ function flattenErrors(...errors) {
213
+ const flattened = [];
214
+ for (const error of errors) if (error instanceof AggregateError) flattened.push(...error.errors);
215
+ else flattened.push(error);
216
+ return flattened;
217
+ }
218
+
219
+ //#endregion
220
+ exports.compileScopedConfig = compileScopedConfig;
221
+ exports.disposeScopedConfig = disposeScopedConfig;
222
+ exports.disposeScopedConfigSync = disposeScopedConfigSync;
223
+ exports.emitWithScopedConfig = emitWithScopedConfig;
224
+ exports.getCurrentScopedConfig = getCurrentScopedConfig;
225
+ exports.runWithScopedConfig = runWithScopedConfig;
226
+ exports.scopedConfigHasSink = scopedConfigHasSink;
227
+ exports.throwCombinedErrors = throwCombinedErrors;
@@ -0,0 +1,21 @@
1
+ import { LogLevel } from "./level.cjs";
2
+ import { FilterLike } from "./filter.cjs";
3
+ import { Sink } from "./sink.cjs";
4
+
5
+ //#region src/scoped-config.d.ts
6
+
7
+ interface ScopedConfigLike<TSinkId extends string, TFilterId extends string> {
8
+ readonly sinks: Record<TSinkId, Sink>;
9
+ readonly filters?: Record<TFilterId, FilterLike>;
10
+ readonly loggers: readonly ScopedLoggerConfigLike<TSinkId, TFilterId>[];
11
+ }
12
+ interface ScopedLoggerConfigLike<TSinkId extends string, TFilterId extends string> {
13
+ readonly category: string | readonly string[];
14
+ readonly sinks?: readonly TSinkId[];
15
+ readonly parentSinks?: "inherit" | "override";
16
+ readonly filters?: readonly TFilterId[];
17
+ readonly lowestLevel?: LogLevel | null;
18
+ }
19
+ //#endregion
20
+ export { ScopedConfigLike };
21
+ //# sourceMappingURL=scoped-config.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-config.d.cts","names":[],"sources":["../src/scoped-config.ts"],"sourcesContent":[],"mappings":";;;;;;AAgByB,UAJR,gBAIQ,CAAA,gBAAA,MAAA,EAAA,kBAAA,MAAA,CAAA,CAAA;EAAO,SAAE,KAAA,EAAhB,MAAgB,CAAT,OAAS,EAAA,IAAA,CAAA;EAAI,SAApB,OAAA,CAAA,EACG,MADH,CACU,SADV,EACqB,UADrB,CAAA;EAAM,SACI,OAAA,EAAA,SACC,sBADD,CACwB,OADxB,EACiC,SADjC,CAAA,EAAA;;AAAP,UAIJ,sBAJI,CAAA,gBAAA,MAAA,EAAA,kBAAA,MAAA,CAAA,CAAA;EAAM,SACyB,QAAA,EAAA,MAAA,GAAA,SAAA,MAAA,EAAA;EAAO,SAAE,KAAA,CAAA,EAAA,SAQjC,OARiC,EAAA;EAAS,SAAzC,WAAA,CAAA,EAAA,SAAA,GAAA,UAAA;EAAsB,SAAA,OAAA,CAAA,EAAA,SAUrB,SAVqB,EAAA;EAGlC,SAAA,WAAA,CAAA,EAQQ,QARc,GAAA,IAAA"}
@@ -0,0 +1,21 @@
1
+ import { LogLevel } from "./level.js";
2
+ import { FilterLike } from "./filter.js";
3
+ import { Sink } from "./sink.js";
4
+
5
+ //#region src/scoped-config.d.ts
6
+
7
+ interface ScopedConfigLike<TSinkId extends string, TFilterId extends string> {
8
+ readonly sinks: Record<TSinkId, Sink>;
9
+ readonly filters?: Record<TFilterId, FilterLike>;
10
+ readonly loggers: readonly ScopedLoggerConfigLike<TSinkId, TFilterId>[];
11
+ }
12
+ interface ScopedLoggerConfigLike<TSinkId extends string, TFilterId extends string> {
13
+ readonly category: string | readonly string[];
14
+ readonly sinks?: readonly TSinkId[];
15
+ readonly parentSinks?: "inherit" | "override";
16
+ readonly filters?: readonly TFilterId[];
17
+ readonly lowestLevel?: LogLevel | null;
18
+ }
19
+ //#endregion
20
+ export { ScopedConfigLike };
21
+ //# sourceMappingURL=scoped-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-config.d.ts","names":[],"sources":["../src/scoped-config.ts"],"sourcesContent":[],"mappings":";;;;;;AAgByB,UAJR,gBAIQ,CAAA,gBAAA,MAAA,EAAA,kBAAA,MAAA,CAAA,CAAA;EAAO,SAAE,KAAA,EAAhB,MAAgB,CAAT,OAAS,EAAA,IAAA,CAAA;EAAI,SAApB,OAAA,CAAA,EACG,MADH,CACU,SADV,EACqB,UADrB,CAAA;EAAM,SACI,OAAA,EAAA,SACC,sBADD,CACwB,OADxB,EACiC,SADjC,CAAA,EAAA;;AAAP,UAIJ,sBAJI,CAAA,gBAAA,MAAA,EAAA,kBAAA,MAAA,CAAA,CAAA;EAAM,SACyB,QAAA,EAAA,MAAA,GAAA,SAAA,MAAA,EAAA;EAAO,SAAE,KAAA,CAAA,EAAA,SAQjC,OARiC,EAAA;EAAS,SAAzC,WAAA,CAAA,EAAA,SAAA,GAAA,UAAA;EAAsB,SAAA,OAAA,CAAA,EAAA,SAUrB,SAVqB,EAAA;EAGlC,SAAA,WAAA,CAAA,EAQQ,QARc,GAAA,IAAA"}
@@ -0,0 +1,221 @@
1
+ import { toFilter } from "./filter.js";
2
+ import { compareLogLevel } from "./level.js";
3
+
4
+ //#region src/scoped-config.ts
5
+ const scopedConfigSymbol = Symbol.for("logtape.scopedConfig");
6
+ const defaultScopedLogger = {
7
+ filters: [],
8
+ lowestLevel: "trace",
9
+ parentSinks: "inherit",
10
+ sinks: []
11
+ };
12
+ function compileScopedConfig(config, allowAsync, createError) {
13
+ const nodes = /* @__PURE__ */ new Map();
14
+ const configuredCategories = /* @__PURE__ */ new Set();
15
+ for (const logger of config.loggers) {
16
+ const category = normalizeCategory(logger.category);
17
+ const key = categoryKey(category);
18
+ if (configuredCategories.has(key)) throw createError(`Duplicate logger configuration for category: ${key}. Each category can only be configured once.`);
19
+ configuredCategories.add(key);
20
+ const sinks = [];
21
+ for (const sinkId of logger.sinks ?? []) {
22
+ const sink = config.sinks[sinkId];
23
+ if (!sink) throw createError(`Sink not found: ${sinkId}.`);
24
+ sinks.push(sink);
25
+ }
26
+ const filters = [];
27
+ for (const filterId of logger.filters ?? []) {
28
+ const filter = config.filters?.[filterId];
29
+ if (filter === void 0) throw createError(`Filter not found: ${filterId}.`);
30
+ filters.push(toFilter(filter));
31
+ }
32
+ nodes.set(key, {
33
+ filters,
34
+ lowestLevel: logger.lowestLevel === void 0 ? "trace" : logger.lowestLevel,
35
+ parentSinks: logger.parentSinks ?? "inherit",
36
+ sinks
37
+ });
38
+ }
39
+ const syncFilters = /* @__PURE__ */ new Set();
40
+ const asyncFilters = /* @__PURE__ */ new Set();
41
+ const syncSinks = /* @__PURE__ */ new Set();
42
+ const asyncSinks = /* @__PURE__ */ new Set();
43
+ for (const sink of Object.values(config.sinks)) {
44
+ if (Symbol.asyncDispose in sink) {
45
+ if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
46
+ asyncSinks.add(sink);
47
+ }
48
+ if (Symbol.dispose in sink) syncSinks.add(sink);
49
+ }
50
+ for (const filter of Object.values(config.filters ?? {})) {
51
+ if (filter == null || typeof filter === "string") continue;
52
+ if (Symbol.asyncDispose in filter) {
53
+ if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
54
+ asyncFilters.add(filter);
55
+ asyncSinks.delete(filter);
56
+ }
57
+ if (Symbol.dispose in filter) {
58
+ syncFilters.add(filter);
59
+ syncSinks.delete(filter);
60
+ }
61
+ }
62
+ return {
63
+ asyncFilters,
64
+ asyncSinks,
65
+ disposed: false,
66
+ nodes,
67
+ parent: void 0,
68
+ syncFilters,
69
+ syncSinks
70
+ };
71
+ }
72
+ function getCurrentScopedConfig(contextLocalStorage) {
73
+ const store = contextLocalStorage?.getStore();
74
+ const scopedConfig = store?.[scopedConfigSymbol];
75
+ return isCompiledScopedConfig(scopedConfig) ? getActiveScopedConfig(scopedConfig) : void 0;
76
+ }
77
+ function runWithScopedConfig(contextLocalStorage, scopedConfig, callback) {
78
+ const parentStore = contextLocalStorage.getStore() ?? {};
79
+ scopedConfig.parent = getCurrentScopedConfig(contextLocalStorage);
80
+ return contextLocalStorage.run({
81
+ ...parentStore,
82
+ [scopedConfigSymbol]: scopedConfig
83
+ }, callback);
84
+ }
85
+ function scopedConfigHasSink(scopedConfig, category, level) {
86
+ return getScopedSinkDispatchPlan(scopedConfig, category, level).kind !== "none";
87
+ }
88
+ function emitWithScopedConfig(scopedConfig, record, bypassSinks, emitToSink) {
89
+ const plan = getScopedSinkDispatchPlan(scopedConfig, record.category, record.level);
90
+ if (plan.kind === "none") return;
91
+ if (!filterScopedRecord(scopedConfig, record.category, record)) return;
92
+ if (plan.kind === "one") {
93
+ if (!bypassSinks?.has(plan.sink)) emitToSink(plan.sink, bypassSinks);
94
+ return;
95
+ }
96
+ for (const sink of plan.sinks) {
97
+ if (bypassSinks?.has(sink)) continue;
98
+ emitToSink(sink, bypassSinks);
99
+ }
100
+ }
101
+ async function disposeScopedConfig(scopedConfig) {
102
+ scopedConfig.disposed = true;
103
+ const errors = [];
104
+ try {
105
+ disposeSyncDisposables(scopedConfig.syncFilters);
106
+ } catch (error) {
107
+ errors.push(error);
108
+ }
109
+ try {
110
+ await disposeAsyncDisposables(scopedConfig.asyncFilters);
111
+ } catch (error) {
112
+ errors.push(error);
113
+ }
114
+ try {
115
+ disposeSyncDisposables(scopedConfig.syncSinks);
116
+ } catch (error) {
117
+ errors.push(error);
118
+ }
119
+ try {
120
+ await disposeAsyncDisposables(scopedConfig.asyncSinks);
121
+ } catch (error) {
122
+ errors.push(error);
123
+ }
124
+ throwDisposeErrors(errors);
125
+ }
126
+ function disposeScopedConfigSync(scopedConfig) {
127
+ scopedConfig.disposed = true;
128
+ const errors = [];
129
+ try {
130
+ disposeSyncDisposables(scopedConfig.syncFilters);
131
+ } catch (error) {
132
+ errors.push(error);
133
+ }
134
+ try {
135
+ disposeSyncDisposables(scopedConfig.syncSinks);
136
+ } catch (error) {
137
+ errors.push(error);
138
+ }
139
+ throwDisposeErrors(errors);
140
+ }
141
+ function throwCombinedErrors(primary, secondary) {
142
+ throw new AggregateError(flattenErrors(primary, secondary), "Multiple errors occurred while running LogTape scoped configuration.");
143
+ }
144
+ function isCompiledScopedConfig(value) {
145
+ return value != null && typeof value === "object" && "nodes" in value;
146
+ }
147
+ function getActiveScopedConfig(scopedConfig) {
148
+ let activeConfig = scopedConfig;
149
+ while (activeConfig?.disposed) activeConfig = activeConfig.parent;
150
+ return activeConfig;
151
+ }
152
+ function normalizeCategory(category) {
153
+ return typeof category === "string" ? [category] : [...category];
154
+ }
155
+ function categoryKey(category) {
156
+ return JSON.stringify(category);
157
+ }
158
+ function getScopedSinkDispatchPlan(scopedConfig, category, level) {
159
+ return getScopedSinkDispatchPlanForPrefix(scopedConfig, category, category.length, level);
160
+ }
161
+ function getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length, level) {
162
+ const prefix = category.slice(0, length);
163
+ const logger = scopedConfig.nodes.get(categoryKey(prefix)) ?? defaultScopedLogger;
164
+ if (logger.lowestLevel === null || compareLogLevel(level, logger.lowestLevel) < 0) return { kind: "none" };
165
+ const parentPlan = length > 0 && logger.parentSinks === "inherit" ? getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length - 1, level) : { kind: "none" };
166
+ let firstSink;
167
+ let sinks;
168
+ const appendSink = (sink) => {
169
+ if (sinks != null) sinks.push(sink);
170
+ else if (firstSink == null) firstSink = sink;
171
+ else sinks = [firstSink, sink];
172
+ };
173
+ if (parentPlan.kind === "one") appendSink(parentPlan.sink);
174
+ else if (parentPlan.kind === "many") for (const sink of parentPlan.sinks) appendSink(sink);
175
+ for (const sink of logger.sinks) appendSink(sink);
176
+ if (sinks != null) return {
177
+ kind: "many",
178
+ sinks
179
+ };
180
+ if (firstSink != null) return {
181
+ kind: "one",
182
+ sink: firstSink
183
+ };
184
+ return { kind: "none" };
185
+ }
186
+ function filterScopedRecord(scopedConfig, category, record) {
187
+ for (let length = category.length; length >= 0; length--) {
188
+ const logger = scopedConfig.nodes.get(categoryKey(category.slice(0, length)));
189
+ if (logger == null || logger.filters.length < 1) continue;
190
+ return logger.filters.every((filter) => filter(record));
191
+ }
192
+ return true;
193
+ }
194
+ function disposeSyncDisposables(disposables) {
195
+ const errors = [];
196
+ for (const disposable of disposables) try {
197
+ disposable[Symbol.dispose]();
198
+ } catch (error) {
199
+ errors.push(error);
200
+ }
201
+ throwDisposeErrors(errors);
202
+ }
203
+ async function disposeAsyncDisposables(disposables) {
204
+ const results = await Promise.allSettled(Array.from(disposables, (disposable) => Promise.resolve().then(() => disposable[Symbol.asyncDispose]())));
205
+ throwDisposeErrors(results.filter((result) => result.status === "rejected").map((result) => result.reason));
206
+ }
207
+ function throwDisposeErrors(errors) {
208
+ if (errors.length < 1) return;
209
+ if (errors.length === 1) throw errors[0];
210
+ throw new AggregateError(errors, "Multiple errors occurred while disposing LogTape scoped resources.");
211
+ }
212
+ function flattenErrors(...errors) {
213
+ const flattened = [];
214
+ for (const error of errors) if (error instanceof AggregateError) flattened.push(...error.errors);
215
+ else flattened.push(error);
216
+ return flattened;
217
+ }
218
+
219
+ //#endregion
220
+ export { compileScopedConfig, disposeScopedConfig, disposeScopedConfigSync, emitWithScopedConfig, getCurrentScopedConfig, runWithScopedConfig, scopedConfigHasSink, throwCombinedErrors };
221
+ //# sourceMappingURL=scoped-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-config.js","names":["scopedConfigSymbol: unique symbol","defaultScopedLogger: CompiledScopedLogger","config: ScopedConfigLike<TSinkId, TFilterId>","allowAsync: boolean","createError: (message: string) => Error","sinks: Sink[]","filters: ((record: LogRecord) => boolean)[]","contextLocalStorage:\n | ContextLocalStorage<Record<string, unknown>>\n | undefined","contextLocalStorage: ContextLocalStorage<Record<string, unknown>>","scopedConfig: CompiledScopedConfig","callback: () => R","category: readonly string[]","level: LogLevel","record: LogRecord","bypassSinks: Set<Sink> | undefined","emitToSink: (sink: Sink, bypassSinks: Set<Sink> | undefined) => void","errors: unknown[]","primary: unknown","secondary: unknown","value: unknown","activeConfig: CompiledScopedConfig | undefined","category: string | readonly string[]","length: number","firstSink: Sink | undefined","sinks: Sink[] | undefined","sink: Sink","disposables: ReadonlySet<Disposable>","disposables: ReadonlySet<AsyncDisposable>","errors: readonly unknown[]","flattened: unknown[]"],"sources":["../src/scoped-config.ts"],"sourcesContent":["import type { ContextLocalStorage } from \"./context.ts\";\nimport { type FilterLike, toFilter } from \"./filter.ts\";\nimport { compareLogLevel, type LogLevel } from \"./level.ts\";\nimport type { LogRecord } from \"./record.ts\";\nimport type { Sink } from \"./sink.ts\";\n\nexport type ScopedConfigSymbol = typeof scopedConfigSymbol;\n\nexport const scopedConfigSymbol: unique symbol = Symbol.for(\n \"logtape.scopedConfig\",\n);\n\nexport interface ScopedConfigLike<\n TSinkId extends string,\n TFilterId extends string,\n> {\n readonly sinks: Record<TSinkId, Sink>;\n readonly filters?: Record<TFilterId, FilterLike>;\n readonly loggers: readonly ScopedLoggerConfigLike<TSinkId, TFilterId>[];\n}\n\nexport interface ScopedLoggerConfigLike<\n TSinkId extends string,\n TFilterId extends string,\n> {\n readonly category: string | readonly string[];\n readonly sinks?: readonly TSinkId[];\n readonly parentSinks?: \"inherit\" | \"override\";\n readonly filters?: readonly TFilterId[];\n readonly lowestLevel?: LogLevel | null;\n}\n\nexport interface CompiledScopedConfig {\n readonly nodes: ReadonlyMap<string, CompiledScopedLogger>;\n parent: CompiledScopedConfig | undefined;\n disposed: boolean;\n readonly syncFilters: ReadonlySet<Disposable>;\n readonly asyncFilters: ReadonlySet<AsyncDisposable>;\n readonly syncSinks: ReadonlySet<Disposable>;\n readonly asyncSinks: ReadonlySet<AsyncDisposable>;\n}\n\ninterface CompiledScopedLogger {\n readonly filters: readonly ((record: LogRecord) => boolean)[];\n readonly lowestLevel: LogLevel | null;\n readonly parentSinks: \"inherit\" | \"override\";\n readonly sinks: readonly Sink[];\n}\n\ntype ScopedSinkDispatchPlan =\n | { readonly kind: \"none\" }\n | { readonly kind: \"one\"; readonly sink: Sink }\n | { readonly kind: \"many\"; readonly sinks: readonly Sink[] };\n\nconst defaultScopedLogger: CompiledScopedLogger = {\n filters: [],\n lowestLevel: \"trace\",\n parentSinks: \"inherit\",\n sinks: [],\n};\n\nexport function compileScopedConfig<\n TSinkId extends string,\n TFilterId extends string,\n>(\n config: ScopedConfigLike<TSinkId, TFilterId>,\n allowAsync: boolean,\n createError: (message: string) => Error,\n): CompiledScopedConfig {\n const nodes = new Map<string, CompiledScopedLogger>();\n const configuredCategories = new Set<string>();\n for (const logger of config.loggers) {\n const category = normalizeCategory(logger.category);\n const key = categoryKey(category);\n if (configuredCategories.has(key)) {\n throw createError(\n `Duplicate logger configuration for category: ${key}. ` +\n \"Each category can only be configured once.\",\n );\n }\n configuredCategories.add(key);\n\n const sinks: Sink[] = [];\n for (const sinkId of logger.sinks ?? []) {\n const sink = config.sinks[sinkId];\n if (!sink) throw createError(`Sink not found: ${sinkId}.`);\n sinks.push(sink);\n }\n\n const filters: ((record: LogRecord) => boolean)[] = [];\n for (const filterId of logger.filters ?? []) {\n const filter = config.filters?.[filterId];\n if (filter === undefined) {\n throw createError(`Filter not found: ${filterId}.`);\n }\n filters.push(toFilter(filter));\n }\n\n nodes.set(key, {\n filters,\n lowestLevel: logger.lowestLevel === undefined\n ? \"trace\"\n : logger.lowestLevel,\n parentSinks: logger.parentSinks ?? \"inherit\",\n sinks,\n });\n }\n\n const syncFilters = new Set<Disposable>();\n const asyncFilters = new Set<AsyncDisposable>();\n const syncSinks = new Set<Disposable>();\n const asyncSinks = new Set<AsyncDisposable>();\n\n for (const sink of Object.values<Sink>(config.sinks)) {\n if (Symbol.asyncDispose in sink) {\n if (!allowAsync) {\n throw createError(\n \"Async disposables cannot be used with withConfigSync().\",\n );\n }\n asyncSinks.add(sink as AsyncDisposable);\n }\n if (Symbol.dispose in sink) syncSinks.add(sink as Disposable);\n }\n\n for (const filter of Object.values<FilterLike>(config.filters ?? {})) {\n if (filter == null || typeof filter === \"string\") continue;\n if (Symbol.asyncDispose in filter) {\n if (!allowAsync) {\n throw createError(\n \"Async disposables cannot be used with withConfigSync().\",\n );\n }\n asyncFilters.add(filter as AsyncDisposable);\n asyncSinks.delete(filter as AsyncDisposable);\n }\n if (Symbol.dispose in filter) {\n syncFilters.add(filter as Disposable);\n syncSinks.delete(filter as Disposable);\n }\n }\n\n return {\n asyncFilters,\n asyncSinks,\n disposed: false,\n nodes,\n parent: undefined,\n syncFilters,\n syncSinks,\n };\n}\n\nexport function getCurrentScopedConfig(\n contextLocalStorage:\n | ContextLocalStorage<Record<string, unknown>>\n | undefined,\n): CompiledScopedConfig | undefined {\n const store = contextLocalStorage?.getStore();\n const scopedConfig = (store as Record<ScopedConfigSymbol, unknown> | null)\n ?.[scopedConfigSymbol];\n return isCompiledScopedConfig(scopedConfig)\n ? getActiveScopedConfig(scopedConfig)\n : undefined;\n}\n\nexport function runWithScopedConfig<R>(\n contextLocalStorage: ContextLocalStorage<Record<string, unknown>>,\n scopedConfig: CompiledScopedConfig,\n callback: () => R,\n): R {\n const parentStore = contextLocalStorage.getStore() ?? {};\n scopedConfig.parent = getCurrentScopedConfig(contextLocalStorage);\n return contextLocalStorage.run({\n ...parentStore,\n [scopedConfigSymbol]: scopedConfig,\n } as Record<string, unknown>, callback);\n}\n\nexport function scopedConfigHasSink(\n scopedConfig: CompiledScopedConfig,\n category: readonly string[],\n level: LogLevel,\n): boolean {\n return getScopedSinkDispatchPlan(scopedConfig, category, level).kind !==\n \"none\";\n}\n\nexport function emitWithScopedConfig(\n scopedConfig: CompiledScopedConfig,\n record: LogRecord,\n bypassSinks: Set<Sink> | undefined,\n emitToSink: (sink: Sink, bypassSinks: Set<Sink> | undefined) => void,\n): void {\n const plan = getScopedSinkDispatchPlan(\n scopedConfig,\n record.category,\n record.level,\n );\n if (plan.kind === \"none\") return;\n if (!filterScopedRecord(scopedConfig, record.category, record)) return;\n if (plan.kind === \"one\") {\n if (!bypassSinks?.has(plan.sink)) emitToSink(plan.sink, bypassSinks);\n return;\n }\n for (const sink of plan.sinks) {\n if (bypassSinks?.has(sink)) continue;\n emitToSink(sink, bypassSinks);\n }\n}\n\nexport async function disposeScopedConfig(\n scopedConfig: CompiledScopedConfig,\n): Promise<void> {\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncFilters);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncSinks);\n } catch (error) {\n errors.push(error);\n }\n throwDisposeErrors(errors);\n}\n\nexport function disposeScopedConfigSync(\n scopedConfig: CompiledScopedConfig,\n): void {\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks);\n } catch (error) {\n errors.push(error);\n }\n throwDisposeErrors(errors);\n}\n\nexport function throwCombinedErrors(\n primary: unknown,\n secondary: unknown,\n): never {\n throw new AggregateError(\n flattenErrors(primary, secondary),\n \"Multiple errors occurred while running LogTape scoped configuration.\",\n );\n}\n\nfunction isCompiledScopedConfig(value: unknown): value is CompiledScopedConfig {\n return value != null && typeof value === \"object\" && \"nodes\" in value;\n}\n\nfunction getActiveScopedConfig(\n scopedConfig: CompiledScopedConfig,\n): CompiledScopedConfig | undefined {\n let activeConfig: CompiledScopedConfig | undefined = scopedConfig;\n while (activeConfig?.disposed) activeConfig = activeConfig.parent;\n return activeConfig;\n}\n\nfunction normalizeCategory(category: string | readonly string[]): string[] {\n return typeof category === \"string\" ? [category] : [...category];\n}\n\nfunction categoryKey(category: readonly string[]): string {\n return JSON.stringify(category);\n}\n\nfunction getScopedSinkDispatchPlan(\n scopedConfig: CompiledScopedConfig,\n category: readonly string[],\n level: LogLevel,\n): ScopedSinkDispatchPlan {\n return getScopedSinkDispatchPlanForPrefix(\n scopedConfig,\n category,\n category.length,\n level,\n );\n}\n\nfunction getScopedSinkDispatchPlanForPrefix(\n scopedConfig: CompiledScopedConfig,\n category: readonly string[],\n length: number,\n level: LogLevel,\n): ScopedSinkDispatchPlan {\n const prefix = category.slice(0, length);\n const logger = scopedConfig.nodes.get(categoryKey(prefix)) ??\n defaultScopedLogger;\n if (\n logger.lowestLevel === null ||\n compareLogLevel(level, logger.lowestLevel) < 0\n ) {\n return { kind: \"none\" };\n }\n\n const parentPlan = length > 0 && logger.parentSinks === \"inherit\"\n ? getScopedSinkDispatchPlanForPrefix(\n scopedConfig,\n category,\n length - 1,\n level,\n )\n : { kind: \"none\" } as const;\n\n let firstSink: Sink | undefined;\n let sinks: Sink[] | undefined;\n const appendSink = (sink: Sink): void => {\n if (sinks != null) {\n sinks.push(sink);\n } else if (firstSink == null) {\n firstSink = sink;\n } else {\n sinks = [firstSink, sink];\n }\n };\n\n if (parentPlan.kind === \"one\") appendSink(parentPlan.sink);\n else if (parentPlan.kind === \"many\") {\n for (const sink of parentPlan.sinks) appendSink(sink);\n }\n for (const sink of logger.sinks) appendSink(sink);\n\n if (sinks != null) return { kind: \"many\", sinks };\n if (firstSink != null) return { kind: \"one\", sink: firstSink };\n return { kind: \"none\" };\n}\n\nfunction filterScopedRecord(\n scopedConfig: CompiledScopedConfig,\n category: readonly string[],\n record: LogRecord,\n): boolean {\n for (let length = category.length; length >= 0; length--) {\n const logger = scopedConfig.nodes.get(\n categoryKey(category.slice(0, length)),\n );\n if (logger == null || logger.filters.length < 1) continue;\n return logger.filters.every((filter) => filter(record));\n }\n return true;\n}\n\nfunction disposeSyncDisposables(disposables: ReadonlySet<Disposable>): void {\n const errors: unknown[] = [];\n for (const disposable of disposables) {\n try {\n disposable[Symbol.dispose]();\n } catch (error) {\n errors.push(error);\n }\n }\n throwDisposeErrors(errors);\n}\n\nasync function disposeAsyncDisposables(\n disposables: ReadonlySet<AsyncDisposable>,\n): Promise<void> {\n const results = await Promise.allSettled(\n Array.from(\n disposables,\n (disposable) =>\n Promise.resolve().then(() => disposable[Symbol.asyncDispose]()),\n ),\n );\n throwDisposeErrors(\n results\n .filter((result): result is PromiseRejectedResult =>\n result.status === \"rejected\"\n )\n .map((result) => result.reason),\n );\n}\n\nfunction throwDisposeErrors(errors: readonly unknown[]): void {\n if (errors.length < 1) return;\n if (errors.length === 1) throw errors[0];\n throw new AggregateError(\n errors,\n \"Multiple errors occurred while disposing LogTape scoped resources.\",\n );\n}\n\nfunction flattenErrors(...errors: readonly unknown[]): unknown[] {\n const flattened: unknown[] = [];\n for (const error of errors) {\n if (error instanceof AggregateError) flattened.push(...error.errors);\n else flattened.push(error);\n }\n return flattened;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/logtape",
3
- "version": "2.3.0-dev.791+61dcdb79",
3
+ "version": "2.3.0-dev.793+68821ae3",
4
4
  "description": "Unobtrusive logging library with zero dependencies—library-first design for Deno/Node.js/Bun/browsers/edge",
5
5
  "keywords": [
6
6
  "logging",
@@ -543,15 +543,14 @@ Available packages
543
543
 
544
544
  ### Framework integrations
545
545
 
546
- | Package | Description |
547
- | ----------------------- | ------------------------- |
548
- | `@logtape/drizzle-orm` | Drizzle ORM query logging |
549
- | `@logtape/elysia` | Elysia HTTP logging |
550
- | `@logtape/express` | Express HTTP logging |
551
- | `@logtape/fastify` | Fastify HTTP logging |
552
- | `@logtape/graphql-yoga` | GraphQL Yoga logging |
553
- | `@logtape/hono` | Hono HTTP logging |
554
- | `@logtape/koa` | Koa HTTP logging |
546
+ | Package | Description |
547
+ | ---------------------- | ------------------------- |
548
+ | `@logtape/express` | Express HTTP logging |
549
+ | `@logtape/fastify` | Fastify HTTP logging |
550
+ | `@logtape/hono` | Hono HTTP logging |
551
+ | `@logtape/koa` | Koa HTTP logging |
552
+ | `@logtape/elysia` | Elysia HTTP logging |
553
+ | `@logtape/drizzle-orm` | Drizzle ORM query logging |
555
554
 
556
555
  ### Formatters
557
556