@noego/wood 0.4.1 → 0.4.2

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.
Files changed (81) hide show
  1. package/README.md +100 -2
  2. package/dist/client/global_polyfill.d.cts +1 -2
  3. package/dist/client/global_polyfill.d.ts +1 -2
  4. package/dist/client/index.cjs.map +1 -1
  5. package/dist/client/index.d.cts +1 -1
  6. package/dist/client/index.d.ts +1 -1
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/index.cjs +0 -4
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +0 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/testing/browser.cjs +188 -34
  15. package/dist/testing/browser.cjs.map +1 -1
  16. package/dist/testing/browser.d.cts +6 -2
  17. package/dist/testing/browser.d.ts +6 -2
  18. package/dist/testing/browser.js +188 -35
  19. package/dist/testing/browser.js.map +1 -1
  20. package/dist/testing/create_controller_harness.cjs +3 -1
  21. package/dist/testing/create_controller_harness.cjs.map +1 -1
  22. package/dist/testing/create_controller_harness.d.cts +4 -2
  23. package/dist/testing/create_controller_harness.d.ts +4 -2
  24. package/dist/testing/create_controller_harness.js +3 -1
  25. package/dist/testing/create_controller_harness.js.map +1 -1
  26. package/dist/testing/index.cjs +3 -3
  27. package/dist/testing/index.cjs.map +1 -1
  28. package/dist/testing/index.d.cts +5 -3
  29. package/dist/testing/index.d.ts +5 -3
  30. package/dist/testing/index.js +2 -2
  31. package/dist/testing/index.js.map +1 -1
  32. package/dist/trace-testing/index.cjs +3 -3
  33. package/dist/trace-testing/index.cjs.map +1 -1
  34. package/dist/trace-testing/index.d.cts +2 -3
  35. package/dist/trace-testing/index.d.ts +2 -3
  36. package/dist/trace-testing/index.js +3 -3
  37. package/dist/trace-testing/index.js.map +1 -1
  38. package/dist/trace-testing/trace_assertions.cjs +2 -46
  39. package/dist/trace-testing/trace_assertions.cjs.map +1 -1
  40. package/dist/trace-testing/trace_assertions.d.cts +1 -15
  41. package/dist/trace-testing/trace_assertions.d.ts +1 -15
  42. package/dist/trace-testing/trace_assertions.js +3 -45
  43. package/dist/trace-testing/trace_assertions.js.map +1 -1
  44. package/dist/trace-testing/trace_query.cjs +4 -115
  45. package/dist/trace-testing/trace_query.cjs.map +1 -1
  46. package/dist/trace-testing/trace_query.d.cts +1 -24
  47. package/dist/trace-testing/trace_query.d.ts +1 -24
  48. package/dist/trace-testing/trace_query.js +5 -112
  49. package/dist/trace-testing/trace_query.js.map +1 -1
  50. package/dist/trace-testing/trace_recorder.cjs +50 -0
  51. package/dist/trace-testing/trace_recorder.cjs.map +1 -0
  52. package/dist/trace-testing/trace_recorder.d.cts +12 -0
  53. package/dist/trace-testing/trace_recorder.d.ts +12 -0
  54. package/dist/trace-testing/trace_recorder.js +32 -0
  55. package/dist/trace-testing/trace_recorder.js.map +1 -0
  56. package/dist/tracing/index.cjs +0 -4
  57. package/dist/tracing/index.cjs.map +1 -1
  58. package/dist/tracing/index.d.cts +1 -1
  59. package/dist/tracing/index.d.ts +1 -1
  60. package/dist/tracing/index.js +1 -5
  61. package/dist/tracing/index.js.map +1 -1
  62. package/dist/tracing/trace_hub.cjs +0 -84
  63. package/dist/tracing/trace_hub.cjs.map +1 -1
  64. package/dist/tracing/trace_hub.d.cts +1 -16
  65. package/dist/tracing/trace_hub.d.ts +1 -16
  66. package/dist/tracing/trace_hub.js +0 -72
  67. package/dist/tracing/trace_hub.js.map +1 -1
  68. package/dist/tracing/trace_provider.cjs +0 -6
  69. package/dist/tracing/trace_provider.cjs.map +1 -1
  70. package/dist/tracing/trace_provider.d.cts +1 -3
  71. package/dist/tracing/trace_provider.d.ts +1 -3
  72. package/dist/tracing/trace_provider.js +0 -7
  73. package/dist/tracing/trace_provider.js.map +1 -1
  74. package/docs/browser-testing.md +84 -0
  75. package/package.json +2 -1
  76. package/dist/trace-testing/trace_scenario.cjs +0 -61
  77. package/dist/trace-testing/trace_scenario.cjs.map +0 -1
  78. package/dist/trace-testing/trace_scenario.d.cts +0 -27
  79. package/dist/trace-testing/trace_scenario.d.ts +0 -27
  80. package/dist/trace-testing/trace_scenario.js +0 -37
  81. package/dist/trace-testing/trace_scenario.js.map +0 -1
@@ -0,0 +1,12 @@
1
+ import { TraceRecorder as TraceRecorder$1 } from '@noego/trace/testing';
2
+ export { TraceObservableSource, TraceRecorderEnableOptions, TraceRecorderSource, TraceWaitOptions } from '@noego/trace/testing';
3
+ import { TraceEvent } from '../tracing/trace_hub.cjs';
4
+ import { FrameworkTracer } from '../tracing/trace_provider.cjs';
5
+ import 'rxjs';
6
+ import '@noego/ioc';
7
+
8
+ declare class TraceRecorder extends TraceRecorder$1<TraceEvent> {
9
+ constructor(traceProvider?: FrameworkTracer);
10
+ }
11
+
12
+ export { TraceRecorder };
@@ -0,0 +1,12 @@
1
+ import { TraceRecorder as TraceRecorder$1 } from '@noego/trace/testing';
2
+ export { TraceObservableSource, TraceRecorderEnableOptions, TraceRecorderSource, TraceWaitOptions } from '@noego/trace/testing';
3
+ import { TraceEvent } from '../tracing/trace_hub.js';
4
+ import { FrameworkTracer } from '../tracing/trace_provider.js';
5
+ import 'rxjs';
6
+ import '@noego/ioc';
7
+
8
+ declare class TraceRecorder extends TraceRecorder$1<TraceEvent> {
9
+ constructor(traceProvider?: FrameworkTracer);
10
+ }
11
+
12
+ export { TraceRecorder };
@@ -0,0 +1,32 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
12
+ import { Component, Inject, LoadAs } from "@noego/ioc";
13
+ import {
14
+ TraceRecorder as BaseTraceRecorder
15
+ } from "@noego/trace/testing";
16
+ import {
17
+ TraceProvider
18
+ } from "../tracing/index.js";
19
+ import { getTraceEvents$ } from "../tracing/trace_hub.js";
20
+ let TraceRecorder = class extends BaseTraceRecorder {
21
+ constructor(traceProvider) {
22
+ super(traceProvider ?? getTraceEvents$());
23
+ }
24
+ };
25
+ TraceRecorder = __decorateClass([
26
+ Component({ scope: LoadAs.Singleton }),
27
+ __decorateParam(0, Inject(TraceProvider))
28
+ ], TraceRecorder);
29
+ export {
30
+ TraceRecorder
31
+ };
32
+ //# sourceMappingURL=trace_recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trace-testing/trace_recorder.ts"],"sourcesContent":["import { Component, Inject, LoadAs } from '@noego/ioc';\nimport {\n TraceRecorder as BaseTraceRecorder,\n type TraceObservableSource,\n type TraceRecorderEnableOptions,\n type TraceRecorderSource,\n type TraceWaitOptions,\n} from '@noego/trace/testing';\nimport {\n TraceProvider,\n type FrameworkTracer,\n type TraceEvent,\n} from '../tracing/index.js';\nimport { getTraceEvents$ } from '../tracing/trace_hub.js';\n\n@Component({ scope: LoadAs.Singleton })\nexport class TraceRecorder extends BaseTraceRecorder<TraceEvent> {\n constructor(\n @Inject(TraceProvider) traceProvider?: FrameworkTracer,\n ) {\n super(traceProvider ?? getTraceEvents$());\n }\n}\n\nexport type {\n TraceObservableSource,\n TraceRecorderEnableOptions,\n TraceRecorderSource,\n TraceWaitOptions,\n};\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,WAAW,QAAQ,cAAc;AAC1C;AAAA,EACE,iBAAiB;AAAA,OAKZ;AACP;AAAA,EACE;AAAA,OAGK;AACP,SAAS,uBAAuB;AAGzB,IAAM,gBAAN,cAA4B,kBAA8B;AAAA,EAC/D,YACyB,eACvB;AACA,UAAM,iBAAiB,gBAAgB,CAAC;AAAA,EAC1C;AACF;AANa,gBAAN;AAAA,EADN,UAAU,EAAE,OAAO,OAAO,UAAU,CAAC;AAAA,EAGjC,0BAAO,aAAa;AAAA,GAFZ;","names":[]}
@@ -22,11 +22,9 @@ __export(tracing_exports, {
22
22
  MainTracer: () => import_trace_provider.MainTracer,
23
23
  RendererTracer: () => import_trace_provider.RendererTracer,
24
24
  TestTracer: () => import_trace_provider.TestTracer,
25
- TraceCapture: () => import_trace_hub.TraceCapture,
26
25
  TraceProvider: () => import_trace_provider.TraceProvider,
27
26
  TraceProviderConfiguration: () => import_trace_provider.TraceProviderConfiguration,
28
27
  clearTraceHubForTests: () => import_trace_hub.clearTraceHubForTests,
29
- createTraceCapture: () => import_trace_hub.createTraceCapture,
30
28
  dispatchRendererTracePayload: () => import_trace_hub.dispatchRendererTracePayload,
31
29
  emitRendererTrace: () => import_trace_hub.emitRendererTrace,
32
30
  getTraceEvents$: () => import_trace_hub.getTraceEvents$,
@@ -46,11 +44,9 @@ var import_trace_provider = require("./trace_provider.js");
46
44
  MainTracer,
47
45
  RendererTracer,
48
46
  TestTracer,
49
- TraceCapture,
50
47
  TraceProvider,
51
48
  TraceProviderConfiguration,
52
49
  clearTraceHubForTests,
53
- createTraceCapture,
54
50
  dispatchRendererTracePayload,
55
51
  emitRendererTrace,
56
52
  getTraceEvents$,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceEnabled,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceRuntimeContext,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceContext,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAqBO;AAEP,4BAUO;","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceEnabled,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceRuntimeContext,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceContext,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAkBO;AAEP,4BAUO;","names":[]}
@@ -1,4 +1,4 @@
1
- export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceRuntimeContext, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.cjs';
1
+ export { TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceRuntimeContext, TraceWaitOptions, clearTraceHubForTests, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.cjs';
2
2
  export { FrameworkTracer, MainTracer, RendererTracer, TestTracer, TraceContext, TraceProvider, TraceProviderConfiguration, TraceProviderMode, TraceRuntime } from './trace_provider.cjs';
3
3
  import 'rxjs';
4
4
  import '@noego/ioc';
@@ -1,4 +1,4 @@
1
- export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceRuntimeContext, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.js';
1
+ export { TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceRuntimeContext, TraceWaitOptions, clearTraceHubForTests, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.js';
2
2
  export { FrameworkTracer, MainTracer, RendererTracer, TestTracer, TraceContext, TraceProvider, TraceProviderConfiguration, TraceProviderMode, TraceRuntime } from './trace_provider.js';
3
3
  import 'rxjs';
4
4
  import '@noego/ioc';
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  clearTraceHubForTests,
3
- createTraceCapture,
4
3
  dispatchRendererTracePayload,
5
4
  emitRendererTrace,
6
5
  getTraceEvents$,
@@ -9,8 +8,7 @@ import {
9
8
  setMainTraceMinLevel,
10
9
  setRendererTraceEnabled,
11
10
  setRendererTraceMinLevel,
12
- setRendererTraceTransport,
13
- TraceCapture
11
+ setRendererTraceTransport
14
12
  } from "./trace_hub.js";
15
13
  import {
16
14
  FrameworkTracer,
@@ -25,11 +23,9 @@ export {
25
23
  MainTracer,
26
24
  RendererTracer,
27
25
  TestTracer,
28
- TraceCapture,
29
26
  TraceProvider,
30
27
  TraceProviderConfiguration,
31
28
  clearTraceHubForTests,
32
- createTraceCapture,
33
29
  dispatchRendererTracePayload,
34
30
  emitRendererTrace,
35
31
  getTraceEvents$,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceEnabled,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceRuntimeContext,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceContext,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceEnabled,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceRuntimeContext,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceContext,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;","names":[]}
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,20 +15,10 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var trace_hub_exports = {};
30
20
  __export(trace_hub_exports, {
31
- TraceCapture: () => TraceCapture,
32
21
  clearTraceHubForTests: () => clearTraceHubForTests,
33
- createTraceCapture: () => createTraceCapture,
34
22
  dispatchRendererTracePayload: () => dispatchRendererTracePayload,
35
23
  emitRendererTrace: () => emitRendererTrace,
36
24
  getTraceEvents$: () => getTraceEvents$,
@@ -97,70 +85,6 @@ function resolveTraceBridge() {
97
85
  }
98
86
  return bridge;
99
87
  }
100
- class TraceCapture {
101
- constructor(source$, options = {}) {
102
- this.buffer = [];
103
- this.pending = /* @__PURE__ */ new Set();
104
- this.maxEvents = Math.max(1, options.maxEvents ?? 1e3);
105
- this.subscription = source$.subscribe((event) => {
106
- this.buffer.push(event);
107
- if (this.buffer.length > this.maxEvents) {
108
- this.buffer.splice(0, this.buffer.length - this.maxEvents);
109
- }
110
- for (const waiter of Array.from(this.pending)) {
111
- if (!waiter.predicate(event)) {
112
- continue;
113
- }
114
- if (waiter.timeoutId) {
115
- clearTimeout(waiter.timeoutId);
116
- }
117
- this.pending.delete(waiter);
118
- waiter.resolve(event);
119
- }
120
- });
121
- }
122
- events() {
123
- return [...this.buffer];
124
- }
125
- async waitFor(predicate, options = {}) {
126
- const existing = this.buffer.find(predicate);
127
- if (existing) {
128
- return existing;
129
- }
130
- return new Promise((resolve, reject) => {
131
- const waiter = {
132
- predicate,
133
- resolve,
134
- reject
135
- };
136
- const timeoutMs = options.timeoutMs ?? 5e3;
137
- waiter.timeoutId = setTimeout(() => {
138
- this.pending.delete(waiter);
139
- reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));
140
- }, timeoutMs);
141
- this.pending.add(waiter);
142
- });
143
- }
144
- async writeArtifact(targetPath) {
145
- const [{ mkdir, writeFile }, pathModule] = await Promise.all([
146
- import("node:fs/promises"),
147
- import("node:path")
148
- ]);
149
- await mkdir(pathModule.dirname(targetPath), { recursive: true });
150
- const lines = this.buffer.map((event) => JSON.stringify(event)).join("\n");
151
- await writeFile(targetPath, `${lines}${lines.length > 0 ? "\n" : ""}`, "utf8");
152
- }
153
- stop() {
154
- for (const waiter of this.pending) {
155
- if (waiter.timeoutId) {
156
- clearTimeout(waiter.timeoutId);
157
- }
158
- waiter.reject(new Error("Trace capture stopped before predicate matched"));
159
- }
160
- this.pending.clear();
161
- this.subscription.unsubscribe();
162
- }
163
- }
164
88
  class TraceHub {
165
89
  constructor() {
166
90
  this.subject = new import_rxjs.Subject();
@@ -192,9 +116,6 @@ class TraceHub {
192
116
  }
193
117
  return event;
194
118
  }
195
- capture(options = {}) {
196
- return new TraceCapture(this.events$, options);
197
- }
198
119
  }
199
120
  function getGlobalTraceHub() {
200
121
  const globalObj = globalThis;
@@ -258,9 +179,6 @@ function emitRendererTrace(level, input) {
258
179
  } catch {
259
180
  }
260
181
  }
261
- function createTraceCapture(options = {}) {
262
- return getGlobalTraceHub().capture(options);
263
- }
264
182
  function clearTraceHubForTests() {
265
183
  const globalObj = globalThis;
266
184
  delete globalObj[TRACE_HUB_SYMBOL];
@@ -270,9 +188,7 @@ function clearTraceHubForTests() {
270
188
  }
271
189
  // Annotate the CommonJS export names for ESM import in node:
272
190
  0 && (module.exports = {
273
- TraceCapture,
274
191
  clearTraceHubForTests,
275
- createTraceCapture,
276
192
  dispatchRendererTracePayload,
277
193
  emitRendererTrace,
278
194
  getTraceEvents$,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevels[process]]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevels[process]]) {\n this.subject.next(event);\n }\n return event;\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
@@ -29,23 +29,9 @@ type TraceRuntimeContext = {
29
29
  routeKey?: string;
30
30
  harnessId?: string;
31
31
  };
32
- type TraceCaptureOptions = {
33
- maxEvents?: number;
34
- };
35
32
  type TraceWaitOptions = {
36
33
  timeoutMs?: number;
37
34
  };
38
- declare class TraceCapture {
39
- private readonly buffer;
40
- private readonly pending;
41
- private readonly maxEvents;
42
- private subscription;
43
- constructor(source$: Observable<TraceEvent>, options?: TraceCaptureOptions);
44
- events(): TraceEvent[];
45
- waitFor(predicate: (event: TraceEvent) => boolean, options?: TraceWaitOptions): Promise<TraceEvent>;
46
- writeArtifact(targetPath: string): Promise<void>;
47
- stop(): void;
48
- }
49
35
  declare function getTraceEvents$(): Observable<TraceEvent>;
50
36
  declare function setMainTraceMinLevel(level: TraceLevel): void;
51
37
  declare function setRendererTraceMinLevel(level: TraceLevel): void;
@@ -55,7 +41,6 @@ declare function publishTestTrace(process: TraceProcess, level: TraceLevel, inpu
55
41
  declare function dispatchRendererTracePayload(rawPayload: unknown, context?: TraceRuntimeContext): TraceDispatchResult;
56
42
  declare function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void;
57
43
  declare function emitRendererTrace(level: TraceLevel, input: TraceInput): void;
58
- declare function createTraceCapture(options?: TraceCaptureOptions): TraceCapture;
59
44
  declare function clearTraceHubForTests(): void;
60
45
 
61
- export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceRuntimeContext, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport };
46
+ export { type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceRuntimeContext, type TraceWaitOptions, clearTraceHubForTests, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport };
@@ -29,23 +29,9 @@ type TraceRuntimeContext = {
29
29
  routeKey?: string;
30
30
  harnessId?: string;
31
31
  };
32
- type TraceCaptureOptions = {
33
- maxEvents?: number;
34
- };
35
32
  type TraceWaitOptions = {
36
33
  timeoutMs?: number;
37
34
  };
38
- declare class TraceCapture {
39
- private readonly buffer;
40
- private readonly pending;
41
- private readonly maxEvents;
42
- private subscription;
43
- constructor(source$: Observable<TraceEvent>, options?: TraceCaptureOptions);
44
- events(): TraceEvent[];
45
- waitFor(predicate: (event: TraceEvent) => boolean, options?: TraceWaitOptions): Promise<TraceEvent>;
46
- writeArtifact(targetPath: string): Promise<void>;
47
- stop(): void;
48
- }
49
35
  declare function getTraceEvents$(): Observable<TraceEvent>;
50
36
  declare function setMainTraceMinLevel(level: TraceLevel): void;
51
37
  declare function setRendererTraceMinLevel(level: TraceLevel): void;
@@ -55,7 +41,6 @@ declare function publishTestTrace(process: TraceProcess, level: TraceLevel, inpu
55
41
  declare function dispatchRendererTracePayload(rawPayload: unknown, context?: TraceRuntimeContext): TraceDispatchResult;
56
42
  declare function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void;
57
43
  declare function emitRendererTrace(level: TraceLevel, input: TraceInput): void;
58
- declare function createTraceCapture(options?: TraceCaptureOptions): TraceCapture;
59
44
  declare function clearTraceHubForTests(): void;
60
45
 
61
- export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceRuntimeContext, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport };
46
+ export { type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceRuntimeContext, type TraceWaitOptions, clearTraceHubForTests, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport };
@@ -53,70 +53,6 @@ function resolveTraceBridge() {
53
53
  }
54
54
  return bridge;
55
55
  }
56
- class TraceCapture {
57
- constructor(source$, options = {}) {
58
- this.buffer = [];
59
- this.pending = /* @__PURE__ */ new Set();
60
- this.maxEvents = Math.max(1, options.maxEvents ?? 1e3);
61
- this.subscription = source$.subscribe((event) => {
62
- this.buffer.push(event);
63
- if (this.buffer.length > this.maxEvents) {
64
- this.buffer.splice(0, this.buffer.length - this.maxEvents);
65
- }
66
- for (const waiter of Array.from(this.pending)) {
67
- if (!waiter.predicate(event)) {
68
- continue;
69
- }
70
- if (waiter.timeoutId) {
71
- clearTimeout(waiter.timeoutId);
72
- }
73
- this.pending.delete(waiter);
74
- waiter.resolve(event);
75
- }
76
- });
77
- }
78
- events() {
79
- return [...this.buffer];
80
- }
81
- async waitFor(predicate, options = {}) {
82
- const existing = this.buffer.find(predicate);
83
- if (existing) {
84
- return existing;
85
- }
86
- return new Promise((resolve, reject) => {
87
- const waiter = {
88
- predicate,
89
- resolve,
90
- reject
91
- };
92
- const timeoutMs = options.timeoutMs ?? 5e3;
93
- waiter.timeoutId = setTimeout(() => {
94
- this.pending.delete(waiter);
95
- reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));
96
- }, timeoutMs);
97
- this.pending.add(waiter);
98
- });
99
- }
100
- async writeArtifact(targetPath) {
101
- const [{ mkdir, writeFile }, pathModule] = await Promise.all([
102
- import("node:fs/promises"),
103
- import("node:path")
104
- ]);
105
- await mkdir(pathModule.dirname(targetPath), { recursive: true });
106
- const lines = this.buffer.map((event) => JSON.stringify(event)).join("\n");
107
- await writeFile(targetPath, `${lines}${lines.length > 0 ? "\n" : ""}`, "utf8");
108
- }
109
- stop() {
110
- for (const waiter of this.pending) {
111
- if (waiter.timeoutId) {
112
- clearTimeout(waiter.timeoutId);
113
- }
114
- waiter.reject(new Error("Trace capture stopped before predicate matched"));
115
- }
116
- this.pending.clear();
117
- this.subscription.unsubscribe();
118
- }
119
- }
120
56
  class TraceHub {
121
57
  constructor() {
122
58
  this.subject = new Subject();
@@ -148,9 +84,6 @@ class TraceHub {
148
84
  }
149
85
  return event;
150
86
  }
151
- capture(options = {}) {
152
- return new TraceCapture(this.events$, options);
153
- }
154
87
  }
155
88
  function getGlobalTraceHub() {
156
89
  const globalObj = globalThis;
@@ -214,9 +147,6 @@ function emitRendererTrace(level, input) {
214
147
  } catch {
215
148
  }
216
149
  }
217
- function createTraceCapture(options = {}) {
218
- return getGlobalTraceHub().capture(options);
219
- }
220
150
  function clearTraceHubForTests() {
221
151
  const globalObj = globalThis;
222
152
  delete globalObj[TRACE_HUB_SYMBOL];
@@ -225,9 +155,7 @@ function clearTraceHubForTests() {
225
155
  customRendererTraceTransport = null;
226
156
  }
227
157
  export {
228
- TraceCapture,
229
158
  clearTraceHubForTests,
230
- createTraceCapture,
231
159
  dispatchRendererTracePayload,
232
160
  emitRendererTrace,
233
161
  getTraceEvents$,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevels[process]]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevels[process]]) {\n this.subject.next(event);\n }\n return event;\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
@@ -41,9 +41,6 @@ class FrameworkTracer {
41
41
  extend(context) {
42
42
  return new ContextualTracer(this, context);
43
43
  }
44
- capture(options = {}) {
45
- return (0, import_trace_hub.createTraceCapture)(options);
46
- }
47
44
  }
48
45
  class ContextualTracer extends FrameworkTracer {
49
46
  constructor(parent, context) {
@@ -231,9 +228,6 @@ let TraceProvider = class extends FrameworkTracer {
231
228
  error(event) {
232
229
  this.resolveImplementation().error(event);
233
230
  }
234
- capture(options = {}) {
235
- return this.resolveImplementation().capture(options);
236
- }
237
231
  resolveImplementation() {
238
232
  const mode = this.configuration.getMode();
239
233
  if (mode === "test") {