@vielzeug/rune 3.0.0 → 26.10.1
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 +1 -1
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +1 -5
- package/dist/_dev.js.map +1 -1
- package/dist/_prototype.cjs +1 -1
- package/dist/_prototype.cjs.map +1 -1
- package/dist/_prototype.js +1 -12
- package/dist/_prototype.js.map +1 -1
- package/dist/console.cjs +1 -1
- package/dist/console.cjs.map +1 -1
- package/dist/console.d.ts +4 -4
- package/dist/console.js +1 -131
- package/dist/console.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +1 -9
- package/dist/errors.js.map +1 -1
- package/dist/index.js +1 -7
- package/dist/lazy.cjs +1 -1
- package/dist/lazy.cjs.map +1 -1
- package/dist/lazy.d.ts +1 -1
- package/dist/lazy.d.ts.map +1 -1
- package/dist/lazy.js +1 -14
- package/dist/lazy.js.map +1 -1
- package/dist/logger.cjs +1 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.d.ts +2 -2
- package/dist/logger.js +1 -155
- package/dist/logger.js.map +1 -1
- package/dist/rune.cjs +1 -1
- package/dist/rune.cjs.map +1 -1
- package/dist/rune.iife.js +1 -1
- package/dist/rune.iife.js.map +1 -1
- package/dist/rune.js +1 -1
- package/dist/rune.js.map +1 -1
- package/dist/transports.cjs +1 -1
- package/dist/transports.cjs.map +1 -1
- package/dist/transports.js +1 -136
- package/dist/transports.js.map +1 -1
- package/dist/types.cjs +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +10 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -15
- package/dist/types.js.map +1 -1
- package/package.json +5 -5
package/dist/transports.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./types.cjs"),t=require("./errors.cjs"),n=require("./_dev.cjs"),r=require("./_prototype.cjs");function
|
|
1
|
+
const e=require("./types.cjs"),t=require("./errors.cjs"),n=require("./_dev.cjs"),r=require("./_prototype.cjs");function detectEnv(){return typeof window<`u`?`development`:globalThis.process?.env?.NODE_ENV===`production`?`production`:`development`}function remoteTransport(t){let{handler:r}=t,i=t.level??`debug`,a=t.env??detectEnv(),o=t.onError??(e=>n.warn(`remote transport error: ${String(e)}`));return t=>{if(!e.isLevelEnabled(i,t.level))return;let n={data:Object.keys(t.data).length>0?t.data:void 0,env:a,level:t.level,message:t.message,namespace:t.namespace||void 0,timestamp:t.timestamp.toISOString()};Promise.resolve().then(()=>r(t.level,n)).catch(e=>{try{o(e,n)}catch(e){`${String(e)}`}})}}function makeCircularReplacer(){let e=new WeakSet;return(t,n)=>{if(typeof n==`object`&&n){if(e.has(n))return`[Circular]`;e.add(n)}return n}}function jsonTransport(t={}){let n=t.level??`debug`,r=t.fields??{},i=r.level??`level`,a=r.time??`time`,o=r.ns??`ns`,s=r.msg??`msg`,c=t.safe??!1,l=t.output??(e=>{globalThis.process?.stdout?.write(`${e}\n`)});return t=>{if(!e.isLevelEnabled(n,t.level))return;let r={...t.data,[i]:t.level,[a]:t.timestamp.toISOString(),...t.namespace&&{[o]:t.namespace},...t.message!==void 0&&{[s]:t.message}};l(JSON.stringify(r,c?makeCircularReplacer():void 0))}}function assertFiniteNumber(e,n){if(!Number.isFinite(e))throw new t.RuneConfigError(`${n} must be a finite number`)}function assertNonNegativeInteger(e,n){if(assertFiniteNumber(e,n),!Number.isInteger(e)||e<0)throw new t.RuneConfigError(`${n} must be a non-negative integer`)}function assertPositiveInteger(e,n){if(assertFiniteNumber(e,n),!Number.isInteger(e)||e<=0)throw new t.RuneConfigError(`${n} must be a positive integer`)}function batchTransport(n){let r=n.level??`debug`,i=n.maxSize??50,a=n.maxBuffer,o=n.interval??5e3;if(assertFiniteNumber(o,`batchTransport interval`),o<=0)throw new t.RuneConfigError(`batchTransport interval must be greater than zero`);assertPositiveInteger(i,`batchTransport maxSize`),a!==void 0&&assertNonNegativeInteger(a,`batchTransport maxBuffer`);let s=[],c,l,u=!1,d=Promise.resolve(),f,deliver=async e=>{try{await n.onFlush(e)}catch(t){try{n.onFlushError?.(e,t)}catch(e){`${String(e)}`}throw t}},enqueue=e=>{let t=d.then(()=>deliver(e));return d=t.catch(()=>void 0),t},flush=()=>{if(s.length===0)return d;let e=s;return s=[],enqueue(e)},flushAutomatically=()=>{flush().catch(e=>{l??={error:e}})},transport=t=>{!u&&e.isLevelEnabled(r,t.level)&&(c||=setInterval(flushAutomatically,o),s.push(t),a!==void 0&&s.length>a&&(s=s.slice(s.length-a)),s.length>=i&&flushAutomatically())},p={dispose(){return f||(u=!0,c&&clearInterval(c),c=void 0,f=flush().then(()=>{if(l)throw l.error}),f)},get disposed(){return u},flush,[Symbol.asyncDispose](){return p.dispose()},transport};return p}function sampleTransport(n){let{rate:r,transport:i}=n,a=n.level??`debug`;if(assertFiniteNumber(r,`sampleTransport rate`),r<0||r>1)throw new t.RuneConfigError(`sampleTransport rate must be between zero and one`);return t=>{e.isLevelEnabled(a,t.level)&&Math.random()<r&&i(t)}}function redactTransport(e){let{keys:t,maxDepth:n=20,replacement:i=`[REDACTED]`,transport:a}=e;assertNonNegativeInteger(n,`redactTransport maxDepth`);for(let e of t)e.includes(`.`)&&`${e}`;let o=new Set(t),s=!1,redact=(e,t)=>{if(typeof e!=`object`||!e)return e;if(t>n)return s||=(`${n}`,!0),i;if(Array.isArray(e))return e.map(e=>redact(e,t+1));let a={};for(let[n,s]of Object.entries(e))r.isUnsafeObjectKey(n)||(a[n]=o.has(n)?i:redact(s,t+1));return a};return e=>a({...e,data:redact(e.data,0)})}exports.batchTransport=batchTransport,exports.jsonTransport=jsonTransport,exports.redactTransport=redactTransport,exports.remoteTransport=remoteTransport,exports.sampleTransport=sampleTransport;
|
|
2
2
|
//# sourceMappingURL=transports.cjs.map
|
package/dist/transports.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transports.cjs","names":[],"sources":["../src/transports.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { RuneConfigError } from './errors';\nimport type {\n BatchHandle,\n BatchTransportOptions,\n Bindings,\n JsonTransportOptions,\n LogEntry,\n RedactTransportOptions,\n RemoteLogData,\n RemoteTransportOptions,\n SampleTransportOptions,\n Transport,\n} from './types';\nimport { isLevelEnabled } from './types';\n\n/* ─── remoteTransport ─── */\n\nfunction detectEnv(): 'development' | 'production' {\n if (typeof window !== 'undefined') return 'development';\n\n return (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV === 'production'\n ? 'production'\n : 'development';\n}\n\n/** Forward entries asynchronously to a remote delivery handler. */\nexport function remoteTransport(options: RemoteTransportOptions): Transport {\n const { handler } = options;\n const level = options.level ?? 'debug';\n const env = options.env ?? detectEnv();\n const onError = options.onError ?? ((error: unknown) => warn(`remote transport error: ${String(error)}`));\n\n return (entry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const payload: RemoteLogData = {\n data: Object.keys(entry.data).length > 0 ? entry.data : undefined,\n env,\n level: entry.level,\n message: entry.message,\n namespace: entry.namespace || undefined,\n timestamp: entry.timestamp.toISOString(),\n };\n\n Promise.resolve()\n .then(() => handler(entry.level, payload))\n .catch((error: unknown) => {\n try {\n onError(error, payload);\n } catch (observerError) {\n warn(`remote transport error observer threw: ${String(observerError)}`);\n }\n });\n };\n}\n\n/* ─── jsonTransport ─── */\n\nfunction makeCircularReplacer(): (_key: string, value: unknown) => unknown {\n const seen = new WeakSet();\n\n return (_key: string, value: unknown): unknown => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n\n seen.add(value);\n }\n\n return value;\n };\n}\n\n/**\n * Writes newline-delimited JSON (NDJSON) to stdout or a custom output function.\n * Useful for structured log aggregation pipelines in Node.js (ELK, Datadog, etc.).\n *\n * @example\n * jsonTransport({ level: 'info' })\n * jsonTransport({ safe: true }) // handles circular references gracefully\n * jsonTransport({ output: (line) => fs.appendFileSync('app.log', line + '\\n') })\n */\nexport function jsonTransport(options: JsonTransportOptions = {}): Transport {\n const level = options.level ?? 'debug';\n const f = options.fields ?? {};\n const fLevel = f.level ?? 'level';\n const fTime = f.time ?? 'time';\n const fNs = f.ns ?? 'ns';\n const fMsg = f.msg ?? 'msg';\n const safe = options.safe ?? false;\n const output =\n options.output ??\n ((line: string) => {\n (\n globalThis as Record<string, unknown> & { process?: { stdout?: { write: (s: string) => void } } }\n ).process?.stdout?.write(`${line}\\n`);\n });\n\n return (entry: LogEntry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const record: Record<string, unknown> = {\n ...entry.data,\n [fLevel]: entry.level,\n [fTime]: entry.timestamp.toISOString(),\n ...(entry.namespace && { [fNs]: entry.namespace }),\n ...(entry.message !== undefined && { [fMsg]: entry.message }),\n };\n\n output(JSON.stringify(record, safe ? makeCircularReplacer() : undefined));\n };\n}\n\nfunction assertFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value)) throw new RuneConfigError(`${name} must be a finite number`);\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value < 0) throw new RuneConfigError(`${name} must be a non-negative integer`);\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value <= 0) throw new RuneConfigError(`${name} must be a positive integer`);\n}\n\n/* ─── batchTransport ─── */\n\n/** Buffer entries and deliver accepted batches serially. */\nexport function batchTransport(options: BatchTransportOptions): BatchHandle {\n const level = options.level ?? 'debug';\n const maxSize = options.maxSize ?? 50;\n const maxBuffer = options.maxBuffer;\n const interval = options.interval ?? 5000;\n\n assertFiniteNumber(interval, 'batchTransport interval');\n if (interval <= 0) throw new RuneConfigError('batchTransport interval must be greater than zero');\n assertPositiveInteger(maxSize, 'batchTransport maxSize');\n if (maxBuffer !== undefined) assertNonNegativeInteger(maxBuffer, 'batchTransport maxBuffer');\n\n let buffer: LogEntry[] = [];\n let timer: ReturnType<typeof setInterval> | undefined;\n let automaticFailure: { error: unknown } | undefined;\n let disposed = false;\n let deliveryTail: Promise<void> = Promise.resolve();\n let disposePromise: Promise<void> | undefined;\n\n const deliver = async (entries: LogEntry[]): Promise<void> => {\n try {\n await options.onFlush(entries);\n } catch (error) {\n try {\n options.onFlushError?.(entries, error);\n } catch (observerError) {\n warn(`batch transport error observer threw: ${String(observerError)}`);\n }\n throw error;\n }\n };\n\n const enqueue = (entries: LogEntry[]): Promise<void> => {\n const delivery = deliveryTail.then(() => deliver(entries));\n deliveryTail = delivery.catch(() => undefined);\n return delivery;\n };\n\n const flush = (): Promise<void> => {\n if (buffer.length === 0) return deliveryTail;\n\n const entries = buffer;\n buffer = [];\n return enqueue(entries);\n };\n\n const flushAutomatically = (): void => {\n void flush().catch((error: unknown) => {\n automaticFailure ??= { error };\n });\n };\n\n const transport: Transport = (entry): void => {\n if (disposed || !isLevelEnabled(level, entry.level)) return;\n\n if (!timer) timer = setInterval(flushAutomatically, interval);\n buffer.push(entry);\n\n if (maxBuffer !== undefined && buffer.length > maxBuffer) buffer = buffer.slice(buffer.length - maxBuffer);\n if (buffer.length >= maxSize) flushAutomatically();\n };\n\n const handle: BatchHandle = {\n dispose(): Promise<void> {\n if (disposePromise) return disposePromise;\n\n disposed = true;\n if (timer) clearInterval(timer);\n timer = undefined;\n disposePromise = flush().then(() => {\n if (automaticFailure) throw automaticFailure.error;\n });\n return disposePromise;\n },\n get disposed(): boolean {\n return disposed;\n },\n flush,\n [Symbol.asyncDispose](): Promise<void> {\n return handle.dispose();\n },\n transport,\n };\n\n return handle;\n}\n\n/* ─── sampleTransport ─── */\n\n/** Forward a random fraction of entries to a downstream transport. */\nexport function sampleTransport(options: SampleTransportOptions): Transport {\n const { rate, transport } = options;\n const level = options.level ?? 'debug';\n\n assertFiniteNumber(rate, 'sampleTransport rate');\n if (rate < 0 || rate > 1) throw new RuneConfigError('sampleTransport rate must be between zero and one');\n\n return (entry): void => {\n if (isLevelEnabled(level, entry.level) && Math.random() < rate) transport(entry);\n };\n}\n\n/* ─── redactTransport ─── */\n\nexport function redactTransport(options: RedactTransportOptions): Transport {\n const { keys, maxDepth = 20, replacement = '[REDACTED]', transport } = options;\n\n assertNonNegativeInteger(maxDepth, 'redactTransport maxDepth');\n\n for (const key of keys) {\n if (key.includes('.')) {\n warn(`redactTransport: key \"${key}\" contains a dot; keys match exact field names, not paths`);\n }\n }\n\n const keySet = new Set(keys);\n let warnedAboutDepth = false;\n\n const redact = (value: unknown, depth: number): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n\n if (depth > maxDepth) {\n if (!warnedAboutDepth) {\n warn(`redactTransport: object nesting depth exceeded ${maxDepth}; deeper subtrees were redacted entirely`);\n warnedAboutDepth = true;\n }\n return replacement;\n }\n\n if (Array.isArray(value)) return value.map((item) => redact(item, depth + 1));\n\n const result: Bindings = {};\n for (const [key, item] of Object.entries(value)) {\n if (isUnsafeObjectKey(key)) continue;\n result[key] = keySet.has(key) ? replacement : redact(item, depth + 1);\n }\n return result;\n };\n\n return (entry) => transport({ ...entry, data: redact(entry.data, 0) as Bindings });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transports.cjs","names":[],"sources":["../src/transports.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { RuneConfigError } from './errors';\nimport type {\n BatchHandle,\n BatchTransportOptions,\n Bindings,\n JsonTransportOptions,\n LogEntry,\n RedactTransportOptions,\n RemoteLogData,\n RemoteTransportOptions,\n SampleTransportOptions,\n Transport,\n} from './types';\nimport { isLevelEnabled } from './types';\n\n/* ─── remoteTransport ─── */\n\nfunction detectEnv(): 'development' | 'production' {\n if (typeof window !== 'undefined') return 'development';\n\n return (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV === 'production'\n ? 'production'\n : 'development';\n}\n\n/** Forward entries asynchronously to a remote delivery handler. */\nexport function remoteTransport(options: RemoteTransportOptions): Transport {\n const { handler } = options;\n const level = options.level ?? 'debug';\n const env = options.env ?? detectEnv();\n const onError = options.onError ?? ((error: unknown) => warn(`remote transport error: ${String(error)}`));\n\n return (entry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const payload: RemoteLogData = {\n data: Object.keys(entry.data).length > 0 ? entry.data : undefined,\n env,\n level: entry.level,\n message: entry.message,\n namespace: entry.namespace || undefined,\n timestamp: entry.timestamp.toISOString(),\n };\n\n Promise.resolve()\n .then(() => handler(entry.level, payload))\n .catch((error: unknown) => {\n try {\n onError(error, payload);\n } catch (observerError) {\n warn(`remote transport error observer threw: ${String(observerError)}`);\n }\n });\n };\n}\n\n/* ─── jsonTransport ─── */\n\nfunction makeCircularReplacer(): (_key: string, value: unknown) => unknown {\n const seen = new WeakSet();\n\n return (_key: string, value: unknown): unknown => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n\n seen.add(value);\n }\n\n return value;\n };\n}\n\n/**\n * Writes newline-delimited JSON (NDJSON) to stdout or a custom output function.\n * Useful for structured log aggregation pipelines in Node.js (ELK, Datadog, etc.).\n *\n * @example\n * jsonTransport({ level: 'info' })\n * jsonTransport({ safe: true }) // handles circular references gracefully\n * jsonTransport({ output: (line) => fs.appendFileSync('app.log', line + '\\n') })\n */\nexport function jsonTransport(options: JsonTransportOptions = {}): Transport {\n const level = options.level ?? 'debug';\n const f = options.fields ?? {};\n const fLevel = f.level ?? 'level';\n const fTime = f.time ?? 'time';\n const fNs = f.ns ?? 'ns';\n const fMsg = f.msg ?? 'msg';\n const safe = options.safe ?? false;\n const output =\n options.output ??\n ((line: string) => {\n (\n globalThis as Record<string, unknown> & { process?: { stdout?: { write: (s: string) => void } } }\n ).process?.stdout?.write(`${line}\\n`);\n });\n\n return (entry: LogEntry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const record: Record<string, unknown> = {\n ...entry.data,\n [fLevel]: entry.level,\n [fTime]: entry.timestamp.toISOString(),\n ...(entry.namespace && { [fNs]: entry.namespace }),\n ...(entry.message !== undefined && { [fMsg]: entry.message }),\n };\n\n output(JSON.stringify(record, safe ? makeCircularReplacer() : undefined));\n };\n}\n\nfunction assertFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value)) throw new RuneConfigError(`${name} must be a finite number`);\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value < 0) throw new RuneConfigError(`${name} must be a non-negative integer`);\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value <= 0) throw new RuneConfigError(`${name} must be a positive integer`);\n}\n\n/* ─── batchTransport ─── */\n\n/** Buffer entries and deliver accepted batches serially. */\nexport function batchTransport(options: BatchTransportOptions): BatchHandle {\n const level = options.level ?? 'debug';\n const maxSize = options.maxSize ?? 50;\n const maxBuffer = options.maxBuffer;\n const interval = options.interval ?? 5000;\n\n assertFiniteNumber(interval, 'batchTransport interval');\n if (interval <= 0) throw new RuneConfigError('batchTransport interval must be greater than zero');\n assertPositiveInteger(maxSize, 'batchTransport maxSize');\n if (maxBuffer !== undefined) assertNonNegativeInteger(maxBuffer, 'batchTransport maxBuffer');\n\n let buffer: LogEntry[] = [];\n let timer: ReturnType<typeof setInterval> | undefined;\n let automaticFailure: { error: unknown } | undefined;\n let disposed = false;\n let deliveryTail: Promise<void> = Promise.resolve();\n let disposePromise: Promise<void> | undefined;\n\n const deliver = async (entries: LogEntry[]): Promise<void> => {\n try {\n await options.onFlush(entries);\n } catch (error) {\n try {\n options.onFlushError?.(entries, error);\n } catch (observerError) {\n warn(`batch transport error observer threw: ${String(observerError)}`);\n }\n throw error;\n }\n };\n\n const enqueue = (entries: LogEntry[]): Promise<void> => {\n const delivery = deliveryTail.then(() => deliver(entries));\n deliveryTail = delivery.catch(() => undefined);\n return delivery;\n };\n\n const flush = (): Promise<void> => {\n if (buffer.length === 0) return deliveryTail;\n\n const entries = buffer;\n buffer = [];\n return enqueue(entries);\n };\n\n const flushAutomatically = (): void => {\n void flush().catch((error: unknown) => {\n automaticFailure ??= { error };\n });\n };\n\n const transport: Transport = (entry): void => {\n if (disposed || !isLevelEnabled(level, entry.level)) return;\n\n if (!timer) timer = setInterval(flushAutomatically, interval);\n buffer.push(entry);\n\n if (maxBuffer !== undefined && buffer.length > maxBuffer) buffer = buffer.slice(buffer.length - maxBuffer);\n if (buffer.length >= maxSize) flushAutomatically();\n };\n\n const handle: BatchHandle = {\n dispose(): Promise<void> {\n if (disposePromise) return disposePromise;\n\n disposed = true;\n if (timer) clearInterval(timer);\n timer = undefined;\n disposePromise = flush().then(() => {\n if (automaticFailure) throw automaticFailure.error;\n });\n return disposePromise;\n },\n get disposed(): boolean {\n return disposed;\n },\n flush,\n [Symbol.asyncDispose](): Promise<void> {\n return handle.dispose();\n },\n transport,\n };\n\n return handle;\n}\n\n/* ─── sampleTransport ─── */\n\n/** Forward a random fraction of entries to a downstream transport. */\nexport function sampleTransport(options: SampleTransportOptions): Transport {\n const { rate, transport } = options;\n const level = options.level ?? 'debug';\n\n assertFiniteNumber(rate, 'sampleTransport rate');\n if (rate < 0 || rate > 1) throw new RuneConfigError('sampleTransport rate must be between zero and one');\n\n return (entry): void => {\n if (isLevelEnabled(level, entry.level) && Math.random() < rate) transport(entry);\n };\n}\n\n/* ─── redactTransport ─── */\n\nexport function redactTransport(options: RedactTransportOptions): Transport {\n const { keys, maxDepth = 20, replacement = '[REDACTED]', transport } = options;\n\n assertNonNegativeInteger(maxDepth, 'redactTransport maxDepth');\n\n for (const key of keys) {\n if (key.includes('.')) {\n warn(`redactTransport: key \"${key}\" contains a dot; keys match exact field names, not paths`);\n }\n }\n\n const keySet = new Set(keys);\n let warnedAboutDepth = false;\n\n const redact = (value: unknown, depth: number): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n\n if (depth > maxDepth) {\n if (!warnedAboutDepth) {\n warn(`redactTransport: object nesting depth exceeded ${maxDepth}; deeper subtrees were redacted entirely`);\n warnedAboutDepth = true;\n }\n return replacement;\n }\n\n if (Array.isArray(value)) return value.map((item) => redact(item, depth + 1));\n\n const result: Bindings = {};\n for (const [key, item] of Object.entries(value)) {\n if (isUnsafeObjectKey(key)) continue;\n result[key] = keySet.has(key) ? replacement : redact(item, depth + 1);\n }\n return result;\n };\n\n return (entry) => transport({ ...entry, data: redact(entry.data, 0) as Bindings });\n}\n"],"mappings":"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"}
|
package/dist/transports.js
CHANGED
|
@@ -1,137 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RuneConfigError as t } from "./errors.js";
|
|
3
|
-
import { warn as n } from "./_dev.js";
|
|
4
|
-
import { isUnsafeObjectKey as r } from "./_prototype.js";
|
|
5
|
-
//#region src/transports.ts
|
|
6
|
-
function i() {
|
|
7
|
-
return typeof window < "u" ? "development" : globalThis.process?.env?.NODE_ENV === "production" ? "production" : "development";
|
|
8
|
-
}
|
|
9
|
-
function a(t) {
|
|
10
|
-
let { handler: r } = t, a = t.level ?? "debug", o = t.env ?? i(), s = t.onError ?? ((e) => /* @__PURE__ */ n(`remote transport error: ${String(e)}`));
|
|
11
|
-
return (t) => {
|
|
12
|
-
if (!e(a, t.level)) return;
|
|
13
|
-
let n = {
|
|
14
|
-
data: Object.keys(t.data).length > 0 ? t.data : void 0,
|
|
15
|
-
env: o,
|
|
16
|
-
level: t.level,
|
|
17
|
-
message: t.message,
|
|
18
|
-
namespace: t.namespace || void 0,
|
|
19
|
-
timestamp: t.timestamp.toISOString()
|
|
20
|
-
};
|
|
21
|
-
Promise.resolve().then(() => r(t.level, n)).catch((e) => {
|
|
22
|
-
try {
|
|
23
|
-
s(e, n);
|
|
24
|
-
} catch (e) {
|
|
25
|
-
`${String(e)}`;
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function o() {
|
|
31
|
-
let e = /* @__PURE__ */ new WeakSet();
|
|
32
|
-
return (t, n) => {
|
|
33
|
-
if (typeof n == "object" && n) {
|
|
34
|
-
if (e.has(n)) return "[Circular]";
|
|
35
|
-
e.add(n);
|
|
36
|
-
}
|
|
37
|
-
return n;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function s(t = {}) {
|
|
41
|
-
let n = t.level ?? "debug", r = t.fields ?? {}, i = r.level ?? "level", a = r.time ?? "time", s = r.ns ?? "ns", c = r.msg ?? "msg", l = t.safe ?? !1, u = t.output ?? ((e) => {
|
|
42
|
-
globalThis.process?.stdout?.write(`${e}\n`);
|
|
43
|
-
});
|
|
44
|
-
return (t) => {
|
|
45
|
-
if (!e(n, t.level)) return;
|
|
46
|
-
let r = {
|
|
47
|
-
...t.data,
|
|
48
|
-
[i]: t.level,
|
|
49
|
-
[a]: t.timestamp.toISOString(),
|
|
50
|
-
...t.namespace && { [s]: t.namespace },
|
|
51
|
-
...t.message !== void 0 && { [c]: t.message }
|
|
52
|
-
};
|
|
53
|
-
u(JSON.stringify(r, l ? o() : void 0));
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function c(e, n) {
|
|
57
|
-
if (!Number.isFinite(e)) throw new t(`${n} must be a finite number`);
|
|
58
|
-
}
|
|
59
|
-
function l(e, n) {
|
|
60
|
-
if (c(e, n), !Number.isInteger(e) || e < 0) throw new t(`${n} must be a non-negative integer`);
|
|
61
|
-
}
|
|
62
|
-
function u(e, n) {
|
|
63
|
-
if (c(e, n), !Number.isInteger(e) || e <= 0) throw new t(`${n} must be a positive integer`);
|
|
64
|
-
}
|
|
65
|
-
function d(n) {
|
|
66
|
-
let r = n.level ?? "debug", i = n.maxSize ?? 50, a = n.maxBuffer, o = n.interval ?? 5e3;
|
|
67
|
-
if (c(o, "batchTransport interval"), o <= 0) throw new t("batchTransport interval must be greater than zero");
|
|
68
|
-
u(i, "batchTransport maxSize"), a !== void 0 && l(a, "batchTransport maxBuffer");
|
|
69
|
-
let s = [], d, f, p = !1, m = Promise.resolve(), h, g = async (e) => {
|
|
70
|
-
try {
|
|
71
|
-
await n.onFlush(e);
|
|
72
|
-
} catch (t) {
|
|
73
|
-
try {
|
|
74
|
-
n.onFlushError?.(e, t);
|
|
75
|
-
} catch (e) {
|
|
76
|
-
`${String(e)}`;
|
|
77
|
-
}
|
|
78
|
-
throw t;
|
|
79
|
-
}
|
|
80
|
-
}, _ = (e) => {
|
|
81
|
-
let t = m.then(() => g(e));
|
|
82
|
-
return m = t.catch(() => void 0), t;
|
|
83
|
-
}, v = () => {
|
|
84
|
-
if (s.length === 0) return m;
|
|
85
|
-
let e = s;
|
|
86
|
-
return s = [], _(e);
|
|
87
|
-
}, y = () => {
|
|
88
|
-
v().catch((e) => {
|
|
89
|
-
f ??= { error: e };
|
|
90
|
-
});
|
|
91
|
-
}, b = (t) => {
|
|
92
|
-
!p && e(r, t.level) && (d ||= setInterval(y, o), s.push(t), a !== void 0 && s.length > a && (s = s.slice(s.length - a)), s.length >= i && y());
|
|
93
|
-
}, x = {
|
|
94
|
-
dispose() {
|
|
95
|
-
return h || (p = !0, d && clearInterval(d), d = void 0, h = v().then(() => {
|
|
96
|
-
if (f) throw f.error;
|
|
97
|
-
}), h);
|
|
98
|
-
},
|
|
99
|
-
get disposed() {
|
|
100
|
-
return p;
|
|
101
|
-
},
|
|
102
|
-
flush: v,
|
|
103
|
-
[Symbol.asyncDispose]() {
|
|
104
|
-
return x.dispose();
|
|
105
|
-
},
|
|
106
|
-
transport: b
|
|
107
|
-
};
|
|
108
|
-
return x;
|
|
109
|
-
}
|
|
110
|
-
function f(n) {
|
|
111
|
-
let { rate: r, transport: i } = n, a = n.level ?? "debug";
|
|
112
|
-
if (c(r, "sampleTransport rate"), r < 0 || r > 1) throw new t("sampleTransport rate must be between zero and one");
|
|
113
|
-
return (t) => {
|
|
114
|
-
e(a, t.level) && Math.random() < r && i(t);
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function p(e) {
|
|
118
|
-
let { keys: t, maxDepth: n = 20, replacement: i = "[REDACTED]", transport: a } = e;
|
|
119
|
-
l(n, "redactTransport maxDepth");
|
|
120
|
-
for (let e of t) e.includes(".") && `${e}`;
|
|
121
|
-
let o = new Set(t), s = !1, c = (e, t) => {
|
|
122
|
-
if (typeof e != "object" || !e) return e;
|
|
123
|
-
if (t > n) return s ||= (`${n}`, !0), i;
|
|
124
|
-
if (Array.isArray(e)) return e.map((e) => c(e, t + 1));
|
|
125
|
-
let a = {};
|
|
126
|
-
for (let [n, s] of Object.entries(e)) r(n) || (a[n] = o.has(n) ? i : c(s, t + 1));
|
|
127
|
-
return a;
|
|
128
|
-
};
|
|
129
|
-
return (e) => a({
|
|
130
|
-
...e,
|
|
131
|
-
data: c(e.data, 0)
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
//#endregion
|
|
135
|
-
export { d as batchTransport, s as jsonTransport, p as redactTransport, a as remoteTransport, f as sampleTransport };
|
|
136
|
-
|
|
1
|
+
import{isLevelEnabled as e}from"./types.js";import{RuneConfigError as t}from"./errors.js";import{warn as n}from"./_dev.js";import{isUnsafeObjectKey as r}from"./_prototype.js";function detectEnv(){return typeof window<`u`?`development`:globalThis.process?.env?.NODE_ENV===`production`?`production`:`development`}function remoteTransport(t){let{handler:r}=t,i=t.level??`debug`,a=t.env??detectEnv(),o=t.onError??(e=>n(`remote transport error: ${String(e)}`));return t=>{if(!e(i,t.level))return;let n={data:Object.keys(t.data).length>0?t.data:void 0,env:a,level:t.level,message:t.message,namespace:t.namespace||void 0,timestamp:t.timestamp.toISOString()};Promise.resolve().then(()=>r(t.level,n)).catch(e=>{try{o(e,n)}catch(e){`${String(e)}`}})}}function makeCircularReplacer(){let e=new WeakSet;return(t,n)=>{if(typeof n==`object`&&n){if(e.has(n))return`[Circular]`;e.add(n)}return n}}function jsonTransport(t={}){let n=t.level??`debug`,r=t.fields??{},i=r.level??`level`,a=r.time??`time`,o=r.ns??`ns`,s=r.msg??`msg`,c=t.safe??!1,l=t.output??(e=>{globalThis.process?.stdout?.write(`${e}\n`)});return t=>{if(!e(n,t.level))return;let r={...t.data,[i]:t.level,[a]:t.timestamp.toISOString(),...t.namespace&&{[o]:t.namespace},...t.message!==void 0&&{[s]:t.message}};l(JSON.stringify(r,c?makeCircularReplacer():void 0))}}function assertFiniteNumber(e,n){if(!Number.isFinite(e))throw new t(`${n} must be a finite number`)}function assertNonNegativeInteger(e,n){if(assertFiniteNumber(e,n),!Number.isInteger(e)||e<0)throw new t(`${n} must be a non-negative integer`)}function assertPositiveInteger(e,n){if(assertFiniteNumber(e,n),!Number.isInteger(e)||e<=0)throw new t(`${n} must be a positive integer`)}function batchTransport(n){let r=n.level??`debug`,i=n.maxSize??50,a=n.maxBuffer,o=n.interval??5e3;if(assertFiniteNumber(o,`batchTransport interval`),o<=0)throw new t(`batchTransport interval must be greater than zero`);assertPositiveInteger(i,`batchTransport maxSize`),a!==void 0&&assertNonNegativeInteger(a,`batchTransport maxBuffer`);let s=[],c,l,u=!1,d=Promise.resolve(),f,deliver=async e=>{try{await n.onFlush(e)}catch(t){try{n.onFlushError?.(e,t)}catch(e){`${String(e)}`}throw t}},enqueue=e=>{let t=d.then(()=>deliver(e));return d=t.catch(()=>void 0),t},flush=()=>{if(s.length===0)return d;let e=s;return s=[],enqueue(e)},flushAutomatically=()=>{flush().catch(e=>{l??={error:e}})},transport=t=>{!u&&e(r,t.level)&&(c||=setInterval(flushAutomatically,o),s.push(t),a!==void 0&&s.length>a&&(s=s.slice(s.length-a)),s.length>=i&&flushAutomatically())},p={dispose(){return f||(u=!0,c&&clearInterval(c),c=void 0,f=flush().then(()=>{if(l)throw l.error}),f)},get disposed(){return u},flush,[Symbol.asyncDispose](){return p.dispose()},transport};return p}function sampleTransport(n){let{rate:r,transport:i}=n,a=n.level??`debug`;if(assertFiniteNumber(r,`sampleTransport rate`),r<0||r>1)throw new t(`sampleTransport rate must be between zero and one`);return t=>{e(a,t.level)&&Math.random()<r&&i(t)}}function redactTransport(e){let{keys:t,maxDepth:n=20,replacement:i=`[REDACTED]`,transport:a}=e;assertNonNegativeInteger(n,`redactTransport maxDepth`);for(let e of t)e.includes(`.`)&&`${e}`;let o=new Set(t),s=!1,redact=(e,t)=>{if(typeof e!=`object`||!e)return e;if(t>n)return s||=(`${n}`,!0),i;if(Array.isArray(e))return e.map(e=>redact(e,t+1));let a={};for(let[n,s]of Object.entries(e))r(n)||(a[n]=o.has(n)?i:redact(s,t+1));return a};return e=>a({...e,data:redact(e.data,0)})}export{batchTransport,jsonTransport,redactTransport,remoteTransport,sampleTransport};
|
|
137
2
|
//# sourceMappingURL=transports.js.map
|
package/dist/transports.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transports.js","names":[],"sources":["../src/transports.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { RuneConfigError } from './errors';\nimport type {\n BatchHandle,\n BatchTransportOptions,\n Bindings,\n JsonTransportOptions,\n LogEntry,\n RedactTransportOptions,\n RemoteLogData,\n RemoteTransportOptions,\n SampleTransportOptions,\n Transport,\n} from './types';\nimport { isLevelEnabled } from './types';\n\n/* ─── remoteTransport ─── */\n\nfunction detectEnv(): 'development' | 'production' {\n if (typeof window !== 'undefined') return 'development';\n\n return (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV === 'production'\n ? 'production'\n : 'development';\n}\n\n/** Forward entries asynchronously to a remote delivery handler. */\nexport function remoteTransport(options: RemoteTransportOptions): Transport {\n const { handler } = options;\n const level = options.level ?? 'debug';\n const env = options.env ?? detectEnv();\n const onError = options.onError ?? ((error: unknown) => warn(`remote transport error: ${String(error)}`));\n\n return (entry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const payload: RemoteLogData = {\n data: Object.keys(entry.data).length > 0 ? entry.data : undefined,\n env,\n level: entry.level,\n message: entry.message,\n namespace: entry.namespace || undefined,\n timestamp: entry.timestamp.toISOString(),\n };\n\n Promise.resolve()\n .then(() => handler(entry.level, payload))\n .catch((error: unknown) => {\n try {\n onError(error, payload);\n } catch (observerError) {\n warn(`remote transport error observer threw: ${String(observerError)}`);\n }\n });\n };\n}\n\n/* ─── jsonTransport ─── */\n\nfunction makeCircularReplacer(): (_key: string, value: unknown) => unknown {\n const seen = new WeakSet();\n\n return (_key: string, value: unknown): unknown => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n\n seen.add(value);\n }\n\n return value;\n };\n}\n\n/**\n * Writes newline-delimited JSON (NDJSON) to stdout or a custom output function.\n * Useful for structured log aggregation pipelines in Node.js (ELK, Datadog, etc.).\n *\n * @example\n * jsonTransport({ level: 'info' })\n * jsonTransport({ safe: true }) // handles circular references gracefully\n * jsonTransport({ output: (line) => fs.appendFileSync('app.log', line + '\\n') })\n */\nexport function jsonTransport(options: JsonTransportOptions = {}): Transport {\n const level = options.level ?? 'debug';\n const f = options.fields ?? {};\n const fLevel = f.level ?? 'level';\n const fTime = f.time ?? 'time';\n const fNs = f.ns ?? 'ns';\n const fMsg = f.msg ?? 'msg';\n const safe = options.safe ?? false;\n const output =\n options.output ??\n ((line: string) => {\n (\n globalThis as Record<string, unknown> & { process?: { stdout?: { write: (s: string) => void } } }\n ).process?.stdout?.write(`${line}\\n`);\n });\n\n return (entry: LogEntry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const record: Record<string, unknown> = {\n ...entry.data,\n [fLevel]: entry.level,\n [fTime]: entry.timestamp.toISOString(),\n ...(entry.namespace && { [fNs]: entry.namespace }),\n ...(entry.message !== undefined && { [fMsg]: entry.message }),\n };\n\n output(JSON.stringify(record, safe ? makeCircularReplacer() : undefined));\n };\n}\n\nfunction assertFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value)) throw new RuneConfigError(`${name} must be a finite number`);\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value < 0) throw new RuneConfigError(`${name} must be a non-negative integer`);\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value <= 0) throw new RuneConfigError(`${name} must be a positive integer`);\n}\n\n/* ─── batchTransport ─── */\n\n/** Buffer entries and deliver accepted batches serially. */\nexport function batchTransport(options: BatchTransportOptions): BatchHandle {\n const level = options.level ?? 'debug';\n const maxSize = options.maxSize ?? 50;\n const maxBuffer = options.maxBuffer;\n const interval = options.interval ?? 5000;\n\n assertFiniteNumber(interval, 'batchTransport interval');\n if (interval <= 0) throw new RuneConfigError('batchTransport interval must be greater than zero');\n assertPositiveInteger(maxSize, 'batchTransport maxSize');\n if (maxBuffer !== undefined) assertNonNegativeInteger(maxBuffer, 'batchTransport maxBuffer');\n\n let buffer: LogEntry[] = [];\n let timer: ReturnType<typeof setInterval> | undefined;\n let automaticFailure: { error: unknown } | undefined;\n let disposed = false;\n let deliveryTail: Promise<void> = Promise.resolve();\n let disposePromise: Promise<void> | undefined;\n\n const deliver = async (entries: LogEntry[]): Promise<void> => {\n try {\n await options.onFlush(entries);\n } catch (error) {\n try {\n options.onFlushError?.(entries, error);\n } catch (observerError) {\n warn(`batch transport error observer threw: ${String(observerError)}`);\n }\n throw error;\n }\n };\n\n const enqueue = (entries: LogEntry[]): Promise<void> => {\n const delivery = deliveryTail.then(() => deliver(entries));\n deliveryTail = delivery.catch(() => undefined);\n return delivery;\n };\n\n const flush = (): Promise<void> => {\n if (buffer.length === 0) return deliveryTail;\n\n const entries = buffer;\n buffer = [];\n return enqueue(entries);\n };\n\n const flushAutomatically = (): void => {\n void flush().catch((error: unknown) => {\n automaticFailure ??= { error };\n });\n };\n\n const transport: Transport = (entry): void => {\n if (disposed || !isLevelEnabled(level, entry.level)) return;\n\n if (!timer) timer = setInterval(flushAutomatically, interval);\n buffer.push(entry);\n\n if (maxBuffer !== undefined && buffer.length > maxBuffer) buffer = buffer.slice(buffer.length - maxBuffer);\n if (buffer.length >= maxSize) flushAutomatically();\n };\n\n const handle: BatchHandle = {\n dispose(): Promise<void> {\n if (disposePromise) return disposePromise;\n\n disposed = true;\n if (timer) clearInterval(timer);\n timer = undefined;\n disposePromise = flush().then(() => {\n if (automaticFailure) throw automaticFailure.error;\n });\n return disposePromise;\n },\n get disposed(): boolean {\n return disposed;\n },\n flush,\n [Symbol.asyncDispose](): Promise<void> {\n return handle.dispose();\n },\n transport,\n };\n\n return handle;\n}\n\n/* ─── sampleTransport ─── */\n\n/** Forward a random fraction of entries to a downstream transport. */\nexport function sampleTransport(options: SampleTransportOptions): Transport {\n const { rate, transport } = options;\n const level = options.level ?? 'debug';\n\n assertFiniteNumber(rate, 'sampleTransport rate');\n if (rate < 0 || rate > 1) throw new RuneConfigError('sampleTransport rate must be between zero and one');\n\n return (entry): void => {\n if (isLevelEnabled(level, entry.level) && Math.random() < rate) transport(entry);\n };\n}\n\n/* ─── redactTransport ─── */\n\nexport function redactTransport(options: RedactTransportOptions): Transport {\n const { keys, maxDepth = 20, replacement = '[REDACTED]', transport } = options;\n\n assertNonNegativeInteger(maxDepth, 'redactTransport maxDepth');\n\n for (const key of keys) {\n if (key.includes('.')) {\n warn(`redactTransport: key \"${key}\" contains a dot; keys match exact field names, not paths`);\n }\n }\n\n const keySet = new Set(keys);\n let warnedAboutDepth = false;\n\n const redact = (value: unknown, depth: number): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n\n if (depth > maxDepth) {\n if (!warnedAboutDepth) {\n warn(`redactTransport: object nesting depth exceeded ${maxDepth}; deeper subtrees were redacted entirely`);\n warnedAboutDepth = true;\n }\n return replacement;\n }\n\n if (Array.isArray(value)) return value.map((item) => redact(item, depth + 1));\n\n const result: Bindings = {};\n for (const [key, item] of Object.entries(value)) {\n if (isUnsafeObjectKey(key)) continue;\n result[key] = keySet.has(key) ? replacement : redact(item, depth + 1);\n }\n return result;\n };\n\n return (entry) => transport({ ...entry, data: redact(entry.data, 0) as Bindings });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transports.js","names":[],"sources":["../src/transports.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { isUnsafeObjectKey } from './_prototype';\nimport { RuneConfigError } from './errors';\nimport type {\n BatchHandle,\n BatchTransportOptions,\n Bindings,\n JsonTransportOptions,\n LogEntry,\n RedactTransportOptions,\n RemoteLogData,\n RemoteTransportOptions,\n SampleTransportOptions,\n Transport,\n} from './types';\nimport { isLevelEnabled } from './types';\n\n/* ─── remoteTransport ─── */\n\nfunction detectEnv(): 'development' | 'production' {\n if (typeof window !== 'undefined') return 'development';\n\n return (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV === 'production'\n ? 'production'\n : 'development';\n}\n\n/** Forward entries asynchronously to a remote delivery handler. */\nexport function remoteTransport(options: RemoteTransportOptions): Transport {\n const { handler } = options;\n const level = options.level ?? 'debug';\n const env = options.env ?? detectEnv();\n const onError = options.onError ?? ((error: unknown) => warn(`remote transport error: ${String(error)}`));\n\n return (entry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const payload: RemoteLogData = {\n data: Object.keys(entry.data).length > 0 ? entry.data : undefined,\n env,\n level: entry.level,\n message: entry.message,\n namespace: entry.namespace || undefined,\n timestamp: entry.timestamp.toISOString(),\n };\n\n Promise.resolve()\n .then(() => handler(entry.level, payload))\n .catch((error: unknown) => {\n try {\n onError(error, payload);\n } catch (observerError) {\n warn(`remote transport error observer threw: ${String(observerError)}`);\n }\n });\n };\n}\n\n/* ─── jsonTransport ─── */\n\nfunction makeCircularReplacer(): (_key: string, value: unknown) => unknown {\n const seen = new WeakSet();\n\n return (_key: string, value: unknown): unknown => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n\n seen.add(value);\n }\n\n return value;\n };\n}\n\n/**\n * Writes newline-delimited JSON (NDJSON) to stdout or a custom output function.\n * Useful for structured log aggregation pipelines in Node.js (ELK, Datadog, etc.).\n *\n * @example\n * jsonTransport({ level: 'info' })\n * jsonTransport({ safe: true }) // handles circular references gracefully\n * jsonTransport({ output: (line) => fs.appendFileSync('app.log', line + '\\n') })\n */\nexport function jsonTransport(options: JsonTransportOptions = {}): Transport {\n const level = options.level ?? 'debug';\n const f = options.fields ?? {};\n const fLevel = f.level ?? 'level';\n const fTime = f.time ?? 'time';\n const fNs = f.ns ?? 'ns';\n const fMsg = f.msg ?? 'msg';\n const safe = options.safe ?? false;\n const output =\n options.output ??\n ((line: string) => {\n (\n globalThis as Record<string, unknown> & { process?: { stdout?: { write: (s: string) => void } } }\n ).process?.stdout?.write(`${line}\\n`);\n });\n\n return (entry: LogEntry): void => {\n if (!isLevelEnabled(level, entry.level)) return;\n\n const record: Record<string, unknown> = {\n ...entry.data,\n [fLevel]: entry.level,\n [fTime]: entry.timestamp.toISOString(),\n ...(entry.namespace && { [fNs]: entry.namespace }),\n ...(entry.message !== undefined && { [fMsg]: entry.message }),\n };\n\n output(JSON.stringify(record, safe ? makeCircularReplacer() : undefined));\n };\n}\n\nfunction assertFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value)) throw new RuneConfigError(`${name} must be a finite number`);\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value < 0) throw new RuneConfigError(`${name} must be a non-negative integer`);\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n assertFiniteNumber(value, name);\n if (!Number.isInteger(value) || value <= 0) throw new RuneConfigError(`${name} must be a positive integer`);\n}\n\n/* ─── batchTransport ─── */\n\n/** Buffer entries and deliver accepted batches serially. */\nexport function batchTransport(options: BatchTransportOptions): BatchHandle {\n const level = options.level ?? 'debug';\n const maxSize = options.maxSize ?? 50;\n const maxBuffer = options.maxBuffer;\n const interval = options.interval ?? 5000;\n\n assertFiniteNumber(interval, 'batchTransport interval');\n if (interval <= 0) throw new RuneConfigError('batchTransport interval must be greater than zero');\n assertPositiveInteger(maxSize, 'batchTransport maxSize');\n if (maxBuffer !== undefined) assertNonNegativeInteger(maxBuffer, 'batchTransport maxBuffer');\n\n let buffer: LogEntry[] = [];\n let timer: ReturnType<typeof setInterval> | undefined;\n let automaticFailure: { error: unknown } | undefined;\n let disposed = false;\n let deliveryTail: Promise<void> = Promise.resolve();\n let disposePromise: Promise<void> | undefined;\n\n const deliver = async (entries: LogEntry[]): Promise<void> => {\n try {\n await options.onFlush(entries);\n } catch (error) {\n try {\n options.onFlushError?.(entries, error);\n } catch (observerError) {\n warn(`batch transport error observer threw: ${String(observerError)}`);\n }\n throw error;\n }\n };\n\n const enqueue = (entries: LogEntry[]): Promise<void> => {\n const delivery = deliveryTail.then(() => deliver(entries));\n deliveryTail = delivery.catch(() => undefined);\n return delivery;\n };\n\n const flush = (): Promise<void> => {\n if (buffer.length === 0) return deliveryTail;\n\n const entries = buffer;\n buffer = [];\n return enqueue(entries);\n };\n\n const flushAutomatically = (): void => {\n void flush().catch((error: unknown) => {\n automaticFailure ??= { error };\n });\n };\n\n const transport: Transport = (entry): void => {\n if (disposed || !isLevelEnabled(level, entry.level)) return;\n\n if (!timer) timer = setInterval(flushAutomatically, interval);\n buffer.push(entry);\n\n if (maxBuffer !== undefined && buffer.length > maxBuffer) buffer = buffer.slice(buffer.length - maxBuffer);\n if (buffer.length >= maxSize) flushAutomatically();\n };\n\n const handle: BatchHandle = {\n dispose(): Promise<void> {\n if (disposePromise) return disposePromise;\n\n disposed = true;\n if (timer) clearInterval(timer);\n timer = undefined;\n disposePromise = flush().then(() => {\n if (automaticFailure) throw automaticFailure.error;\n });\n return disposePromise;\n },\n get disposed(): boolean {\n return disposed;\n },\n flush,\n [Symbol.asyncDispose](): Promise<void> {\n return handle.dispose();\n },\n transport,\n };\n\n return handle;\n}\n\n/* ─── sampleTransport ─── */\n\n/** Forward a random fraction of entries to a downstream transport. */\nexport function sampleTransport(options: SampleTransportOptions): Transport {\n const { rate, transport } = options;\n const level = options.level ?? 'debug';\n\n assertFiniteNumber(rate, 'sampleTransport rate');\n if (rate < 0 || rate > 1) throw new RuneConfigError('sampleTransport rate must be between zero and one');\n\n return (entry): void => {\n if (isLevelEnabled(level, entry.level) && Math.random() < rate) transport(entry);\n };\n}\n\n/* ─── redactTransport ─── */\n\nexport function redactTransport(options: RedactTransportOptions): Transport {\n const { keys, maxDepth = 20, replacement = '[REDACTED]', transport } = options;\n\n assertNonNegativeInteger(maxDepth, 'redactTransport maxDepth');\n\n for (const key of keys) {\n if (key.includes('.')) {\n warn(`redactTransport: key \"${key}\" contains a dot; keys match exact field names, not paths`);\n }\n }\n\n const keySet = new Set(keys);\n let warnedAboutDepth = false;\n\n const redact = (value: unknown, depth: number): unknown => {\n if (typeof value !== 'object' || value === null) return value;\n\n if (depth > maxDepth) {\n if (!warnedAboutDepth) {\n warn(`redactTransport: object nesting depth exceeded ${maxDepth}; deeper subtrees were redacted entirely`);\n warnedAboutDepth = true;\n }\n return replacement;\n }\n\n if (Array.isArray(value)) return value.map((item) => redact(item, depth + 1));\n\n const result: Bindings = {};\n for (const [key, item] of Object.entries(value)) {\n if (isUnsafeObjectKey(key)) continue;\n result[key] = keySet.has(key) ? replacement : redact(item, depth + 1);\n }\n return result;\n };\n\n return (entry) => transport({ ...entry, data: redact(entry.data, 0) as Bindings });\n}\n"],"mappings":"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"}
|
package/dist/types.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={debug:0,error:3,fatal:4,info:1,off:5,warn:2};function
|
|
1
|
+
var e={debug:0,error:3,fatal:4,info:1,off:5,warn:2};function isLevelEnabled(t,n){return n!==`off`&&e[t]<=e[n]}exports.PRIORITY=e,exports.isLevelEnabled=isLevelEnabled;
|
|
2
2
|
//# sourceMappingURL=types.cjs.map
|
package/dist/types.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/* ─── Log levels ─── */\n\nexport type LogType = 'debug' | 'error' | 'fatal' | 'info' | 'warn';\nexport type LogLevel = LogType | 'off';\n\n/** Numeric priority for each level. Lower = more verbose. Exported for transport authors. */\nexport const PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\n/** Returns true if `level` passes the `threshold`. Returns false when `level` is 'off'. Exported for transport authors. */\nexport function isLevelEnabled(threshold: LogLevel, level: LogLevel): boolean {\n if (level === 'off') return false;\n\n return PRIORITY[threshold] <= PRIORITY[level];\n}\n\n/* ─── Bindings ─── */\n\nexport type Bindings = Record<string, unknown>;\n\n/* ─── Log entry ─── */\n\n/**\n * The structured record produced by every log call and dispatched to all transports.\n * `data` is the merged result of pinned bindings and per-call context — transports\n * receive a single flat object and do not need to merge anything themselves.\n * Any `Error` instances — whether from a pinned binding (`bindings`/`withBindings()`) or\n * per-call context — are automatically serialized to `{ message, name, stack }`.\n * **Shallow only** — an `Error` nested inside a plain object (e.g. `{ meta: { err } }`) is left as-is;\n * only top-level fields of `data` are checked.\n */\nexport type LogEntry = {\n /**\n * Merged structured data: pinned bindings overlaid with per-call context.\n * Already shallow-copied and immutable — do not mutate.\n */\n data: Readonly<Bindings>;\n level: LogType;\n message?: string;\n namespace: string;\n /** Exact moment of the log call — shared across all transports for the same entry. */\n timestamp: Date;\n};\n\n/* ─── Transport ─── */\n\n/**\n * A transport receives a log entry and is responsible for its own delivery and formatting.\n * If a transport throws, the logger catches it, reports it via a dev-only warning, and continues\n * dispatching the entry to remaining transports — a single misbehaving transport can never crash\n * the caller of `log.info()`/etc. or block its siblings.\n */\nexport type Transport = (entry: LogEntry) => void;\n\n/** Transform or filter entries before dispatch. Return `null` to drop an entry. */\nexport type LogMiddleware = (entry: LogEntry) => LogEntry | null;\n\n/* ─── Transport option types ─── */\n\nexport type RemoteLogData = {\n data?: Readonly<Bindings>;\n env: 'development' | 'production';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp: string;\n};\n\nexport type RemoteTransportOptions = {\n /** Override the detected runtime environment. Default: auto-detected. */\n env?: 'development' | 'production';\n /** Remote delivery handler. */\n handler: (type: LogType, data: RemoteLogData) => void | Promise<unknown>;\n /** Minimum level to forward. Default: 'debug'. */\n level?: LogLevel;\n /** Observe synchronous throws and asynchronous rejections from `handler`. */\n onError?: (error: unknown, data: RemoteLogData) => void;\n};\n\nexport type JsonTransportOptions = {\n /**\n * Custom output field names. Useful for adapting to aggregator conventions\n * (Datadog, ELK, Loki, etc.).\n *\n * @example\n * jsonTransport({ fields: { level: 'severity', time: '@timestamp', msg: 'message' } })\n */\n fields?: {\n level?: string;\n msg?: string;\n ns?: string;\n time?: string;\n };\n /** Minimum level to output. Default: 'debug'. */\n level?: LogLevel;\n /** Custom output function. Default: process.stdout.write. */\n output?: (line: string) => void;\n /**\n * Replace circular references with `'[Circular]'` instead of throwing a TypeError.\n * Useful in environments where log payloads may contain complex object graphs.\n * Default: false.\n */\n safe?: boolean;\n};\n\n/** Handle returned by `batchTransport()`. */\nexport type BatchHandle = {\n [Symbol.asyncDispose]: () => Promise<void>;\n dispose: () => Promise<void>;\n readonly disposed: boolean;\n flush: () => Promise<void>;\n transport: Transport;\n};\n\nexport type BatchTransportOptions = {\n /** Flush interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Minimum level to buffer. Default: 'debug'. */\n level?: LogLevel;\n /** Hard limit on buffered entries. Oldest entries are dropped first. Default: unbounded. */\n maxBuffer?: number;\n /** Flush once this many entries are buffered. Default: 50. */\n maxSize?: number;\n /** Deliver one accepted batch. Batches are delivered serially. */\n onFlush: (entries: LogEntry[]) => void | Promise<void>;\n /** Observe delivery failures. Manual failures reject `flush()`; automatic failures reject `dispose()`. */\n onFlushError?: (entries: LogEntry[], error: unknown) => void;\n};\n\nexport type SampleTransportOptions = {\n /** Minimum level to sample. Default: 'debug'. */\n level?: LogLevel;\n /** Finite fraction of entries to forward, from 0 to 1. */\n rate: number;\n transport: Transport;\n};\n\nexport type RedactTransportOptions = {\n /** Exact field names to replace at any depth. */\n keys: readonly string[];\n /** Maximum nested object depth to inspect. Deeper subtrees are replaced entirely. Default: 20. */\n maxDepth?: number;\n /** Replacement used for matching fields and depth-limited subtrees. Default: '[REDACTED]'. */\n replacement?: string;\n transport: Transport;\n};\n\n/* ─── Logger options ─── */\n\nexport type RuneOptions = {\n /** Initial pinned bindings for this logger instance. `Error` values are auto-serialized, same as per-call context. */\n bindings?: Bindings;\n /** Minimum log level for this logger instance. Default: 'debug'. */\n logLevel?: LogLevel;\n /** Middleware applied once, in order, before dispatch to every transport. */\n middleware?: LogMiddleware[];\n /**\n * Namespace for this logger. When passed to `child()`, it is automatically\n * dot-joined to the parent namespace (e.g. parent `'api'` + child `'auth'` → `'api.auth'`).\n */\n namespace?: string;\n /**\n * Transport pipeline. Each transport receives every entry that passes the level threshold.\n * Default: [consoleTransport()].\n */\n transports?: Transport[];\n};\n\n/* ─── Log method ─── */\n\n/**\n * Signature shared by all five log-level methods.\n *\n * Message-first calls are preferred for ordinary application logging. Context-first and error-first\n * calls support structured events, adapters, and error forwarding without synthetic messages.\n * `Error` values in context are serialized shallowly to `{ message, name, stack }`.\n *\n * @example\n * log.info('request started', { requestId: 'abc' })\n * log.debug(event, `bus:${event.type}`)\n * log.error(new Error('timeout'), { requestId: 'abc' }, 'request failed')\n */\nexport type LogMethod = {\n (message: string, context?: Bindings): void;\n (error: Error, message?: string): void;\n (error: Error, context: Bindings, message?: string): void;\n (context: Bindings, message?: string): void;\n};\n\n/* ─── Logger interface ─── */\n\nexport type Logger = {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose]: () => void;\n /** Snapshot of currently pinned bindings. */\n readonly bindings: Readonly<Bindings>;\n /** Create a child logger with config overrides. Inherits all config and bindings by default. */\n child: (overrides?: RuneOptions) => Logger;\n debug: LogMethod;\n /** `AbortSignal` aborted when `dispose()` is called. Use to tie external lifetimes to this logger. */\n readonly disposalSignal: AbortSignal;\n /**\n * Marks the logger as disposed — all subsequent log calls become no-ops.\n * Aborts `disposalSignal`. Idempotent — safe to call multiple times.\n */\n dispose: () => void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Returns true if entries at this level will pass the configured threshold. */\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n /**\n * Wrap a callback in a console group, closing it even on throw/reject.\n * Pass a `level` to gate the group header on the configured log threshold\n * (e.g. `level: 'debug'` suppresses the group when `logLevel` is above `'debug'`).\n * Default: always renders (unless `logLevel` is `'off'`).\n */\n group: <T>(label: string, fn: () => T, level?: LogType) => T;\n /**\n * Same as `group`, using `console.groupCollapsed`.\n * Pass a `level` to gate the group on the configured log threshold.\n */\n groupCollapsed: <T>(label: string, fn: () => T, level?: LogType) => T;\n info: LogMethod;\n /** Active log level for this logger instance. */\n readonly logLevel: LogLevel;\n /** Middleware pipeline snapshot. */\n readonly middleware: readonly LogMiddleware[];\n /** Namespace string for this logger instance. */\n readonly namespace: string;\n /**\n * Measure execution time of `fn` and emit a structured log entry.\n * The entry message is `label`; `data` contains `{ duration_ms }` (rounded to 2 dp).\n * When `fn` throws or rejects, `data` also includes `{ err }` with the serialized error.\n * @param label - Human-readable description of the operation.\n * @param fn - Synchronous or async function to time.\n * @param level - Log level for the timing entry. Default: `'debug'`.\n */\n time: <T>(label: string, fn: () => T, level?: LogType) => T;\n /** Transport pipeline for this logger instance. */\n readonly transports: readonly Transport[];\n /** Return a new logger with one additional middleware function. */\n use: (middleware: LogMiddleware) => Logger;\n warn: LogMethod;\n /**\n * Derive a child logger with additional pinned bindings.\n * The returned logger is fully independent — disposing it does not affect the parent,\n * and disposing the parent does not affect child loggers.\n */\n withBindings: (bindings: Bindings) => Logger;\n};\n"],"mappings":"AAMA,IAAa,EAAqC,CAChD,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,EACN,IAAK,EACL,KAAM,CACR,EAGA,SAAgB,EAAe,EAAqB,EAA0B,CAG5E,OAFI,IAAU,OAEP,EAAS,IAAc,EAAS,EACzC"}
|
|
1
|
+
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/* ─── Log levels ─── */\n\nexport type LogType = 'debug' | 'error' | 'fatal' | 'info' | 'warn';\nexport type LogLevel = LogType | 'off';\n\n/** Numeric priority for each level. Lower = more verbose. Exported for transport authors. */\nexport const PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\n/** Returns true if `level` passes the `threshold`. Returns false when `level` is 'off'. Exported for transport authors. */\nexport function isLevelEnabled(threshold: LogLevel, level: LogLevel): boolean {\n if (level === 'off') return false;\n\n return PRIORITY[threshold] <= PRIORITY[level];\n}\n\n/* ─── Bindings ─── */\n\nexport type Bindings = Record<string, unknown>;\n\n/* ─── Log entry ─── */\n\n/**\n * The structured record produced by every log call and dispatched to all transports.\n * `data` is the merged result of pinned bindings and per-call context: transports\n * receive a single flat object and do not need to merge anything themselves.\n * Any `Error` instances: whether from a pinned binding (`bindings`/`withBindings()`) or\n * per-call context: are automatically serialized to `{ message, name, stack }`.\n * **Shallow only**: an `Error` nested inside a plain object (e.g. `{ meta: { err } }`) is left as-is;\n * only top-level fields of `data` are checked.\n */\nexport type LogEntry = {\n /**\n * Merged structured data: pinned bindings overlaid with per-call context.\n * Already shallow-copied and immutable: do not mutate.\n */\n data: Readonly<Bindings>;\n level: LogType;\n message?: string;\n namespace: string;\n /** Exact moment of the log call: shared across all transports for the same entry. */\n timestamp: Date;\n};\n\n/* ─── Transport ─── */\n\n/**\n * A transport receives a log entry and is responsible for its own delivery and formatting.\n * If a transport throws, the logger catches it, reports it via a dev-only warning, and continues\n * dispatching the entry to remaining transports: a single misbehaving transport can never crash\n * the caller of `log.info()`/etc. or block its siblings.\n */\nexport type Transport = (entry: LogEntry) => void;\n\n/** Transform or filter entries before dispatch. Return `null` to drop an entry. */\nexport type LogMiddleware = (entry: LogEntry) => LogEntry | null;\n\n/* ─── Transport option types ─── */\n\nexport type RemoteLogData = {\n data?: Readonly<Bindings>;\n env: 'development' | 'production';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp: string;\n};\n\nexport type RemoteTransportOptions = {\n /** Override the detected runtime environment. Default: auto-detected. */\n env?: 'development' | 'production';\n /** Remote delivery handler. */\n handler: (type: LogType, data: RemoteLogData) => void | Promise<unknown>;\n /** Minimum level to forward. Default: 'debug'. */\n level?: LogLevel;\n /** Observe synchronous throws and asynchronous rejections from `handler`. */\n onError?: (error: unknown, data: RemoteLogData) => void;\n};\n\nexport type JsonTransportOptions = {\n /**\n * Custom output field names. Useful for adapting to aggregator conventions\n * (Datadog, ELK, Loki, etc.).\n *\n * @example\n * jsonTransport({ fields: { level: 'severity', time: '@timestamp', msg: 'message' } })\n */\n fields?: {\n level?: string;\n msg?: string;\n ns?: string;\n time?: string;\n };\n /** Minimum level to output. Default: 'debug'. */\n level?: LogLevel;\n /** Custom output function. Default: process.stdout.write. */\n output?: (line: string) => void;\n /**\n * Replace circular references with `'[Circular]'` instead of throwing a TypeError.\n * Useful in environments where log payloads may contain complex object graphs.\n * Default: false.\n */\n safe?: boolean;\n};\n\n/** Handle returned by `batchTransport()`. */\nexport type BatchHandle = {\n [Symbol.asyncDispose]: () => Promise<void>;\n dispose: () => Promise<void>;\n readonly disposed: boolean;\n flush: () => Promise<void>;\n transport: Transport;\n};\n\nexport type BatchTransportOptions = {\n /** Flush interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Minimum level to buffer. Default: 'debug'. */\n level?: LogLevel;\n /** Hard limit on buffered entries. Oldest entries are dropped first. Default: unbounded. */\n maxBuffer?: number;\n /** Flush once this many entries are buffered. Default: 50. */\n maxSize?: number;\n /** Deliver one accepted batch. Batches are delivered serially. */\n onFlush: (entries: LogEntry[]) => void | Promise<void>;\n /** Observe delivery failures. Manual failures reject `flush()`; automatic failures reject `dispose()`. */\n onFlushError?: (entries: LogEntry[], error: unknown) => void;\n};\n\nexport type SampleTransportOptions = {\n /** Minimum level to sample. Default: 'debug'. */\n level?: LogLevel;\n /** Finite fraction of entries to forward, from 0 to 1. */\n rate: number;\n transport: Transport;\n};\n\nexport type RedactTransportOptions = {\n /** Exact field names to replace at any depth. */\n keys: readonly string[];\n /** Maximum nested object depth to inspect. Deeper subtrees are replaced entirely. Default: 20. */\n maxDepth?: number;\n /** Replacement used for matching fields and depth-limited subtrees. Default: '[REDACTED]'. */\n replacement?: string;\n transport: Transport;\n};\n\n/* ─── Logger options ─── */\n\nexport type RuneOptions = {\n /** Initial pinned bindings for this logger instance. `Error` values are auto-serialized, same as per-call context. */\n bindings?: Bindings;\n /** Minimum log level for this logger instance. Default: 'debug'. */\n logLevel?: LogLevel;\n /** Middleware applied once, in order, before dispatch to every transport. */\n middleware?: LogMiddleware[];\n /**\n * Namespace for this logger. When passed to `child()`, it is automatically\n * dot-joined to the parent namespace (e.g. parent `'api'` + child `'auth'` → `'api.auth'`).\n */\n namespace?: string;\n /**\n * Transport pipeline. Each transport receives every entry that passes the level threshold.\n * Default: [consoleTransport()].\n */\n transports?: Transport[];\n};\n\n/* ─── Log method ─── */\n\n/**\n * Signature shared by all five log-level methods.\n *\n * Message-first calls are preferred for ordinary application logging. Context-first and error-first\n * calls support structured events, adapters, and error forwarding without synthetic messages.\n * `Error` values in context are serialized shallowly to `{ message, name, stack }`.\n *\n * @example\n * log.info('request started', { requestId: 'abc' })\n * log.debug(event, `bus:${event.type}`)\n * log.error(new Error('timeout'), { requestId: 'abc' }, 'request failed')\n */\nexport type LogMethod = {\n (message: string, context?: Bindings): void;\n (error: Error, message?: string): void;\n (error: Error, context: Bindings, message?: string): void;\n (context: Bindings, message?: string): void;\n};\n\n/* ─── Logger interface ─── */\n\nexport type Logger = {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose]: () => void;\n /** Snapshot of currently pinned bindings. */\n readonly bindings: Readonly<Bindings>;\n /** Create a child logger with config overrides. Inherits all config and bindings by default. */\n child: (overrides?: RuneOptions) => Logger;\n debug: LogMethod;\n /** `AbortSignal` aborted when `dispose()` is called. Use to tie external lifetimes to this logger. */\n readonly disposalSignal: AbortSignal;\n /**\n * Marks the logger as disposed: all subsequent log calls become no-ops.\n * Aborts `disposalSignal`. Idempotent: safe to call multiple times.\n */\n dispose: () => void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Returns true if entries at this level will pass the configured threshold. */\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n /**\n * Wrap a callback in a console group, closing it even on throw/reject.\n * Pass a `level` to gate the group header on the configured log threshold\n * (e.g. `level: 'debug'` suppresses the group when `logLevel` is above `'debug'`).\n * Default: always renders (unless `logLevel` is `'off'`).\n */\n group: <T>(label: string, fn: () => T, level?: LogType) => T;\n /**\n * Same as `group`, using `console.groupCollapsed`.\n * Pass a `level` to gate the group on the configured log threshold.\n */\n groupCollapsed: <T>(label: string, fn: () => T, level?: LogType) => T;\n info: LogMethod;\n /** Active log level for this logger instance. */\n readonly logLevel: LogLevel;\n /** Middleware pipeline snapshot. */\n readonly middleware: readonly LogMiddleware[];\n /** Namespace string for this logger instance. */\n readonly namespace: string;\n /**\n * Measure execution time of `fn` and emit a structured log entry.\n * The entry message is `label`; `data` contains `{ duration_ms }` (rounded to 2 dp).\n * When `fn` throws or rejects, `data` also includes `{ err }` with the serialized error.\n * @param label - Human-readable description of the operation.\n * @param fn - Synchronous or async function to time.\n * @param level - Log level for the timing entry. Default: `'debug'`.\n */\n time: <T>(label: string, fn: () => T, level?: LogType) => T;\n /** Transport pipeline for this logger instance. */\n readonly transports: readonly Transport[];\n /** Return a new logger with one additional middleware function. */\n use: (middleware: LogMiddleware) => Logger;\n warn: LogMethod;\n /**\n * Derive a child logger with additional pinned bindings.\n * The returned logger is fully independent: disposing it does not affect the parent,\n * and disposing the parent does not affect child loggers.\n */\n withBindings: (bindings: Bindings) => Logger;\n};\n"],"mappings":"AAMA,IAAa,EAAqC,CAChD,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,EACN,IAAK,EACL,KAAM,CACR,EAGA,SAAgB,eAAe,EAAqB,EAA0B,CAG5E,OAFI,IAAU,OAEP,EAAS,IAAc,EAAS,EACzC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,29 +7,29 @@ export declare function isLevelEnabled(threshold: LogLevel, level: LogLevel): bo
|
|
|
7
7
|
export type Bindings = Record<string, unknown>;
|
|
8
8
|
/**
|
|
9
9
|
* The structured record produced by every log call and dispatched to all transports.
|
|
10
|
-
* `data` is the merged result of pinned bindings and per-call context
|
|
10
|
+
* `data` is the merged result of pinned bindings and per-call context: transports
|
|
11
11
|
* receive a single flat object and do not need to merge anything themselves.
|
|
12
|
-
* Any `Error` instances
|
|
13
|
-
* per-call context
|
|
14
|
-
* **Shallow only
|
|
12
|
+
* Any `Error` instances: whether from a pinned binding (`bindings`/`withBindings()`) or
|
|
13
|
+
* per-call context: are automatically serialized to `{ message, name, stack }`.
|
|
14
|
+
* **Shallow only**: an `Error` nested inside a plain object (e.g. `{ meta: { err } }`) is left as-is;
|
|
15
15
|
* only top-level fields of `data` are checked.
|
|
16
16
|
*/
|
|
17
17
|
export type LogEntry = {
|
|
18
18
|
/**
|
|
19
19
|
* Merged structured data: pinned bindings overlaid with per-call context.
|
|
20
|
-
* Already shallow-copied and immutable
|
|
20
|
+
* Already shallow-copied and immutable: do not mutate.
|
|
21
21
|
*/
|
|
22
22
|
data: Readonly<Bindings>;
|
|
23
23
|
level: LogType;
|
|
24
24
|
message?: string;
|
|
25
25
|
namespace: string;
|
|
26
|
-
/** Exact moment of the log call
|
|
26
|
+
/** Exact moment of the log call: shared across all transports for the same entry. */
|
|
27
27
|
timestamp: Date;
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
30
|
* A transport receives a log entry and is responsible for its own delivery and formatting.
|
|
31
31
|
* If a transport throws, the logger catches it, reports it via a dev-only warning, and continues
|
|
32
|
-
* dispatching the entry to remaining transports
|
|
32
|
+
* dispatching the entry to remaining transports: a single misbehaving transport can never crash
|
|
33
33
|
* the caller of `log.info()`/etc. or block its siblings.
|
|
34
34
|
*/
|
|
35
35
|
export type Transport = (entry: LogEntry) => void;
|
|
@@ -163,8 +163,8 @@ export type Logger = {
|
|
|
163
163
|
/** `AbortSignal` aborted when `dispose()` is called. Use to tie external lifetimes to this logger. */
|
|
164
164
|
readonly disposalSignal: AbortSignal;
|
|
165
165
|
/**
|
|
166
|
-
* Marks the logger as disposed
|
|
167
|
-
* Aborts `disposalSignal`. Idempotent
|
|
166
|
+
* Marks the logger as disposed: all subsequent log calls become no-ops.
|
|
167
|
+
* Aborts `disposalSignal`. Idempotent: safe to call multiple times.
|
|
168
168
|
*/
|
|
169
169
|
dispose: () => void;
|
|
170
170
|
/** `true` after `dispose()` has been called. */
|
|
@@ -208,7 +208,7 @@ export type Logger = {
|
|
|
208
208
|
warn: LogMethod;
|
|
209
209
|
/**
|
|
210
210
|
* Derive a child logger with additional pinned bindings.
|
|
211
|
-
* The returned logger is fully independent
|
|
211
|
+
* The returned logger is fully independent: disposing it does not affect the parent,
|
|
212
212
|
* and disposing the parent does not affect child loggers.
|
|
213
213
|
*/
|
|
214
214
|
withBindings: (bindings: Bindings) => Logger;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AAEvC,6FAA6F;AAC7F,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAO7C,CAAC;AAEF,2HAA2H;AAC3H,wBAAgB,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAI5E;AAID,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAI/C;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB;;;OAGG;IACH,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
var e = {
|
|
3
|
-
debug: 0,
|
|
4
|
-
error: 3,
|
|
5
|
-
fatal: 4,
|
|
6
|
-
info: 1,
|
|
7
|
-
off: 5,
|
|
8
|
-
warn: 2
|
|
9
|
-
};
|
|
10
|
-
function t(t, n) {
|
|
11
|
-
return n !== "off" && e[t] <= e[n];
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
14
|
-
export { e as PRIORITY, t as isLevelEnabled };
|
|
15
|
-
|
|
1
|
+
var e={debug:0,error:3,fatal:4,info:1,off:5,warn:2};function isLevelEnabled(t,n){return n!==`off`&&e[t]<=e[n]}export{e as PRIORITY,isLevelEnabled};
|
|
16
2
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/* ─── Log levels ─── */\n\nexport type LogType = 'debug' | 'error' | 'fatal' | 'info' | 'warn';\nexport type LogLevel = LogType | 'off';\n\n/** Numeric priority for each level. Lower = more verbose. Exported for transport authors. */\nexport const PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\n/** Returns true if `level` passes the `threshold`. Returns false when `level` is 'off'. Exported for transport authors. */\nexport function isLevelEnabled(threshold: LogLevel, level: LogLevel): boolean {\n if (level === 'off') return false;\n\n return PRIORITY[threshold] <= PRIORITY[level];\n}\n\n/* ─── Bindings ─── */\n\nexport type Bindings = Record<string, unknown>;\n\n/* ─── Log entry ─── */\n\n/**\n * The structured record produced by every log call and dispatched to all transports.\n * `data` is the merged result of pinned bindings and per-call context — transports\n * receive a single flat object and do not need to merge anything themselves.\n * Any `Error` instances — whether from a pinned binding (`bindings`/`withBindings()`) or\n * per-call context — are automatically serialized to `{ message, name, stack }`.\n * **Shallow only** — an `Error` nested inside a plain object (e.g. `{ meta: { err } }`) is left as-is;\n * only top-level fields of `data` are checked.\n */\nexport type LogEntry = {\n /**\n * Merged structured data: pinned bindings overlaid with per-call context.\n * Already shallow-copied and immutable — do not mutate.\n */\n data: Readonly<Bindings>;\n level: LogType;\n message?: string;\n namespace: string;\n /** Exact moment of the log call — shared across all transports for the same entry. */\n timestamp: Date;\n};\n\n/* ─── Transport ─── */\n\n/**\n * A transport receives a log entry and is responsible for its own delivery and formatting.\n * If a transport throws, the logger catches it, reports it via a dev-only warning, and continues\n * dispatching the entry to remaining transports — a single misbehaving transport can never crash\n * the caller of `log.info()`/etc. or block its siblings.\n */\nexport type Transport = (entry: LogEntry) => void;\n\n/** Transform or filter entries before dispatch. Return `null` to drop an entry. */\nexport type LogMiddleware = (entry: LogEntry) => LogEntry | null;\n\n/* ─── Transport option types ─── */\n\nexport type RemoteLogData = {\n data?: Readonly<Bindings>;\n env: 'development' | 'production';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp: string;\n};\n\nexport type RemoteTransportOptions = {\n /** Override the detected runtime environment. Default: auto-detected. */\n env?: 'development' | 'production';\n /** Remote delivery handler. */\n handler: (type: LogType, data: RemoteLogData) => void | Promise<unknown>;\n /** Minimum level to forward. Default: 'debug'. */\n level?: LogLevel;\n /** Observe synchronous throws and asynchronous rejections from `handler`. */\n onError?: (error: unknown, data: RemoteLogData) => void;\n};\n\nexport type JsonTransportOptions = {\n /**\n * Custom output field names. Useful for adapting to aggregator conventions\n * (Datadog, ELK, Loki, etc.).\n *\n * @example\n * jsonTransport({ fields: { level: 'severity', time: '@timestamp', msg: 'message' } })\n */\n fields?: {\n level?: string;\n msg?: string;\n ns?: string;\n time?: string;\n };\n /** Minimum level to output. Default: 'debug'. */\n level?: LogLevel;\n /** Custom output function. Default: process.stdout.write. */\n output?: (line: string) => void;\n /**\n * Replace circular references with `'[Circular]'` instead of throwing a TypeError.\n * Useful in environments where log payloads may contain complex object graphs.\n * Default: false.\n */\n safe?: boolean;\n};\n\n/** Handle returned by `batchTransport()`. */\nexport type BatchHandle = {\n [Symbol.asyncDispose]: () => Promise<void>;\n dispose: () => Promise<void>;\n readonly disposed: boolean;\n flush: () => Promise<void>;\n transport: Transport;\n};\n\nexport type BatchTransportOptions = {\n /** Flush interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Minimum level to buffer. Default: 'debug'. */\n level?: LogLevel;\n /** Hard limit on buffered entries. Oldest entries are dropped first. Default: unbounded. */\n maxBuffer?: number;\n /** Flush once this many entries are buffered. Default: 50. */\n maxSize?: number;\n /** Deliver one accepted batch. Batches are delivered serially. */\n onFlush: (entries: LogEntry[]) => void | Promise<void>;\n /** Observe delivery failures. Manual failures reject `flush()`; automatic failures reject `dispose()`. */\n onFlushError?: (entries: LogEntry[], error: unknown) => void;\n};\n\nexport type SampleTransportOptions = {\n /** Minimum level to sample. Default: 'debug'. */\n level?: LogLevel;\n /** Finite fraction of entries to forward, from 0 to 1. */\n rate: number;\n transport: Transport;\n};\n\nexport type RedactTransportOptions = {\n /** Exact field names to replace at any depth. */\n keys: readonly string[];\n /** Maximum nested object depth to inspect. Deeper subtrees are replaced entirely. Default: 20. */\n maxDepth?: number;\n /** Replacement used for matching fields and depth-limited subtrees. Default: '[REDACTED]'. */\n replacement?: string;\n transport: Transport;\n};\n\n/* ─── Logger options ─── */\n\nexport type RuneOptions = {\n /** Initial pinned bindings for this logger instance. `Error` values are auto-serialized, same as per-call context. */\n bindings?: Bindings;\n /** Minimum log level for this logger instance. Default: 'debug'. */\n logLevel?: LogLevel;\n /** Middleware applied once, in order, before dispatch to every transport. */\n middleware?: LogMiddleware[];\n /**\n * Namespace for this logger. When passed to `child()`, it is automatically\n * dot-joined to the parent namespace (e.g. parent `'api'` + child `'auth'` → `'api.auth'`).\n */\n namespace?: string;\n /**\n * Transport pipeline. Each transport receives every entry that passes the level threshold.\n * Default: [consoleTransport()].\n */\n transports?: Transport[];\n};\n\n/* ─── Log method ─── */\n\n/**\n * Signature shared by all five log-level methods.\n *\n * Message-first calls are preferred for ordinary application logging. Context-first and error-first\n * calls support structured events, adapters, and error forwarding without synthetic messages.\n * `Error` values in context are serialized shallowly to `{ message, name, stack }`.\n *\n * @example\n * log.info('request started', { requestId: 'abc' })\n * log.debug(event, `bus:${event.type}`)\n * log.error(new Error('timeout'), { requestId: 'abc' }, 'request failed')\n */\nexport type LogMethod = {\n (message: string, context?: Bindings): void;\n (error: Error, message?: string): void;\n (error: Error, context: Bindings, message?: string): void;\n (context: Bindings, message?: string): void;\n};\n\n/* ─── Logger interface ─── */\n\nexport type Logger = {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose]: () => void;\n /** Snapshot of currently pinned bindings. */\n readonly bindings: Readonly<Bindings>;\n /** Create a child logger with config overrides. Inherits all config and bindings by default. */\n child: (overrides?: RuneOptions) => Logger;\n debug: LogMethod;\n /** `AbortSignal` aborted when `dispose()` is called. Use to tie external lifetimes to this logger. */\n readonly disposalSignal: AbortSignal;\n /**\n * Marks the logger as disposed — all subsequent log calls become no-ops.\n * Aborts `disposalSignal`. Idempotent — safe to call multiple times.\n */\n dispose: () => void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Returns true if entries at this level will pass the configured threshold. */\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n /**\n * Wrap a callback in a console group, closing it even on throw/reject.\n * Pass a `level` to gate the group header on the configured log threshold\n * (e.g. `level: 'debug'` suppresses the group when `logLevel` is above `'debug'`).\n * Default: always renders (unless `logLevel` is `'off'`).\n */\n group: <T>(label: string, fn: () => T, level?: LogType) => T;\n /**\n * Same as `group`, using `console.groupCollapsed`.\n * Pass a `level` to gate the group on the configured log threshold.\n */\n groupCollapsed: <T>(label: string, fn: () => T, level?: LogType) => T;\n info: LogMethod;\n /** Active log level for this logger instance. */\n readonly logLevel: LogLevel;\n /** Middleware pipeline snapshot. */\n readonly middleware: readonly LogMiddleware[];\n /** Namespace string for this logger instance. */\n readonly namespace: string;\n /**\n * Measure execution time of `fn` and emit a structured log entry.\n * The entry message is `label`; `data` contains `{ duration_ms }` (rounded to 2 dp).\n * When `fn` throws or rejects, `data` also includes `{ err }` with the serialized error.\n * @param label - Human-readable description of the operation.\n * @param fn - Synchronous or async function to time.\n * @param level - Log level for the timing entry. Default: `'debug'`.\n */\n time: <T>(label: string, fn: () => T, level?: LogType) => T;\n /** Transport pipeline for this logger instance. */\n readonly transports: readonly Transport[];\n /** Return a new logger with one additional middleware function. */\n use: (middleware: LogMiddleware) => Logger;\n warn: LogMethod;\n /**\n * Derive a child logger with additional pinned bindings.\n * The returned logger is fully independent — disposing it does not affect the parent,\n * and disposing the parent does not affect child loggers.\n */\n withBindings: (bindings: Bindings) => Logger;\n};\n"],"mappings":";AAMA,IAAa,IAAqC;CAChD,OAAO;CACP,OAAO;CACP,OAAO;CACP,MAAM;CACN,KAAK;CACL,MAAM;AACR;AAGA,SAAgB,EAAe,GAAqB,GAA0B;CAG5E,OAFI,MAAU,SAEP,EAAS,MAAc,EAAS;AACzC"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/* ─── Log levels ─── */\n\nexport type LogType = 'debug' | 'error' | 'fatal' | 'info' | 'warn';\nexport type LogLevel = LogType | 'off';\n\n/** Numeric priority for each level. Lower = more verbose. Exported for transport authors. */\nexport const PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\n/** Returns true if `level` passes the `threshold`. Returns false when `level` is 'off'. Exported for transport authors. */\nexport function isLevelEnabled(threshold: LogLevel, level: LogLevel): boolean {\n if (level === 'off') return false;\n\n return PRIORITY[threshold] <= PRIORITY[level];\n}\n\n/* ─── Bindings ─── */\n\nexport type Bindings = Record<string, unknown>;\n\n/* ─── Log entry ─── */\n\n/**\n * The structured record produced by every log call and dispatched to all transports.\n * `data` is the merged result of pinned bindings and per-call context: transports\n * receive a single flat object and do not need to merge anything themselves.\n * Any `Error` instances: whether from a pinned binding (`bindings`/`withBindings()`) or\n * per-call context: are automatically serialized to `{ message, name, stack }`.\n * **Shallow only**: an `Error` nested inside a plain object (e.g. `{ meta: { err } }`) is left as-is;\n * only top-level fields of `data` are checked.\n */\nexport type LogEntry = {\n /**\n * Merged structured data: pinned bindings overlaid with per-call context.\n * Already shallow-copied and immutable: do not mutate.\n */\n data: Readonly<Bindings>;\n level: LogType;\n message?: string;\n namespace: string;\n /** Exact moment of the log call: shared across all transports for the same entry. */\n timestamp: Date;\n};\n\n/* ─── Transport ─── */\n\n/**\n * A transport receives a log entry and is responsible for its own delivery and formatting.\n * If a transport throws, the logger catches it, reports it via a dev-only warning, and continues\n * dispatching the entry to remaining transports: a single misbehaving transport can never crash\n * the caller of `log.info()`/etc. or block its siblings.\n */\nexport type Transport = (entry: LogEntry) => void;\n\n/** Transform or filter entries before dispatch. Return `null` to drop an entry. */\nexport type LogMiddleware = (entry: LogEntry) => LogEntry | null;\n\n/* ─── Transport option types ─── */\n\nexport type RemoteLogData = {\n data?: Readonly<Bindings>;\n env: 'development' | 'production';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp: string;\n};\n\nexport type RemoteTransportOptions = {\n /** Override the detected runtime environment. Default: auto-detected. */\n env?: 'development' | 'production';\n /** Remote delivery handler. */\n handler: (type: LogType, data: RemoteLogData) => void | Promise<unknown>;\n /** Minimum level to forward. Default: 'debug'. */\n level?: LogLevel;\n /** Observe synchronous throws and asynchronous rejections from `handler`. */\n onError?: (error: unknown, data: RemoteLogData) => void;\n};\n\nexport type JsonTransportOptions = {\n /**\n * Custom output field names. Useful for adapting to aggregator conventions\n * (Datadog, ELK, Loki, etc.).\n *\n * @example\n * jsonTransport({ fields: { level: 'severity', time: '@timestamp', msg: 'message' } })\n */\n fields?: {\n level?: string;\n msg?: string;\n ns?: string;\n time?: string;\n };\n /** Minimum level to output. Default: 'debug'. */\n level?: LogLevel;\n /** Custom output function. Default: process.stdout.write. */\n output?: (line: string) => void;\n /**\n * Replace circular references with `'[Circular]'` instead of throwing a TypeError.\n * Useful in environments where log payloads may contain complex object graphs.\n * Default: false.\n */\n safe?: boolean;\n};\n\n/** Handle returned by `batchTransport()`. */\nexport type BatchHandle = {\n [Symbol.asyncDispose]: () => Promise<void>;\n dispose: () => Promise<void>;\n readonly disposed: boolean;\n flush: () => Promise<void>;\n transport: Transport;\n};\n\nexport type BatchTransportOptions = {\n /** Flush interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Minimum level to buffer. Default: 'debug'. */\n level?: LogLevel;\n /** Hard limit on buffered entries. Oldest entries are dropped first. Default: unbounded. */\n maxBuffer?: number;\n /** Flush once this many entries are buffered. Default: 50. */\n maxSize?: number;\n /** Deliver one accepted batch. Batches are delivered serially. */\n onFlush: (entries: LogEntry[]) => void | Promise<void>;\n /** Observe delivery failures. Manual failures reject `flush()`; automatic failures reject `dispose()`. */\n onFlushError?: (entries: LogEntry[], error: unknown) => void;\n};\n\nexport type SampleTransportOptions = {\n /** Minimum level to sample. Default: 'debug'. */\n level?: LogLevel;\n /** Finite fraction of entries to forward, from 0 to 1. */\n rate: number;\n transport: Transport;\n};\n\nexport type RedactTransportOptions = {\n /** Exact field names to replace at any depth. */\n keys: readonly string[];\n /** Maximum nested object depth to inspect. Deeper subtrees are replaced entirely. Default: 20. */\n maxDepth?: number;\n /** Replacement used for matching fields and depth-limited subtrees. Default: '[REDACTED]'. */\n replacement?: string;\n transport: Transport;\n};\n\n/* ─── Logger options ─── */\n\nexport type RuneOptions = {\n /** Initial pinned bindings for this logger instance. `Error` values are auto-serialized, same as per-call context. */\n bindings?: Bindings;\n /** Minimum log level for this logger instance. Default: 'debug'. */\n logLevel?: LogLevel;\n /** Middleware applied once, in order, before dispatch to every transport. */\n middleware?: LogMiddleware[];\n /**\n * Namespace for this logger. When passed to `child()`, it is automatically\n * dot-joined to the parent namespace (e.g. parent `'api'` + child `'auth'` → `'api.auth'`).\n */\n namespace?: string;\n /**\n * Transport pipeline. Each transport receives every entry that passes the level threshold.\n * Default: [consoleTransport()].\n */\n transports?: Transport[];\n};\n\n/* ─── Log method ─── */\n\n/**\n * Signature shared by all five log-level methods.\n *\n * Message-first calls are preferred for ordinary application logging. Context-first and error-first\n * calls support structured events, adapters, and error forwarding without synthetic messages.\n * `Error` values in context are serialized shallowly to `{ message, name, stack }`.\n *\n * @example\n * log.info('request started', { requestId: 'abc' })\n * log.debug(event, `bus:${event.type}`)\n * log.error(new Error('timeout'), { requestId: 'abc' }, 'request failed')\n */\nexport type LogMethod = {\n (message: string, context?: Bindings): void;\n (error: Error, message?: string): void;\n (error: Error, context: Bindings, message?: string): void;\n (context: Bindings, message?: string): void;\n};\n\n/* ─── Logger interface ─── */\n\nexport type Logger = {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose]: () => void;\n /** Snapshot of currently pinned bindings. */\n readonly bindings: Readonly<Bindings>;\n /** Create a child logger with config overrides. Inherits all config and bindings by default. */\n child: (overrides?: RuneOptions) => Logger;\n debug: LogMethod;\n /** `AbortSignal` aborted when `dispose()` is called. Use to tie external lifetimes to this logger. */\n readonly disposalSignal: AbortSignal;\n /**\n * Marks the logger as disposed: all subsequent log calls become no-ops.\n * Aborts `disposalSignal`. Idempotent: safe to call multiple times.\n */\n dispose: () => void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Returns true if entries at this level will pass the configured threshold. */\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n /**\n * Wrap a callback in a console group, closing it even on throw/reject.\n * Pass a `level` to gate the group header on the configured log threshold\n * (e.g. `level: 'debug'` suppresses the group when `logLevel` is above `'debug'`).\n * Default: always renders (unless `logLevel` is `'off'`).\n */\n group: <T>(label: string, fn: () => T, level?: LogType) => T;\n /**\n * Same as `group`, using `console.groupCollapsed`.\n * Pass a `level` to gate the group on the configured log threshold.\n */\n groupCollapsed: <T>(label: string, fn: () => T, level?: LogType) => T;\n info: LogMethod;\n /** Active log level for this logger instance. */\n readonly logLevel: LogLevel;\n /** Middleware pipeline snapshot. */\n readonly middleware: readonly LogMiddleware[];\n /** Namespace string for this logger instance. */\n readonly namespace: string;\n /**\n * Measure execution time of `fn` and emit a structured log entry.\n * The entry message is `label`; `data` contains `{ duration_ms }` (rounded to 2 dp).\n * When `fn` throws or rejects, `data` also includes `{ err }` with the serialized error.\n * @param label - Human-readable description of the operation.\n * @param fn - Synchronous or async function to time.\n * @param level - Log level for the timing entry. Default: `'debug'`.\n */\n time: <T>(label: string, fn: () => T, level?: LogType) => T;\n /** Transport pipeline for this logger instance. */\n readonly transports: readonly Transport[];\n /** Return a new logger with one additional middleware function. */\n use: (middleware: LogMiddleware) => Logger;\n warn: LogMethod;\n /**\n * Derive a child logger with additional pinned bindings.\n * The returned logger is fully independent: disposing it does not affect the parent,\n * and disposing the parent does not affect child loggers.\n */\n withBindings: (bindings: Bindings) => Logger;\n};\n"],"mappings":"AAMA,IAAa,EAAqC,CAChD,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,EACN,IAAK,EACL,KAAM,CACR,EAGA,SAAgB,eAAe,EAAqB,EAA0B,CAG5E,OAFI,IAAU,OAEP,EAAS,IAAc,EAAS,EACzC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/rune",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Structured
|
|
3
|
+
"version": "26.10.1",
|
|
4
|
+
"description": "Structured scoped logger with remote transport",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/helmuthdu/vielzeug",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"test": "vitest"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@types/node": "^26.
|
|
43
|
+
"@types/node": "^26.6.2",
|
|
44
44
|
"typescript": "^6.0.3",
|
|
45
|
-
"vite": "^8.
|
|
46
|
-
"vitest": "^5.0.
|
|
45
|
+
"vite": "^8.3.0",
|
|
46
|
+
"vitest": "^5.0.1"
|
|
47
47
|
}
|
|
48
48
|
}
|