@logtape/logtape 2.3.0-dev.811 → 2.3.0-dev.815
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/README.md +7 -2
- package/dist/scoped-config.cjs +13 -2
- package/dist/scoped-config.js +13 -2
- package/dist/scoped-config.js.map +1 -1
- package/package.json +1 -1
- package/skills/logtape/SKILL.md +9 -8
package/README.md
CHANGED
|
@@ -47,8 +47,9 @@ The highlights of LogTape are:
|
|
|
47
47
|
- *[Dead simple sinks]*: You can easily add your own sinks to LogTape.
|
|
48
48
|
|
|
49
49
|
- *[Framework integrations]*: First-class support for popular frameworks
|
|
50
|
-
like [Express], [Fastify], [Hono], [Koa], and [Drizzle ORM]
|
|
51
|
-
HTTP request logging and database
|
|
50
|
+
like [Express], [Fastify], [GraphQL Yoga], [Hono], [Koa], and [Drizzle ORM]
|
|
51
|
+
with automatic HTTP request logging, GraphQL server logging, and database
|
|
52
|
+
query logging.
|
|
52
53
|
|
|
53
54
|

|
|
54
55
|

|
|
@@ -73,6 +74,7 @@ The highlights of LogTape are:
|
|
|
73
74
|
[Framework integrations]: https://logtape.org/manual/integrations
|
|
74
75
|
[Express]: https://expressjs.com/
|
|
75
76
|
[Fastify]: https://fastify.dev/
|
|
77
|
+
[GraphQL Yoga]: https://the-guild.dev/graphql/yoga-server
|
|
76
78
|
[Hono]: https://hono.dev/
|
|
77
79
|
[Koa]: https://koajs.com/
|
|
78
80
|
[Drizzle ORM]: https://orm.drizzle.team/
|
|
@@ -116,6 +118,7 @@ list of the packages in the LogTape monorepo:
|
|
|
116
118
|
| [*@logtape/elysia*](/packages/elysia/) | [JSR][jsr:@logtape/elysia] | [npm][npm:@logtape/elysia] | [Elysia] integration |
|
|
117
119
|
| [*@logtape/express*](/packages/express/) | [JSR][jsr:@logtape/express] | [npm][npm:@logtape/express] | [Express] integration |
|
|
118
120
|
| [*@logtape/fastify*](/packages/fastify/) | [JSR][jsr:@logtape/fastify] | [npm][npm:@logtape/fastify] | [Fastify] integration |
|
|
121
|
+
| [*@logtape/graphql-yoga*](/packages/graphql-yoga/) | [JSR][jsr:@logtape/graphql-yoga] | [npm][npm:@logtape/graphql-yoga] | [GraphQL Yoga] integration |
|
|
119
122
|
| [*@logtape/hono*](/packages/hono/) | [JSR][jsr:@logtape/hono] | [npm][npm:@logtape/hono] | [Hono] integration |
|
|
120
123
|
| [*@logtape/koa*](/packages/koa/) | [JSR][jsr:@logtape/koa] | [npm][npm:@logtape/koa] | [Koa] integration |
|
|
121
124
|
| [*@logtape/lint*](/packages/lint/) | [JSR][jsr:@logtape/lint] | [npm][npm:@logtape/lint] | ESLint/Oxlint/Deno Lint rules |
|
|
@@ -156,6 +159,8 @@ list of the packages in the LogTape monorepo:
|
|
|
156
159
|
[npm:@logtape/express]: https://www.npmjs.com/package/@logtape/express
|
|
157
160
|
[jsr:@logtape/fastify]: https://jsr.io/@logtape/fastify
|
|
158
161
|
[npm:@logtape/fastify]: https://www.npmjs.com/package/@logtape/fastify
|
|
162
|
+
[jsr:@logtape/graphql-yoga]: https://jsr.io/@logtape/graphql-yoga
|
|
163
|
+
[npm:@logtape/graphql-yoga]: https://www.npmjs.com/package/@logtape/graphql-yoga
|
|
159
164
|
[jsr:@logtape/hono]: https://jsr.io/@logtape/hono
|
|
160
165
|
[npm:@logtape/hono]: https://www.npmjs.com/package/@logtape/hono
|
|
161
166
|
[jsr:@logtape/koa]: https://jsr.io/@logtape/koa
|
package/dist/scoped-config.cjs
CHANGED
|
@@ -9,6 +9,7 @@ const defaultScopedLogger = {
|
|
|
9
9
|
parentSinks: "inherit",
|
|
10
10
|
sinks: []
|
|
11
11
|
};
|
|
12
|
+
const noFilters = [];
|
|
12
13
|
function compileScopedConfig(config, allowAsync, createError) {
|
|
13
14
|
if (!isObjectLike(config)) throw createError("Configuration must be an object.");
|
|
14
15
|
if (!isObjectLike(config.sinks)) throw createError("Configuration must include a sinks object.");
|
|
@@ -77,6 +78,7 @@ function compileScopedConfig(config, allowAsync, createError) {
|
|
|
77
78
|
asyncSinks,
|
|
78
79
|
dispatchCache: /* @__PURE__ */ new Map(),
|
|
79
80
|
disposed: false,
|
|
81
|
+
filterCache: /* @__PURE__ */ new Map(),
|
|
80
82
|
nodes,
|
|
81
83
|
parent: void 0,
|
|
82
84
|
syncFilters,
|
|
@@ -232,12 +234,21 @@ function getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length, leve
|
|
|
232
234
|
return { kind: "none" };
|
|
233
235
|
}
|
|
234
236
|
function filterScopedRecord(scopedConfig, category, record) {
|
|
237
|
+
const key = categoryKey(category);
|
|
238
|
+
let filters = scopedConfig.filterCache.get(key);
|
|
239
|
+
if (filters == null) {
|
|
240
|
+
filters = getScopedFilters(scopedConfig, category);
|
|
241
|
+
scopedConfig.filterCache.set(key, filters);
|
|
242
|
+
}
|
|
243
|
+
return filters.every((filter) => filter(record));
|
|
244
|
+
}
|
|
245
|
+
function getScopedFilters(scopedConfig, category) {
|
|
235
246
|
for (let length = category.length; length >= 0; length--) {
|
|
236
247
|
const logger = scopedConfig.nodes.get(categoryKey(category.slice(0, length)));
|
|
237
248
|
if (logger == null || logger.filters.length < 1) continue;
|
|
238
|
-
return logger.filters
|
|
249
|
+
return logger.filters;
|
|
239
250
|
}
|
|
240
|
-
return
|
|
251
|
+
return noFilters;
|
|
241
252
|
}
|
|
242
253
|
function disposeSyncDisposables(disposables, retainedDisposables) {
|
|
243
254
|
const disposableList = filterRetainedDisposables(disposables, retainedDisposables);
|
package/dist/scoped-config.js
CHANGED
|
@@ -9,6 +9,7 @@ const defaultScopedLogger = {
|
|
|
9
9
|
parentSinks: "inherit",
|
|
10
10
|
sinks: []
|
|
11
11
|
};
|
|
12
|
+
const noFilters = [];
|
|
12
13
|
function compileScopedConfig(config, allowAsync, createError) {
|
|
13
14
|
if (!isObjectLike(config)) throw createError("Configuration must be an object.");
|
|
14
15
|
if (!isObjectLike(config.sinks)) throw createError("Configuration must include a sinks object.");
|
|
@@ -77,6 +78,7 @@ function compileScopedConfig(config, allowAsync, createError) {
|
|
|
77
78
|
asyncSinks,
|
|
78
79
|
dispatchCache: /* @__PURE__ */ new Map(),
|
|
79
80
|
disposed: false,
|
|
81
|
+
filterCache: /* @__PURE__ */ new Map(),
|
|
80
82
|
nodes,
|
|
81
83
|
parent: void 0,
|
|
82
84
|
syncFilters,
|
|
@@ -232,12 +234,21 @@ function getScopedSinkDispatchPlanForPrefix(scopedConfig, category, length, leve
|
|
|
232
234
|
return { kind: "none" };
|
|
233
235
|
}
|
|
234
236
|
function filterScopedRecord(scopedConfig, category, record) {
|
|
237
|
+
const key = categoryKey(category);
|
|
238
|
+
let filters = scopedConfig.filterCache.get(key);
|
|
239
|
+
if (filters == null) {
|
|
240
|
+
filters = getScopedFilters(scopedConfig, category);
|
|
241
|
+
scopedConfig.filterCache.set(key, filters);
|
|
242
|
+
}
|
|
243
|
+
return filters.every((filter) => filter(record));
|
|
244
|
+
}
|
|
245
|
+
function getScopedFilters(scopedConfig, category) {
|
|
235
246
|
for (let length = category.length; length >= 0; length--) {
|
|
236
247
|
const logger = scopedConfig.nodes.get(categoryKey(category.slice(0, length)));
|
|
237
248
|
if (logger == null || logger.filters.length < 1) continue;
|
|
238
|
-
return logger.filters
|
|
249
|
+
return logger.filters;
|
|
239
250
|
}
|
|
240
|
-
return
|
|
251
|
+
return noFilters;
|
|
241
252
|
}
|
|
242
253
|
function disposeSyncDisposables(disposables, retainedDisposables) {
|
|
243
254
|
const disposableList = filterRetainedDisposables(disposables, retainedDisposables);
|
|
@@ -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[]","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","retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>","errors: unknown[]","primary: unknown","secondary: unknown","value: unknown","activeConfig: CompiledScopedConfig | undefined","extraRetained?: ReadonlySet<Disposable | AsyncDisposable>","disposables: Set<Disposable | AsyncDisposable>","category: unknown","length: number","firstSink: Sink | undefined","sinks: Sink[] | undefined","sink: Sink","disposables: Set<Disposable>","retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>","disposables: Set<AsyncDisposable>","disposables: ReadonlySet<TDisposable>","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 readonly dispatchCache: Map<string, ScopedSinkDispatchPlan>;\n parent: CompiledScopedConfig | undefined;\n disposed: boolean;\n readonly syncFilters: Set<Disposable>;\n readonly asyncFilters: Set<AsyncDisposable>;\n readonly syncSinks: Set<Disposable>;\n readonly asyncSinks: Set<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 if (config.filters !== undefined && !isObjectLike(config.filters)) {\n throw createError(\"Configuration filters must be an object.\");\n }\n\n const nodes = new Map<string, CompiledScopedLogger>();\n const configuredCategories = new Set<string>();\n for (const logger of config.loggers) {\n if (!isObjectLike(logger)) {\n throw createError(\"Logger configuration must be an object.\");\n }\n const loggerConfig = logger as ScopedLoggerConfigLike<TSinkId, TFilterId>;\n const category = normalizeCategory(loggerConfig.category, createError);\n if (\n loggerConfig.sinks !== undefined && !Array.isArray(loggerConfig.sinks)\n ) {\n throw createError(\"Logger sinks must be an array.\");\n }\n if (\n loggerConfig.filters !== undefined &&\n !Array.isArray(loggerConfig.filters)\n ) {\n throw createError(\"Logger filters must be an array.\");\n }\n if (\n loggerConfig.parentSinks !== undefined &&\n loggerConfig.parentSinks !== \"inherit\" &&\n loggerConfig.parentSinks !== \"override\"\n ) {\n throw createError(\n 'Logger parentSinks must be \"inherit\" or \"override\".',\n );\n }\n if (\n loggerConfig.lowestLevel !== undefined &&\n loggerConfig.lowestLevel !== null &&\n !isLogLevel(loggerConfig.lowestLevel)\n ) {\n throw createError(\"Logger lowestLevel must be a log level or null.\");\n }\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[] = loggerConfig.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[] = loggerConfig.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: loggerConfig.lowestLevel === undefined\n ? \"trace\"\n : loggerConfig.lowestLevel,\n parentSinks: loggerConfig.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 } else 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 } else 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 dispatchCache: new Map(),\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 retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>,\n): Promise<void> {\n const parentDisposables = getParentScopedDisposables(\n scopedConfig,\n retainedDisposables,\n );\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncSinks, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n throwDisposeErrors(errors);\n}\n\nexport function disposeScopedConfigSync(\n scopedConfig: CompiledScopedConfig,\n retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>,\n): void {\n const parentDisposables = getParentScopedDisposables(\n scopedConfig,\n retainedDisposables,\n );\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks, parentDisposables);\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 getParentScopedDisposables(\n scopedConfig: CompiledScopedConfig,\n extraRetained?: ReadonlySet<Disposable | AsyncDisposable>,\n): ReadonlySet<Disposable | AsyncDisposable> {\n const disposables = new Set<Disposable | AsyncDisposable>(extraRetained);\n let parent = scopedConfig.parent;\n while (parent != null) {\n const activeParent = getActiveScopedConfig(parent);\n if (activeParent == null) break;\n addScopedDisposables(disposables, activeParent);\n parent = activeParent.parent;\n }\n return disposables;\n}\n\nfunction addScopedDisposables(\n disposables: Set<Disposable | AsyncDisposable>,\n scopedConfig: CompiledScopedConfig,\n): void {\n for (const disposable of scopedConfig.syncFilters) {\n disposables.add(disposable);\n }\n for (const disposable of scopedConfig.asyncFilters) {\n disposables.add(disposable);\n }\n for (const disposable of scopedConfig.syncSinks) disposables.add(disposable);\n for (const disposable of scopedConfig.asyncSinks) disposables.add(disposable);\n}\n\nfunction normalizeCategory(\n category: unknown,\n createError: (message: string) => Error,\n): string[] {\n if (typeof category === \"string\") return [category];\n if (!Array.isArray(category)) {\n throw createError(\"Logger category must be a string or array of strings.\");\n }\n if (category.some((part) => typeof part !== \"string\")) {\n throw createError(\"Logger category must only contain strings.\");\n }\n return [...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 const cacheKey = `${categoryKey(category)}:${level}`;\n let plan = scopedConfig.dispatchCache.get(cacheKey);\n if (plan == null) {\n plan = getScopedSinkDispatchPlanForPrefix(\n scopedConfig,\n category,\n category.length,\n level,\n );\n scopedConfig.dispatchCache.set(cacheKey, plan);\n }\n return plan;\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(\n disposables: Set<Disposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): void {\n const disposableList = filterRetainedDisposables(\n disposables,\n retainedDisposables,\n );\n const errors: unknown[] = [];\n try {\n for (const disposable of disposableList) {\n try {\n disposable[Symbol.dispose]();\n } catch (error) {\n errors.push(error);\n }\n }\n } finally {\n disposables.clear();\n }\n throwDisposeErrors(errors);\n}\n\nasync function disposeAsyncDisposables(\n disposables: Set<AsyncDisposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): Promise<void> {\n const disposableList = filterRetainedDisposables(\n disposables,\n retainedDisposables,\n );\n for (const disposable of disposableList) disposables.delete(disposable);\n try {\n const results = await Promise.allSettled(\n disposableList.map((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 } finally {\n disposables.clear();\n }\n}\n\nfunction filterRetainedDisposables<\n TDisposable extends Disposable | AsyncDisposable,\n>(\n disposables: ReadonlySet<TDisposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): TDisposable[] {\n return Array.from(\n disposables,\n ).filter((disposable) => !retainedDisposables.has(disposable));\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","noFilters: readonly ((record: LogRecord) => boolean)[]","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","retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>","errors: unknown[]","primary: unknown","secondary: unknown","value: unknown","activeConfig: CompiledScopedConfig | undefined","extraRetained?: ReadonlySet<Disposable | AsyncDisposable>","disposables: Set<Disposable | AsyncDisposable>","category: unknown","length: number","firstSink: Sink | undefined","sinks: Sink[] | undefined","sink: Sink","disposables: Set<Disposable>","retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>","disposables: Set<AsyncDisposable>","disposables: ReadonlySet<TDisposable>","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 readonly dispatchCache: Map<string, ScopedSinkDispatchPlan>;\n readonly filterCache: Map<\n string,\n readonly ((record: LogRecord) => boolean)[]\n >;\n parent: CompiledScopedConfig | undefined;\n disposed: boolean;\n readonly syncFilters: Set<Disposable>;\n readonly asyncFilters: Set<AsyncDisposable>;\n readonly syncSinks: Set<Disposable>;\n readonly asyncSinks: Set<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};\nconst noFilters: readonly ((record: LogRecord) => boolean)[] = [];\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 if (config.filters !== undefined && !isObjectLike(config.filters)) {\n throw createError(\"Configuration filters must be an object.\");\n }\n\n const nodes = new Map<string, CompiledScopedLogger>();\n const configuredCategories = new Set<string>();\n for (const logger of config.loggers) {\n if (!isObjectLike(logger)) {\n throw createError(\"Logger configuration must be an object.\");\n }\n const loggerConfig = logger as ScopedLoggerConfigLike<TSinkId, TFilterId>;\n const category = normalizeCategory(loggerConfig.category, createError);\n if (\n loggerConfig.sinks !== undefined && !Array.isArray(loggerConfig.sinks)\n ) {\n throw createError(\"Logger sinks must be an array.\");\n }\n if (\n loggerConfig.filters !== undefined &&\n !Array.isArray(loggerConfig.filters)\n ) {\n throw createError(\"Logger filters must be an array.\");\n }\n if (\n loggerConfig.parentSinks !== undefined &&\n loggerConfig.parentSinks !== \"inherit\" &&\n loggerConfig.parentSinks !== \"override\"\n ) {\n throw createError(\n 'Logger parentSinks must be \"inherit\" or \"override\".',\n );\n }\n if (\n loggerConfig.lowestLevel !== undefined &&\n loggerConfig.lowestLevel !== null &&\n !isLogLevel(loggerConfig.lowestLevel)\n ) {\n throw createError(\"Logger lowestLevel must be a log level or null.\");\n }\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[] = loggerConfig.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[] = loggerConfig.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: loggerConfig.lowestLevel === undefined\n ? \"trace\"\n : loggerConfig.lowestLevel,\n parentSinks: loggerConfig.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 } else 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 } else 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 dispatchCache: new Map(),\n disposed: false,\n filterCache: new Map(),\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 retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>,\n): Promise<void> {\n const parentDisposables = getParentScopedDisposables(\n scopedConfig,\n retainedDisposables,\n );\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n await disposeAsyncDisposables(scopedConfig.asyncSinks, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n throwDisposeErrors(errors);\n}\n\nexport function disposeScopedConfigSync(\n scopedConfig: CompiledScopedConfig,\n retainedDisposables?: ReadonlySet<Disposable | AsyncDisposable>,\n): void {\n const parentDisposables = getParentScopedDisposables(\n scopedConfig,\n retainedDisposables,\n );\n scopedConfig.disposed = true;\n const errors: unknown[] = [];\n try {\n disposeSyncDisposables(scopedConfig.syncFilters, parentDisposables);\n } catch (error) {\n errors.push(error);\n }\n try {\n disposeSyncDisposables(scopedConfig.syncSinks, parentDisposables);\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 getParentScopedDisposables(\n scopedConfig: CompiledScopedConfig,\n extraRetained?: ReadonlySet<Disposable | AsyncDisposable>,\n): ReadonlySet<Disposable | AsyncDisposable> {\n const disposables = new Set<Disposable | AsyncDisposable>(extraRetained);\n let parent = scopedConfig.parent;\n while (parent != null) {\n const activeParent = getActiveScopedConfig(parent);\n if (activeParent == null) break;\n addScopedDisposables(disposables, activeParent);\n parent = activeParent.parent;\n }\n return disposables;\n}\n\nfunction addScopedDisposables(\n disposables: Set<Disposable | AsyncDisposable>,\n scopedConfig: CompiledScopedConfig,\n): void {\n for (const disposable of scopedConfig.syncFilters) {\n disposables.add(disposable);\n }\n for (const disposable of scopedConfig.asyncFilters) {\n disposables.add(disposable);\n }\n for (const disposable of scopedConfig.syncSinks) disposables.add(disposable);\n for (const disposable of scopedConfig.asyncSinks) disposables.add(disposable);\n}\n\nfunction normalizeCategory(\n category: unknown,\n createError: (message: string) => Error,\n): string[] {\n if (typeof category === \"string\") return [category];\n if (!Array.isArray(category)) {\n throw createError(\"Logger category must be a string or array of strings.\");\n }\n if (category.some((part) => typeof part !== \"string\")) {\n throw createError(\"Logger category must only contain strings.\");\n }\n return [...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 const cacheKey = `${categoryKey(category)}:${level}`;\n let plan = scopedConfig.dispatchCache.get(cacheKey);\n if (plan == null) {\n plan = getScopedSinkDispatchPlanForPrefix(\n scopedConfig,\n category,\n category.length,\n level,\n );\n scopedConfig.dispatchCache.set(cacheKey, plan);\n }\n return plan;\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 const key = categoryKey(category);\n let filters = scopedConfig.filterCache.get(key);\n if (filters == null) {\n filters = getScopedFilters(scopedConfig, category);\n scopedConfig.filterCache.set(key, filters);\n }\n return filters.every((filter) => filter(record));\n}\n\nfunction getScopedFilters(\n scopedConfig: CompiledScopedConfig,\n category: readonly string[],\n): readonly ((record: LogRecord) => 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;\n }\n return noFilters;\n}\n\nfunction disposeSyncDisposables(\n disposables: Set<Disposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): void {\n const disposableList = filterRetainedDisposables(\n disposables,\n retainedDisposables,\n );\n const errors: unknown[] = [];\n try {\n for (const disposable of disposableList) {\n try {\n disposable[Symbol.dispose]();\n } catch (error) {\n errors.push(error);\n }\n }\n } finally {\n disposables.clear();\n }\n throwDisposeErrors(errors);\n}\n\nasync function disposeAsyncDisposables(\n disposables: Set<AsyncDisposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): Promise<void> {\n const disposableList = filterRetainedDisposables(\n disposables,\n retainedDisposables,\n );\n for (const disposable of disposableList) disposables.delete(disposable);\n try {\n const results = await Promise.allSettled(\n disposableList.map((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 } finally {\n disposables.clear();\n }\n}\n\nfunction filterRetainedDisposables<\n TDisposable extends Disposable | AsyncDisposable,\n>(\n disposables: ReadonlySet<TDisposable>,\n retainedDisposables: ReadonlySet<Disposable | AsyncDisposable>,\n): TDisposable[] {\n return Array.from(\n disposables,\n ).filter((disposable) => !retainedDisposables.has(disposable));\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
package/skills/logtape/SKILL.md
CHANGED
|
@@ -543,14 +543,15 @@ Available packages
|
|
|
543
543
|
|
|
544
544
|
### Framework integrations
|
|
545
545
|
|
|
546
|
-
| Package
|
|
547
|
-
|
|
|
548
|
-
| `@logtape/
|
|
549
|
-
| `@logtape/
|
|
550
|
-
| `@logtape/
|
|
551
|
-
| `@logtape/
|
|
552
|
-
| `@logtape/
|
|
553
|
-
| `@logtape/
|
|
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 |
|
|
554
555
|
|
|
555
556
|
### Formatters
|
|
556
557
|
|