@logtape/testing 2.3.0-dev.818 → 2.3.0-dev.822

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/reporter.cjs CHANGED
@@ -56,7 +56,9 @@ function createFailureLogReporter(options = {}) {
56
56
  return result;
57
57
  }
58
58
  function wrap(callback) {
59
- return (...args) => run(() => callback(...args));
59
+ return function(...args) {
60
+ return run(() => Reflect.apply(callback, this, args));
61
+ };
60
62
  }
61
63
  return {
62
64
  run,
@@ -48,7 +48,7 @@ interface FailureLogReporter {
48
48
  * @param callback The test callback to wrap.
49
49
  * @returns An async callback with the same parameters.
50
50
  */
51
- wrap<TArgs extends readonly unknown[], TResult>(callback: (...args: TArgs) => TResult): (...args: TArgs) => Promise<Awaited<TResult>>;
51
+ wrap<TThis, TArgs extends readonly unknown[], TResult>(callback: (this: TThis, ...args: TArgs) => TResult): (this: TThis, ...args: TArgs) => Promise<Awaited<TResult>>;
52
52
  /**
53
53
  * Runs a callback and reports matching LogTape records according to the
54
54
  * configured mode.
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.cts","names":[],"sources":["../src/reporter.ts"],"sourcesContent":[],"mappings":";;;;;;AAiBA;AAOA;;;AAUyB,KAjBb,oBAAA,GAiBa,YAAA,GAAA,QAAA,GAAA,OAAA;;;AAWW;AASpC;;AASwB,UAvCP,yBAAA,CAuCO;EAAK;;;EACmB,SAAf,IAAA,CAAA,EApCf,oBAoCe;EAAO;;;;EASgB,SAAf,WAAA,CAAA,EAvChB,QAuCgB;EAAO;AA0BhD;;;EACyC,SACtC,IAAA,CAAA,EA7De,IA6Df;EAAkB;;;uBAxDE;;;;;;;;UASN,kBAAA;;;;;;;;sEASO,UAAU,oBACnB,UAAU,QAAQ,QAAQ;;;;;;;;+BASV,UAAU,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BzC,wBAAA,WACL,4BACR"}
1
+ {"version":3,"file":"reporter.d.cts","names":[],"sources":["../src/reporter.ts"],"sourcesContent":[],"mappings":";;;;;;AAiBA;AAOA;;;AAUyB,KAjBb,oBAAA,GAiBa,YAAA,GAAA,QAAA,GAAA,OAAA;;;AAWW;AASpC;;AASqB,UAvCJ,yBAAA,CAuCI;EAAK;;;EACT,SAAW,IAAA,CAAA,EApCV,oBAoCU;EAAK;;;;EASK,SAAmB,WAAA,CAAA,EAvChC,QAuCgC;EAAO;;AAAhB;AA0BhD;EAAwC,SAAA,IAAA,CAAA,EA3DtB,IA2DsB;EAAA;;AAEnB;uBAxDE;;;;;;;;UASN,kBAAA;;;;;;;;0EASI,gBAAgB,UAAU,iBACnC,gBAAgB,UAAU,QAAQ,QAAQ;;;;;;;;+BASvB,UAAU,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BzC,wBAAA,WACL,4BACR"}
@@ -48,7 +48,7 @@ interface FailureLogReporter {
48
48
  * @param callback The test callback to wrap.
49
49
  * @returns An async callback with the same parameters.
50
50
  */
51
- wrap<TArgs extends readonly unknown[], TResult>(callback: (...args: TArgs) => TResult): (...args: TArgs) => Promise<Awaited<TResult>>;
51
+ wrap<TThis, TArgs extends readonly unknown[], TResult>(callback: (this: TThis, ...args: TArgs) => TResult): (this: TThis, ...args: TArgs) => Promise<Awaited<TResult>>;
52
52
  /**
53
53
  * Runs a callback and reports matching LogTape records according to the
54
54
  * configured mode.
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","names":[],"sources":["../src/reporter.ts"],"sourcesContent":[],"mappings":";;;;;;AAiBA;AAOA;;;AAUyB,KAjBb,oBAAA,GAiBa,YAAA,GAAA,QAAA,GAAA,OAAA;;;AAWW;AASpC;;AASwB,UAvCP,yBAAA,CAuCO;EAAK;;;EACmB,SAAf,IAAA,CAAA,EApCf,oBAoCe;EAAO;;;;EASgB,SAAf,WAAA,CAAA,EAvChB,QAuCgB;EAAO;AA0BhD;;;EACyC,SACtC,IAAA,CAAA,EA7De,IA6Df;EAAkB;;;uBAxDE;;;;;;;;UASN,kBAAA;;;;;;;;sEASO,UAAU,oBACnB,UAAU,QAAQ,QAAQ;;;;;;;;+BASV,UAAU,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BzC,wBAAA,WACL,4BACR"}
1
+ {"version":3,"file":"reporter.d.ts","names":[],"sources":["../src/reporter.ts"],"sourcesContent":[],"mappings":";;;;;;AAiBA;AAOA;;;AAUyB,KAjBb,oBAAA,GAiBa,YAAA,GAAA,QAAA,GAAA,OAAA;;;AAWW;AASpC;;AASqB,UAvCJ,yBAAA,CAuCI;EAAK;;;EACT,SAAW,IAAA,CAAA,EApCV,oBAoCU;EAAK;;;;EASK,SAAmB,WAAA,CAAA,EAvChC,QAuCgC;EAAO;;AAAhB;AA0BhD;EAAwC,SAAA,IAAA,CAAA,EA3DtB,IA2DsB;EAAA;;AAEnB;uBAxDE;;;;;;;;UASN,kBAAA;;;;;;;;0EASI,gBAAgB,UAAU,iBACnC,gBAAgB,UAAU,QAAQ,QAAQ;;;;;;;;+BASvB,UAAU,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BzC,wBAAA,WACL,4BACR"}
package/dist/reporter.js CHANGED
@@ -55,7 +55,9 @@ function createFailureLogReporter(options = {}) {
55
55
  return result;
56
56
  }
57
57
  function wrap(callback) {
58
- return (...args) => run(() => callback(...args));
58
+ return function(...args) {
59
+ return run(() => Reflect.apply(callback, this, args));
60
+ };
59
61
  }
60
62
  return {
61
63
  run,
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.js","names":["options: FailureLogReporterOptions","callback: () => TResult","records: LogRecord[]","bufferSink: Sink","record: LogRecord","result: Awaited<TResult>","callback: (...args: TArgs) => TResult","records: readonly LogRecord[]","sink: Sink"],"sources":["../src/reporter.ts"],"sourcesContent":["import {\n getConsoleSink,\n type LogLevel,\n type LogRecord,\n type Sink,\n type TextFormatter,\n withConfig,\n} from \"@logtape/logtape\";\n\nimport { materializeLogRecord } from \"./snapshot.ts\";\n\n/**\n * Controls when buffered records are reported by a\n * {@link FailureLogReporter}.\n *\n * @since 2.3.0\n */\nexport type FailureLogReportMode = \"on-failure\" | \"always\" | \"never\";\n\n/**\n * Options for {@link createFailureLogReporter}.\n *\n * @since 2.3.0\n */\nexport interface FailureLogReporterOptions {\n /**\n * When to report buffered records. Defaults to `\"on-failure\"`.\n */\n readonly mode?: FailureLogReportMode;\n\n /**\n * The lowest severity level collected by the reporter's scoped\n * configuration. Defaults to `\"info\"`.\n */\n readonly lowestLevel?: LogLevel;\n\n /**\n * The sink that receives buffered records when the reporter flushes.\n * Defaults to a console sink.\n */\n readonly sink?: Sink;\n\n /**\n * The text formatter used by the default console sink.\n */\n readonly formatter?: TextFormatter;\n}\n\n/**\n * A reporter that buffers LogTape records while a test callback runs and\n * reports them depending on the configured mode.\n *\n * @since 2.3.0\n */\nexport interface FailureLogReporter {\n /**\n * Wraps a callback so matching LogTape records are reported according to the\n * configured mode.\n *\n * @param callback The test callback to wrap.\n * @returns An async callback with the same parameters.\n */\n wrap<TArgs extends readonly unknown[], TResult>(\n callback: (...args: TArgs) => TResult,\n ): (...args: TArgs) => Promise<Awaited<TResult>>;\n\n /**\n * Runs a callback and reports matching LogTape records according to the\n * configured mode.\n *\n * @param callback The callback to run.\n * @returns The callback result.\n */\n run<TResult>(callback: () => TResult): Promise<Awaited<TResult>>;\n}\n\n/**\n * Creates a failure log reporter for tests.\n *\n * The reporter uses LogTape's scoped configuration support. The process-wide\n * configuration must already include `Config.contextLocalStorage`, but the\n * reporter does not mutate global logger routing while a wrapped callback\n * runs.\n *\n * @example\n * ```ts\n * import { createFailureLogReporter } from \"@logtape/testing/reporter\";\n *\n * const reporter = createFailureLogReporter({ lowestLevel: \"debug\" });\n *\n * test(\"case\", reporter.wrap(async () => {\n * // Logs emitted here are reported only if this callback throws.\n * }));\n * ```\n *\n * @param options Reporter options.\n * @returns A failure log reporter.\n * @since 2.3.0\n */\nexport function createFailureLogReporter(\n options: FailureLogReporterOptions = {},\n): FailureLogReporter {\n const mode = options.mode ?? \"on-failure\";\n const lowestLevel = options.lowestLevel ?? \"info\";\n const outputSink = options.sink ?? getConsoleSink({\n formatter: options.formatter,\n });\n\n async function run<TResult>(\n callback: () => TResult,\n ): Promise<Awaited<TResult>> {\n const records: LogRecord[] = [];\n const bufferSink: Sink = (record: LogRecord): void => {\n records.push(materializeLogRecord(record));\n };\n\n let result: Awaited<TResult>;\n try {\n result = await withConfig({\n sinks: { failureLogReporter: bufferSink },\n loggers: [{\n category: [],\n lowestLevel,\n parentSinks: \"override\",\n sinks: [\"failureLogReporter\"],\n }],\n }, callback);\n } catch (error) {\n if (mode !== \"never\") {\n try {\n flushRecords(records, outputSink);\n } catch {\n // Keep the test runner focused on the original assertion error.\n }\n }\n throw error;\n }\n\n if (mode === \"always\") flushRecords(records, outputSink);\n return result;\n }\n\n function wrap<TArgs extends readonly unknown[], TResult>(\n callback: (...args: TArgs) => TResult,\n ): (...args: TArgs) => Promise<Awaited<TResult>> {\n return (...args: TArgs) => run(() => callback(...args));\n }\n\n return {\n run,\n wrap,\n };\n}\n\nfunction flushRecords(\n records: readonly LogRecord[],\n sink: Sink,\n): void {\n for (const record of records) sink(record);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,SAAgB,yBACdA,UAAqC,CAAE,GACnB;CACpB,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,aAAa,QAAQ,QAAQ,eAAe,EAChD,WAAW,QAAQ,UACpB,EAAC;CAEF,eAAe,IACbC,UAC2B;EAC3B,MAAMC,UAAuB,CAAE;EAC/B,MAAMC,aAAmB,CAACC,WAA4B;AACpD,WAAQ,KAAK,qBAAqB,OAAO,CAAC;EAC3C;EAED,IAAIC;AACJ,MAAI;AACF,YAAS,MAAM,WAAW;IACxB,OAAO,EAAE,oBAAoB,WAAY;IACzC,SAAS,CAAC;KACR,UAAU,CAAE;KACZ;KACA,aAAa;KACb,OAAO,CAAC,oBAAqB;IAC9B,CAAC;GACH,GAAE,SAAS;EACb,SAAQ,OAAO;AACd,OAAI,SAAS,QACX,KAAI;AACF,iBAAa,SAAS,WAAW;GAClC,QAAO,CAEP;AAEH,SAAM;EACP;AAED,MAAI,SAAS,SAAU,cAAa,SAAS,WAAW;AACxD,SAAO;CACR;CAED,SAAS,KACPC,UAC+C;AAC/C,SAAO,CAAC,GAAG,SAAgB,IAAI,MAAM,SAAS,GAAG,KAAK,CAAC;CACxD;AAED,QAAO;EACL;EACA;CACD;AACF;AAED,SAAS,aACPC,SACAC,MACM;AACN,MAAK,MAAM,UAAU,QAAS,MAAK,OAAO;AAC3C"}
1
+ {"version":3,"file":"reporter.js","names":["options: FailureLogReporterOptions","callback: () => TResult","records: LogRecord[]","bufferSink: Sink","record: LogRecord","result: Awaited<TResult>","callback: (this: TThis, ...args: TArgs) => TResult","records: readonly LogRecord[]","sink: Sink"],"sources":["../src/reporter.ts"],"sourcesContent":["import {\n getConsoleSink,\n type LogLevel,\n type LogRecord,\n type Sink,\n type TextFormatter,\n withConfig,\n} from \"@logtape/logtape\";\n\nimport { materializeLogRecord } from \"./snapshot.ts\";\n\n/**\n * Controls when buffered records are reported by a\n * {@link FailureLogReporter}.\n *\n * @since 2.3.0\n */\nexport type FailureLogReportMode = \"on-failure\" | \"always\" | \"never\";\n\n/**\n * Options for {@link createFailureLogReporter}.\n *\n * @since 2.3.0\n */\nexport interface FailureLogReporterOptions {\n /**\n * When to report buffered records. Defaults to `\"on-failure\"`.\n */\n readonly mode?: FailureLogReportMode;\n\n /**\n * The lowest severity level collected by the reporter's scoped\n * configuration. Defaults to `\"info\"`.\n */\n readonly lowestLevel?: LogLevel;\n\n /**\n * The sink that receives buffered records when the reporter flushes.\n * Defaults to a console sink.\n */\n readonly sink?: Sink;\n\n /**\n * The text formatter used by the default console sink.\n */\n readonly formatter?: TextFormatter;\n}\n\n/**\n * A reporter that buffers LogTape records while a test callback runs and\n * reports them depending on the configured mode.\n *\n * @since 2.3.0\n */\nexport interface FailureLogReporter {\n /**\n * Wraps a callback so matching LogTape records are reported according to the\n * configured mode.\n *\n * @param callback The test callback to wrap.\n * @returns An async callback with the same parameters.\n */\n wrap<TThis, TArgs extends readonly unknown[], TResult>(\n callback: (this: TThis, ...args: TArgs) => TResult,\n ): (this: TThis, ...args: TArgs) => Promise<Awaited<TResult>>;\n\n /**\n * Runs a callback and reports matching LogTape records according to the\n * configured mode.\n *\n * @param callback The callback to run.\n * @returns The callback result.\n */\n run<TResult>(callback: () => TResult): Promise<Awaited<TResult>>;\n}\n\n/**\n * Creates a failure log reporter for tests.\n *\n * The reporter uses LogTape's scoped configuration support. The process-wide\n * configuration must already include `Config.contextLocalStorage`, but the\n * reporter does not mutate global logger routing while a wrapped callback\n * runs.\n *\n * @example\n * ```ts\n * import { createFailureLogReporter } from \"@logtape/testing/reporter\";\n *\n * const reporter = createFailureLogReporter({ lowestLevel: \"debug\" });\n *\n * test(\"case\", reporter.wrap(async () => {\n * // Logs emitted here are reported only if this callback throws.\n * }));\n * ```\n *\n * @param options Reporter options.\n * @returns A failure log reporter.\n * @since 2.3.0\n */\nexport function createFailureLogReporter(\n options: FailureLogReporterOptions = {},\n): FailureLogReporter {\n const mode = options.mode ?? \"on-failure\";\n const lowestLevel = options.lowestLevel ?? \"info\";\n const outputSink = options.sink ?? getConsoleSink({\n formatter: options.formatter,\n });\n\n async function run<TResult>(\n callback: () => TResult,\n ): Promise<Awaited<TResult>> {\n const records: LogRecord[] = [];\n const bufferSink: Sink = (record: LogRecord): void => {\n records.push(materializeLogRecord(record));\n };\n\n let result: Awaited<TResult>;\n try {\n result = await withConfig({\n sinks: { failureLogReporter: bufferSink },\n loggers: [{\n category: [],\n lowestLevel,\n parentSinks: \"override\",\n sinks: [\"failureLogReporter\"],\n }],\n }, callback);\n } catch (error) {\n if (mode !== \"never\") {\n try {\n flushRecords(records, outputSink);\n } catch {\n // Keep the test runner focused on the original assertion error.\n }\n }\n throw error;\n }\n\n if (mode === \"always\") flushRecords(records, outputSink);\n return result;\n }\n\n function wrap<TThis, TArgs extends readonly unknown[], TResult>(\n callback: (this: TThis, ...args: TArgs) => TResult,\n ): (this: TThis, ...args: TArgs) => Promise<Awaited<TResult>> {\n return function (\n this: TThis,\n ...args: TArgs\n ): Promise<Awaited<TResult>> {\n return run(() => Reflect.apply(callback, this, args) as TResult);\n };\n }\n\n return {\n run,\n wrap,\n };\n}\n\nfunction flushRecords(\n records: readonly LogRecord[],\n sink: Sink,\n): void {\n for (const record of records) sink(record);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,SAAgB,yBACdA,UAAqC,CAAE,GACnB;CACpB,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,aAAa,QAAQ,QAAQ,eAAe,EAChD,WAAW,QAAQ,UACpB,EAAC;CAEF,eAAe,IACbC,UAC2B;EAC3B,MAAMC,UAAuB,CAAE;EAC/B,MAAMC,aAAmB,CAACC,WAA4B;AACpD,WAAQ,KAAK,qBAAqB,OAAO,CAAC;EAC3C;EAED,IAAIC;AACJ,MAAI;AACF,YAAS,MAAM,WAAW;IACxB,OAAO,EAAE,oBAAoB,WAAY;IACzC,SAAS,CAAC;KACR,UAAU,CAAE;KACZ;KACA,aAAa;KACb,OAAO,CAAC,oBAAqB;IAC9B,CAAC;GACH,GAAE,SAAS;EACb,SAAQ,OAAO;AACd,OAAI,SAAS,QACX,KAAI;AACF,iBAAa,SAAS,WAAW;GAClC,QAAO,CAEP;AAEH,SAAM;EACP;AAED,MAAI,SAAS,SAAU,cAAa,SAAS,WAAW;AACxD,SAAO;CACR;CAED,SAAS,KACPC,UAC4D;AAC5D,SAAO,SAEL,GAAG,MACwB;AAC3B,UAAO,IAAI,MAAM,QAAQ,MAAM,UAAU,MAAM,KAAK,CAAY;EACjE;CACF;AAED,QAAO;EACL;EACA;CACD;AACF;AAED,SAAS,aACPC,SACAC,MACM;AACN,MAAK,MAAM,UAAU,QAAS,MAAK,OAAO;AAC3C"}
package/dist/snapshot.cjs CHANGED
@@ -4,7 +4,7 @@ function materializeLogRecord(record) {
4
4
  const message = record.message;
5
5
  const rawMessage = record.rawMessage;
6
6
  const descriptors = Object.getOwnPropertyDescriptors(record);
7
- if (!hasStringAccessorDescriptor(descriptors)) return record;
7
+ if (!hasAccessorDescriptor(descriptors)) return record;
8
8
  const messageDescriptor = descriptors.message;
9
9
  const rawMessageDescriptor = descriptors.rawMessage;
10
10
  const snapshotDescriptors = Object.create(null);
@@ -24,8 +24,8 @@ function materializeLogRecord(record) {
24
24
  });
25
25
  return Object.defineProperties(Object.create(Object.getPrototypeOf(record)), snapshotDescriptors);
26
26
  }
27
- function hasStringAccessorDescriptor(descriptors) {
28
- for (const key of Object.getOwnPropertyNames(descriptors)) {
27
+ function hasAccessorDescriptor(descriptors) {
28
+ for (const key of Reflect.ownKeys(descriptors)) {
29
29
  const descriptor = descriptors[key];
30
30
  if (descriptor != null && !isDataDescriptor(descriptor)) return true;
31
31
  }
package/dist/snapshot.js CHANGED
@@ -3,7 +3,7 @@ function materializeLogRecord(record) {
3
3
  const message = record.message;
4
4
  const rawMessage = record.rawMessage;
5
5
  const descriptors = Object.getOwnPropertyDescriptors(record);
6
- if (!hasStringAccessorDescriptor(descriptors)) return record;
6
+ if (!hasAccessorDescriptor(descriptors)) return record;
7
7
  const messageDescriptor = descriptors.message;
8
8
  const rawMessageDescriptor = descriptors.rawMessage;
9
9
  const snapshotDescriptors = Object.create(null);
@@ -23,8 +23,8 @@ function materializeLogRecord(record) {
23
23
  });
24
24
  return Object.defineProperties(Object.create(Object.getPrototypeOf(record)), snapshotDescriptors);
25
25
  }
26
- function hasStringAccessorDescriptor(descriptors) {
27
- for (const key of Object.getOwnPropertyNames(descriptors)) {
26
+ function hasAccessorDescriptor(descriptors) {
27
+ for (const key of Reflect.ownKeys(descriptors)) {
28
28
  const descriptor = descriptors[key];
29
29
  if (descriptor != null && !isDataDescriptor(descriptor)) return true;
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":["record: LogRecord","descriptors: PropertyDescriptorMap","descriptor: PropertyDescriptor | undefined","key: PropertyKey","value: unknown"],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { LogRecord } from \"@logtape/logtape\";\n\nexport function materializeLogRecord(record: LogRecord): LogRecord {\n const message = record.message;\n const rawMessage = record.rawMessage;\n const descriptors = Object.getOwnPropertyDescriptors(\n record,\n ) as PropertyDescriptorMap;\n if (!hasStringAccessorDescriptor(descriptors)) {\n return record;\n }\n const messageDescriptor = descriptors.message;\n const rawMessageDescriptor = descriptors.rawMessage;\n const snapshotDescriptors = Object.create(null) as PropertyDescriptorMap;\n for (const key of Reflect.ownKeys(descriptors)) {\n if (isLogRecordKey(key)) continue;\n const descriptor = descriptors[key];\n if (descriptor == null) continue;\n snapshotDescriptors[key] = isDataDescriptor(descriptor)\n ? descriptor\n : materializedDescriptor(Reflect.get(record, key), descriptor);\n }\n Object.assign(snapshotDescriptors, {\n category: materializedDescriptor(record.category, descriptors.category),\n level: materializedDescriptor(record.level, descriptors.level),\n message: materializedDescriptor(message, messageDescriptor),\n rawMessage: materializedDescriptor(rawMessage, rawMessageDescriptor),\n timestamp: materializedDescriptor(record.timestamp, descriptors.timestamp),\n properties: materializedDescriptor(\n record.properties,\n descriptors.properties,\n ),\n });\n return Object.defineProperties(\n Object.create(Object.getPrototypeOf(record)),\n snapshotDescriptors,\n ) as LogRecord;\n}\n\nfunction hasStringAccessorDescriptor(\n descriptors: PropertyDescriptorMap,\n): boolean {\n for (const key of Object.getOwnPropertyNames(descriptors)) {\n const descriptor = descriptors[key];\n if (descriptor != null && !isDataDescriptor(descriptor)) return true;\n }\n return false;\n}\n\nfunction isDataDescriptor(\n descriptor: PropertyDescriptor | undefined,\n): descriptor is PropertyDescriptor & { readonly value: unknown } {\n return descriptor != null && \"value\" in descriptor;\n}\n\nfunction isLogRecordKey(key: PropertyKey): key is keyof LogRecord {\n return key === \"category\" ||\n key === \"level\" ||\n key === \"message\" ||\n key === \"rawMessage\" ||\n key === \"timestamp\" ||\n key === \"properties\";\n}\n\nfunction materializedDescriptor(\n value: unknown,\n descriptor: PropertyDescriptor | undefined,\n): PropertyDescriptor {\n return {\n configurable: descriptor?.configurable ?? true,\n enumerable: descriptor?.enumerable ?? true,\n value,\n writable: isDataDescriptor(descriptor) ? descriptor.writable : true,\n };\n}\n"],"mappings":";AAEA,SAAgB,qBAAqBA,QAA8B;CACjE,MAAM,UAAU,OAAO;CACvB,MAAM,aAAa,OAAO;CAC1B,MAAM,cAAc,OAAO,0BACzB,OACD;AACD,MAAK,4BAA4B,YAAY,CAC3C,QAAO;CAET,MAAM,oBAAoB,YAAY;CACtC,MAAM,uBAAuB,YAAY;CACzC,MAAM,sBAAsB,OAAO,OAAO,KAAK;AAC/C,MAAK,MAAM,OAAO,QAAQ,QAAQ,YAAY,EAAE;AAC9C,MAAI,eAAe,IAAI,CAAE;EACzB,MAAM,aAAa,YAAY;AAC/B,MAAI,cAAc,KAAM;AACxB,sBAAoB,OAAO,iBAAiB,WAAW,GACnD,aACA,uBAAuB,QAAQ,IAAI,QAAQ,IAAI,EAAE,WAAW;CACjE;AACD,QAAO,OAAO,qBAAqB;EACjC,UAAU,uBAAuB,OAAO,UAAU,YAAY,SAAS;EACvE,OAAO,uBAAuB,OAAO,OAAO,YAAY,MAAM;EAC9D,SAAS,uBAAuB,SAAS,kBAAkB;EAC3D,YAAY,uBAAuB,YAAY,qBAAqB;EACpE,WAAW,uBAAuB,OAAO,WAAW,YAAY,UAAU;EAC1E,YAAY,uBACV,OAAO,YACP,YAAY,WACb;CACF,EAAC;AACF,QAAO,OAAO,iBACZ,OAAO,OAAO,OAAO,eAAe,OAAO,CAAC,EAC5C,oBACD;AACF;AAED,SAAS,4BACPC,aACS;AACT,MAAK,MAAM,OAAO,OAAO,oBAAoB,YAAY,EAAE;EACzD,MAAM,aAAa,YAAY;AAC/B,MAAI,cAAc,SAAS,iBAAiB,WAAW,CAAE,QAAO;CACjE;AACD,QAAO;AACR;AAED,SAAS,iBACPC,YACgE;AAChE,QAAO,cAAc,QAAQ,WAAW;AACzC;AAED,SAAS,eAAeC,KAA0C;AAChE,QAAO,QAAQ,cACb,QAAQ,WACR,QAAQ,aACR,QAAQ,gBACR,QAAQ,eACR,QAAQ;AACX;AAED,SAAS,uBACPC,OACAF,YACoB;AACpB,QAAO;EACL,cAAc,YAAY,gBAAgB;EAC1C,YAAY,YAAY,cAAc;EACtC;EACA,UAAU,iBAAiB,WAAW,GAAG,WAAW,WAAW;CAChE;AACF"}
1
+ {"version":3,"file":"snapshot.js","names":["record: LogRecord","descriptors: PropertyDescriptorMap","descriptor: PropertyDescriptor | undefined","key: PropertyKey","value: unknown"],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { LogRecord } from \"@logtape/logtape\";\n\nexport function materializeLogRecord(record: LogRecord): LogRecord {\n const message = record.message;\n const rawMessage = record.rawMessage;\n const descriptors = Object.getOwnPropertyDescriptors(\n record,\n ) as PropertyDescriptorMap;\n if (!hasAccessorDescriptor(descriptors)) {\n return record;\n }\n const messageDescriptor = descriptors.message;\n const rawMessageDescriptor = descriptors.rawMessage;\n const snapshotDescriptors = Object.create(null) as PropertyDescriptorMap;\n for (const key of Reflect.ownKeys(descriptors)) {\n if (isLogRecordKey(key)) continue;\n const descriptor = descriptors[key];\n if (descriptor == null) continue;\n snapshotDescriptors[key] = isDataDescriptor(descriptor)\n ? descriptor\n : materializedDescriptor(Reflect.get(record, key), descriptor);\n }\n Object.assign(snapshotDescriptors, {\n category: materializedDescriptor(record.category, descriptors.category),\n level: materializedDescriptor(record.level, descriptors.level),\n message: materializedDescriptor(message, messageDescriptor),\n rawMessage: materializedDescriptor(rawMessage, rawMessageDescriptor),\n timestamp: materializedDescriptor(record.timestamp, descriptors.timestamp),\n properties: materializedDescriptor(\n record.properties,\n descriptors.properties,\n ),\n });\n return Object.defineProperties(\n Object.create(Object.getPrototypeOf(record)),\n snapshotDescriptors,\n ) as LogRecord;\n}\n\nfunction hasAccessorDescriptor(\n descriptors: PropertyDescriptorMap,\n): boolean {\n for (const key of Reflect.ownKeys(descriptors)) {\n const descriptor = descriptors[key];\n if (descriptor != null && !isDataDescriptor(descriptor)) return true;\n }\n return false;\n}\n\nfunction isDataDescriptor(\n descriptor: PropertyDescriptor | undefined,\n): descriptor is PropertyDescriptor & { readonly value: unknown } {\n return descriptor != null && \"value\" in descriptor;\n}\n\nfunction isLogRecordKey(key: PropertyKey): key is keyof LogRecord {\n return key === \"category\" ||\n key === \"level\" ||\n key === \"message\" ||\n key === \"rawMessage\" ||\n key === \"timestamp\" ||\n key === \"properties\";\n}\n\nfunction materializedDescriptor(\n value: unknown,\n descriptor: PropertyDescriptor | undefined,\n): PropertyDescriptor {\n return {\n configurable: descriptor?.configurable ?? true,\n enumerable: descriptor?.enumerable ?? true,\n value,\n writable: isDataDescriptor(descriptor) ? descriptor.writable : true,\n };\n}\n"],"mappings":";AAEA,SAAgB,qBAAqBA,QAA8B;CACjE,MAAM,UAAU,OAAO;CACvB,MAAM,aAAa,OAAO;CAC1B,MAAM,cAAc,OAAO,0BACzB,OACD;AACD,MAAK,sBAAsB,YAAY,CACrC,QAAO;CAET,MAAM,oBAAoB,YAAY;CACtC,MAAM,uBAAuB,YAAY;CACzC,MAAM,sBAAsB,OAAO,OAAO,KAAK;AAC/C,MAAK,MAAM,OAAO,QAAQ,QAAQ,YAAY,EAAE;AAC9C,MAAI,eAAe,IAAI,CAAE;EACzB,MAAM,aAAa,YAAY;AAC/B,MAAI,cAAc,KAAM;AACxB,sBAAoB,OAAO,iBAAiB,WAAW,GACnD,aACA,uBAAuB,QAAQ,IAAI,QAAQ,IAAI,EAAE,WAAW;CACjE;AACD,QAAO,OAAO,qBAAqB;EACjC,UAAU,uBAAuB,OAAO,UAAU,YAAY,SAAS;EACvE,OAAO,uBAAuB,OAAO,OAAO,YAAY,MAAM;EAC9D,SAAS,uBAAuB,SAAS,kBAAkB;EAC3D,YAAY,uBAAuB,YAAY,qBAAqB;EACpE,WAAW,uBAAuB,OAAO,WAAW,YAAY,UAAU;EAC1E,YAAY,uBACV,OAAO,YACP,YAAY,WACb;CACF,EAAC;AACF,QAAO,OAAO,iBACZ,OAAO,OAAO,OAAO,eAAe,OAAO,CAAC,EAC5C,oBACD;AACF;AAED,SAAS,sBACPC,aACS;AACT,MAAK,MAAM,OAAO,QAAQ,QAAQ,YAAY,EAAE;EAC9C,MAAM,aAAa,YAAY;AAC/B,MAAI,cAAc,SAAS,iBAAiB,WAAW,CAAE,QAAO;CACjE;AACD,QAAO;AACR;AAED,SAAS,iBACPC,YACgE;AAChE,QAAO,cAAc,QAAQ,WAAW;AACzC;AAED,SAAS,eAAeC,KAA0C;AAChE,QAAO,QAAQ,cACb,QAAQ,WACR,QAAQ,aACR,QAAQ,gBACR,QAAQ,eACR,QAAQ;AACX;AAED,SAAS,uBACPC,OACAF,YACoB;AACpB,QAAO;EACL,cAAc,YAAY,gBAAgB;EAC1C,YAAY,YAAY,cAAc;EACtC;EACA,UAAU,iBAAiB,WAAW,GAAG,WAAW,WAAW;CAChE;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/testing",
3
- "version": "2.3.0-dev.818+d457bb3c",
3
+ "version": "2.3.0-dev.822+8b280a72",
4
4
  "description": "Testing utilities for collecting and asserting LogTape records",
5
5
  "keywords": [
6
6
  "logging",
@@ -64,12 +64,12 @@
64
64
  "dist/"
65
65
  ],
66
66
  "peerDependencies": {
67
- "@logtape/logtape": "^2.3.0-dev.818+d457bb3c"
67
+ "@logtape/logtape": "^2.3.0-dev.822+8b280a72"
68
68
  },
69
69
  "devDependencies": {
70
70
  "tsdown": "^0.12.7",
71
71
  "typescript": "^5.8.3",
72
- "@logtape/redaction": "^2.3.0-dev.818+d457bb3c"
72
+ "@logtape/redaction": "^2.3.0-dev.822+8b280a72"
73
73
  },
74
74
  "scripts": {
75
75
  "build": "tsdown",