@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.
- package/README.md +100 -2
- package/dist/client/global_polyfill.d.cts +1 -2
- package/dist/client/global_polyfill.d.ts +1 -2
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/testing/browser.cjs +188 -34
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +6 -2
- package/dist/testing/browser.d.ts +6 -2
- package/dist/testing/browser.js +188 -35
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.cjs +3 -1
- package/dist/testing/create_controller_harness.cjs.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +4 -2
- package/dist/testing/create_controller_harness.d.ts +4 -2
- package/dist/testing/create_controller_harness.js +3 -1
- package/dist/testing/create_controller_harness.js.map +1 -1
- package/dist/testing/index.cjs +3 -3
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +5 -3
- package/dist/testing/index.d.ts +5 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/trace-testing/index.cjs +3 -3
- package/dist/trace-testing/index.cjs.map +1 -1
- package/dist/trace-testing/index.d.cts +2 -3
- package/dist/trace-testing/index.d.ts +2 -3
- package/dist/trace-testing/index.js +3 -3
- package/dist/trace-testing/index.js.map +1 -1
- package/dist/trace-testing/trace_assertions.cjs +2 -46
- package/dist/trace-testing/trace_assertions.cjs.map +1 -1
- package/dist/trace-testing/trace_assertions.d.cts +1 -15
- package/dist/trace-testing/trace_assertions.d.ts +1 -15
- package/dist/trace-testing/trace_assertions.js +3 -45
- package/dist/trace-testing/trace_assertions.js.map +1 -1
- package/dist/trace-testing/trace_query.cjs +4 -115
- package/dist/trace-testing/trace_query.cjs.map +1 -1
- package/dist/trace-testing/trace_query.d.cts +1 -24
- package/dist/trace-testing/trace_query.d.ts +1 -24
- package/dist/trace-testing/trace_query.js +5 -112
- package/dist/trace-testing/trace_query.js.map +1 -1
- package/dist/trace-testing/trace_recorder.cjs +50 -0
- package/dist/trace-testing/trace_recorder.cjs.map +1 -0
- package/dist/trace-testing/trace_recorder.d.cts +12 -0
- package/dist/trace-testing/trace_recorder.d.ts +12 -0
- package/dist/trace-testing/trace_recorder.js +32 -0
- package/dist/trace-testing/trace_recorder.js.map +1 -0
- package/dist/tracing/index.cjs +0 -4
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +1 -1
- package/dist/tracing/index.d.ts +1 -1
- package/dist/tracing/index.js +1 -5
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/trace_hub.cjs +0 -84
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +1 -16
- package/dist/tracing/trace_hub.d.ts +1 -16
- package/dist/tracing/trace_hub.js +0 -72
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +0 -6
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +1 -3
- package/dist/tracing/trace_provider.d.ts +1 -3
- package/dist/tracing/trace_provider.js +0 -7
- package/dist/tracing/trace_provider.js.map +1 -1
- package/docs/browser-testing.md +84 -0
- package/package.json +2 -1
- package/dist/trace-testing/trace_scenario.cjs +0 -61
- package/dist/trace-testing/trace_scenario.cjs.map +0 -1
- package/dist/trace-testing/trace_scenario.d.cts +0 -27
- package/dist/trace-testing/trace_scenario.d.ts +0 -27
- package/dist/trace-testing/trace_scenario.js +0 -37
- 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":[]}
|
package/dist/tracing/index.cjs
CHANGED
|
@@ -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
|
|
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":[]}
|
package/dist/tracing/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
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';
|
package/dist/tracing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
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';
|
package/dist/tracing/index.js
CHANGED
|
@@ -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
|
|
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 {
|
|
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 {
|
|
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") {
|