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

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.
@@ -10,6 +10,9 @@ const defaultScopedLogger = {
10
10
  sinks: []
11
11
  };
12
12
  function compileScopedConfig(config, allowAsync, createError) {
13
+ if (!isObjectLike(config)) throw createError("Configuration must be an object.");
14
+ if (!isObjectLike(config.sinks)) throw createError("Configuration must include a sinks object.");
15
+ if (!Array.isArray(config.loggers)) throw createError("Configuration must include a loggers array.");
13
16
  const nodes = /* @__PURE__ */ new Map();
14
17
  const configuredCategories = /* @__PURE__ */ new Set();
15
18
  for (const logger of config.loggers) {
@@ -18,15 +21,19 @@ function compileScopedConfig(config, allowAsync, createError) {
18
21
  if (configuredCategories.has(key)) throw createError(`Duplicate logger configuration for category: ${key}. Each category can only be configured once.`);
19
22
  configuredCategories.add(key);
20
23
  const sinks = [];
21
- for (const sinkId of logger.sinks ?? []) {
24
+ const sinkIds = logger.sinks ?? [];
25
+ for (const sinkId of sinkIds) {
22
26
  const sink = config.sinks[sinkId];
23
27
  if (!sink) throw createError(`Sink not found: ${sinkId}.`);
28
+ if (typeof sink !== "function") throw createError(`Sink must be a function: ${sinkId}.`);
24
29
  sinks.push(sink);
25
30
  }
26
31
  const filters = [];
27
- for (const filterId of logger.filters ?? []) {
32
+ const filterIds = logger.filters ?? [];
33
+ for (const filterId of filterIds) {
28
34
  const filter = config.filters?.[filterId];
29
35
  if (filter === void 0) throw createError(`Filter not found: ${filterId}.`);
36
+ if (!isFilterLike(filter)) throw createError(`Filter must be a function, log level, or null: ${filterId}.`);
30
37
  filters.push(require_filter.toFilter(filter));
31
38
  }
32
39
  nodes.set(key, {
@@ -41,6 +48,7 @@ function compileScopedConfig(config, allowAsync, createError) {
41
48
  const syncSinks = /* @__PURE__ */ new Set();
42
49
  const asyncSinks = /* @__PURE__ */ new Set();
43
50
  for (const sink of Object.values(config.sinks)) {
51
+ if (!isObjectLike(sink)) continue;
44
52
  if (Symbol.asyncDispose in sink) {
45
53
  if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
46
54
  asyncSinks.add(sink);
@@ -48,7 +56,7 @@ function compileScopedConfig(config, allowAsync, createError) {
48
56
  if (Symbol.dispose in sink) syncSinks.add(sink);
49
57
  }
50
58
  for (const filter of Object.values(config.filters ?? {})) {
51
- if (filter == null || typeof filter === "string") continue;
59
+ if (!isObjectLike(filter)) continue;
52
60
  if (Symbol.asyncDispose in filter) {
53
61
  if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
54
62
  asyncFilters.add(filter);
@@ -144,6 +152,12 @@ function throwCombinedErrors(primary, secondary) {
144
152
  function isCompiledScopedConfig(value) {
145
153
  return value != null && typeof value === "object" && "nodes" in value;
146
154
  }
155
+ function isObjectLike(value) {
156
+ return value != null && (typeof value === "object" || typeof value === "function");
157
+ }
158
+ function isFilterLike(value) {
159
+ return value == null || typeof value === "function" || typeof value === "string" && require_level.isLogLevel(value);
160
+ }
147
161
  function getActiveScopedConfig(scopedConfig) {
148
162
  let activeConfig = scopedConfig;
149
163
  while (activeConfig?.disposed) activeConfig = activeConfig.parent;
@@ -1,5 +1,5 @@
1
1
  import { toFilter } from "./filter.js";
2
- import { compareLogLevel } from "./level.js";
2
+ import { compareLogLevel, isLogLevel } from "./level.js";
3
3
 
4
4
  //#region src/scoped-config.ts
5
5
  const scopedConfigSymbol = Symbol.for("logtape.scopedConfig");
@@ -10,6 +10,9 @@ const defaultScopedLogger = {
10
10
  sinks: []
11
11
  };
12
12
  function compileScopedConfig(config, allowAsync, createError) {
13
+ if (!isObjectLike(config)) throw createError("Configuration must be an object.");
14
+ if (!isObjectLike(config.sinks)) throw createError("Configuration must include a sinks object.");
15
+ if (!Array.isArray(config.loggers)) throw createError("Configuration must include a loggers array.");
13
16
  const nodes = /* @__PURE__ */ new Map();
14
17
  const configuredCategories = /* @__PURE__ */ new Set();
15
18
  for (const logger of config.loggers) {
@@ -18,15 +21,19 @@ function compileScopedConfig(config, allowAsync, createError) {
18
21
  if (configuredCategories.has(key)) throw createError(`Duplicate logger configuration for category: ${key}. Each category can only be configured once.`);
19
22
  configuredCategories.add(key);
20
23
  const sinks = [];
21
- for (const sinkId of logger.sinks ?? []) {
24
+ const sinkIds = logger.sinks ?? [];
25
+ for (const sinkId of sinkIds) {
22
26
  const sink = config.sinks[sinkId];
23
27
  if (!sink) throw createError(`Sink not found: ${sinkId}.`);
28
+ if (typeof sink !== "function") throw createError(`Sink must be a function: ${sinkId}.`);
24
29
  sinks.push(sink);
25
30
  }
26
31
  const filters = [];
27
- for (const filterId of logger.filters ?? []) {
32
+ const filterIds = logger.filters ?? [];
33
+ for (const filterId of filterIds) {
28
34
  const filter = config.filters?.[filterId];
29
35
  if (filter === void 0) throw createError(`Filter not found: ${filterId}.`);
36
+ if (!isFilterLike(filter)) throw createError(`Filter must be a function, log level, or null: ${filterId}.`);
30
37
  filters.push(toFilter(filter));
31
38
  }
32
39
  nodes.set(key, {
@@ -41,6 +48,7 @@ function compileScopedConfig(config, allowAsync, createError) {
41
48
  const syncSinks = /* @__PURE__ */ new Set();
42
49
  const asyncSinks = /* @__PURE__ */ new Set();
43
50
  for (const sink of Object.values(config.sinks)) {
51
+ if (!isObjectLike(sink)) continue;
44
52
  if (Symbol.asyncDispose in sink) {
45
53
  if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
46
54
  asyncSinks.add(sink);
@@ -48,7 +56,7 @@ function compileScopedConfig(config, allowAsync, createError) {
48
56
  if (Symbol.dispose in sink) syncSinks.add(sink);
49
57
  }
50
58
  for (const filter of Object.values(config.filters ?? {})) {
51
- if (filter == null || typeof filter === "string") continue;
59
+ if (!isObjectLike(filter)) continue;
52
60
  if (Symbol.asyncDispose in filter) {
53
61
  if (!allowAsync) throw createError("Async disposables cannot be used with withConfigSync().");
54
62
  asyncFilters.add(filter);
@@ -144,6 +152,12 @@ function throwCombinedErrors(primary, secondary) {
144
152
  function isCompiledScopedConfig(value) {
145
153
  return value != null && typeof value === "object" && "nodes" in value;
146
154
  }
155
+ function isObjectLike(value) {
156
+ return value != null && (typeof value === "object" || typeof value === "function");
157
+ }
158
+ function isFilterLike(value) {
159
+ return value == null || typeof value === "function" || typeof value === "string" && isLogLevel(value);
160
+ }
147
161
  function getActiveScopedConfig(scopedConfig) {
148
162
  let activeConfig = scopedConfig;
149
163
  while (activeConfig?.disposed) activeConfig = activeConfig.parent;
@@ -1 +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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"}
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[]","sinkIds: readonly TSinkId[]","filters: ((record: LogRecord) => boolean)[]","filterIds: readonly TFilterId[]","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, isLogLevel, 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 if (!isObjectLike(config)) {\n throw createError(\"Configuration must be an object.\");\n }\n if (!isObjectLike(config.sinks)) {\n throw createError(\"Configuration must include a sinks object.\");\n }\n if (!Array.isArray(config.loggers)) {\n throw createError(\"Configuration must include a loggers array.\");\n }\n\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 const sinkIds: readonly TSinkId[] = logger.sinks ?? [];\n for (const sinkId of sinkIds) {\n const sink = config.sinks[sinkId];\n if (!sink) throw createError(`Sink not found: ${sinkId}.`);\n if (typeof sink !== \"function\") {\n throw createError(`Sink must be a function: ${sinkId}.`);\n }\n sinks.push(sink);\n }\n\n const filters: ((record: LogRecord) => boolean)[] = [];\n const filterIds: readonly TFilterId[] = logger.filters ?? [];\n for (const filterId of filterIds) {\n const filter = config.filters?.[filterId];\n if (filter === undefined) {\n throw createError(`Filter not found: ${filterId}.`);\n }\n if (!isFilterLike(filter)) {\n throw createError(\n `Filter must be a function, log level, or null: ${filterId}.`,\n );\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 (!isObjectLike(sink)) continue;\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 (!isObjectLike(filter)) 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 isObjectLike(\n value: unknown,\n): value is object | ((...args: never[]) => unknown) {\n return value != null &&\n (typeof value === \"object\" || typeof value === \"function\");\n}\n\nfunction isFilterLike(value: unknown): value is FilterLike {\n return value == null || typeof value === \"function\" ||\n (typeof value === \"string\" && isLogLevel(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.793+68821ae3",
3
+ "version": "2.3.0-dev.797+b92e30e5",
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",