@noego/wood 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/index.cjs +10 -16
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1 -4
  4. package/dist/index.d.ts +1 -4
  5. package/dist/index.js +1 -7
  6. package/dist/index.js.map +1 -1
  7. package/dist/main/index.cjs +16 -2
  8. package/dist/main/index.cjs.map +1 -1
  9. package/dist/main/index.js +16 -2
  10. package/dist/main/index.js.map +1 -1
  11. package/dist/runtime/runtime.cjs +4 -4
  12. package/dist/runtime/runtime.cjs.map +1 -1
  13. package/dist/runtime/runtime.d.cts +2 -1
  14. package/dist/runtime/runtime.d.ts +2 -1
  15. package/dist/runtime/runtime.js +8 -5
  16. package/dist/runtime/runtime.js.map +1 -1
  17. package/dist/testing/browser.cjs +45 -7
  18. package/dist/testing/browser.cjs.map +1 -1
  19. package/dist/testing/browser.d.cts +14 -1
  20. package/dist/testing/browser.d.ts +14 -1
  21. package/dist/testing/browser.js +48 -7
  22. package/dist/testing/browser.js.map +1 -1
  23. package/dist/testing/index.cjs.map +1 -1
  24. package/dist/testing/index.d.cts +1 -1
  25. package/dist/testing/index.d.ts +1 -1
  26. package/dist/testing/index.js.map +1 -1
  27. package/dist/trace-testing/index.cjs +39 -0
  28. package/dist/trace-testing/index.cjs.map +1 -0
  29. package/dist/trace-testing/index.d.cts +7 -0
  30. package/dist/trace-testing/index.d.ts +7 -0
  31. package/dist/trace-testing/index.js +19 -0
  32. package/dist/trace-testing/index.js.map +1 -0
  33. package/dist/trace-testing/trace_assertions.cjs +73 -0
  34. package/dist/trace-testing/trace_assertions.cjs.map +1 -0
  35. package/dist/trace-testing/trace_assertions.d.cts +15 -0
  36. package/dist/trace-testing/trace_assertions.d.ts +15 -0
  37. package/dist/trace-testing/trace_assertions.js +49 -0
  38. package/dist/trace-testing/trace_assertions.js.map +1 -0
  39. package/dist/trace-testing/trace_query.cjs +144 -0
  40. package/dist/trace-testing/trace_query.cjs.map +1 -0
  41. package/dist/trace-testing/trace_query.d.cts +24 -0
  42. package/dist/trace-testing/trace_query.d.ts +24 -0
  43. package/dist/trace-testing/trace_query.js +118 -0
  44. package/dist/trace-testing/trace_query.js.map +1 -0
  45. package/dist/trace-testing/trace_scenario.cjs +61 -0
  46. package/dist/trace-testing/trace_scenario.cjs.map +1 -0
  47. package/dist/trace-testing/trace_scenario.d.cts +27 -0
  48. package/dist/trace-testing/trace_scenario.d.ts +27 -0
  49. package/dist/trace-testing/trace_scenario.js +37 -0
  50. package/dist/trace-testing/trace_scenario.js.map +1 -0
  51. package/dist/tracing/index.cjs.map +1 -1
  52. package/dist/tracing/index.d.cts +1 -1
  53. package/dist/tracing/index.d.ts +1 -1
  54. package/dist/tracing/index.js.map +1 -1
  55. package/dist/tracing/trace_hub.cjs +19 -2
  56. package/dist/tracing/trace_hub.cjs.map +1 -1
  57. package/dist/tracing/trace_hub.d.cts +12 -2
  58. package/dist/tracing/trace_hub.d.ts +12 -2
  59. package/dist/tracing/trace_hub.js +19 -2
  60. package/dist/tracing/trace_hub.js.map +1 -1
  61. package/package.json +13 -1
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var trace_query_exports = {};
20
+ __export(trace_query_exports, {
21
+ createTraceQuery: () => createTraceQuery,
22
+ matchesTrace: () => matchesTrace,
23
+ readPath: () => readPath
24
+ });
25
+ module.exports = __toCommonJS(trace_query_exports);
26
+ function createTraceQuery(source) {
27
+ const readEvents = () => Array.isArray(source) ? source.slice() : source().slice();
28
+ return {
29
+ all: () => readEvents(),
30
+ filter: (filter) => readEvents().filter((event) => matchesTrace(event, filter)),
31
+ count: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length,
32
+ countByType: (types) => countTracesByType(readEvents(), types),
33
+ payloads: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).map((event) => event.payload).filter((payload) => isRecord(payload)),
34
+ first: (filter) => readEvents().find((event) => matchesTrace(event, filter)) ?? null,
35
+ last: (filter) => findLastTrace(readEvents(), filter),
36
+ sequence: (filters) => includesTraceSequence(readEvents(), filters),
37
+ none: (filter) => readEvents().every((event) => !matchesTrace(event, filter)),
38
+ once: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length === 1,
39
+ uniqueBy: (filter, path) => valuesAtPathAreUnique(readEvents(), filter, path)
40
+ };
41
+ }
42
+ function matchesTrace(event, filter) {
43
+ if (typeof filter === "function") {
44
+ return filter(event);
45
+ }
46
+ for (const [path, expected] of Object.entries(filter)) {
47
+ const actual = readPath(event, path);
48
+ if (!matchesValue(actual, expected)) {
49
+ return false;
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+ function readPath(value, path) {
55
+ let current = value;
56
+ for (const segment of path.split(".")) {
57
+ if (!isRecord(current)) {
58
+ return void 0;
59
+ }
60
+ current = current[segment];
61
+ }
62
+ return current;
63
+ }
64
+ function countTracesByType(traces, types) {
65
+ const allowedTypes = types ? new Set(types) : null;
66
+ const counts = {};
67
+ for (const trace of traces) {
68
+ if (allowedTypes && !allowedTypes.has(trace.type)) {
69
+ continue;
70
+ }
71
+ counts[trace.type] = (counts[trace.type] ?? 0) + 1;
72
+ }
73
+ return counts;
74
+ }
75
+ function findLastTrace(traces, filter) {
76
+ for (let index = traces.length - 1; index >= 0; index -= 1) {
77
+ const trace = traces[index];
78
+ if (trace && matchesTrace(trace, filter)) {
79
+ return trace;
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+ function includesTraceSequence(traces, filters) {
85
+ let filterIndex = 0;
86
+ if (filters.length === 0) {
87
+ return true;
88
+ }
89
+ for (const trace of traces) {
90
+ const filter = filters[filterIndex];
91
+ if (!filter || !matchesTrace(trace, filter)) {
92
+ continue;
93
+ }
94
+ filterIndex += 1;
95
+ if (filterIndex === filters.length) {
96
+ return true;
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ function valuesAtPathAreUnique(traces, filter, path) {
102
+ const seen = /* @__PURE__ */ new Set();
103
+ for (const trace of traces) {
104
+ if (!matchesTrace(trace, filter)) {
105
+ continue;
106
+ }
107
+ const value = readPath(trace, path);
108
+ if (seen.has(value)) {
109
+ return false;
110
+ }
111
+ seen.add(value);
112
+ }
113
+ return true;
114
+ }
115
+ function matchesValue(actual, expected) {
116
+ if (expected instanceof RegExp) {
117
+ return typeof actual === "string" && expected.test(actual);
118
+ }
119
+ if (typeof expected === "function") {
120
+ return Boolean(expected(actual));
121
+ }
122
+ if (isRecord(expected)) {
123
+ return isRecord(actual) && objectContains(actual, expected);
124
+ }
125
+ return Object.is(actual, expected);
126
+ }
127
+ function objectContains(actual, expected) {
128
+ for (const [key, value] of Object.entries(expected)) {
129
+ if (!matchesValue(actual[key], value)) {
130
+ return false;
131
+ }
132
+ }
133
+ return true;
134
+ }
135
+ function isRecord(value) {
136
+ return typeof value === "object" && value !== null && !Array.isArray(value);
137
+ }
138
+ // Annotate the CommonJS export names for ESM import in node:
139
+ 0 && (module.exports = {
140
+ createTraceQuery,
141
+ matchesTrace,
142
+ readPath
143
+ });
144
+ //# sourceMappingURL=trace_query.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trace-testing/trace_query.ts"],"sourcesContent":["import type { TraceEvent } from '../tracing/index.js';\n\nexport type TraceFilter =\n | ((event: TraceEvent) => boolean)\n | Record<string, unknown>;\n\nexport type TraceCountSummary = Record<string, number>;\n\nexport type TraceQuery = {\n all(): TraceEvent[];\n filter(filter: TraceFilter): TraceEvent[];\n count(filter: TraceFilter): number;\n countByType(types?: string[]): TraceCountSummary;\n payloads(filter: TraceFilter): Record<string, unknown>[];\n first(filter: TraceFilter): TraceEvent | null;\n last(filter: TraceFilter): TraceEvent | null;\n sequence(filters: TraceFilter[]): boolean;\n none(filter: TraceFilter): boolean;\n once(filter: TraceFilter): boolean;\n uniqueBy(filter: TraceFilter, path: string): boolean;\n};\n\ntype TraceSource = TraceEvent[] | (() => TraceEvent[]);\n\nexport function createTraceQuery(source: TraceSource): TraceQuery {\n const readEvents = () => Array.isArray(source) ? source.slice() : source().slice();\n return {\n all: () => readEvents(),\n filter: (filter) => readEvents().filter((event) => matchesTrace(event, filter)),\n count: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length,\n countByType: (types) => countTracesByType(readEvents(), types),\n payloads: (filter) => readEvents()\n .filter((event) => matchesTrace(event, filter))\n .map((event) => event.payload)\n .filter((payload): payload is Record<string, unknown> => isRecord(payload)),\n first: (filter) => readEvents().find((event) => matchesTrace(event, filter)) ?? null,\n last: (filter) => findLastTrace(readEvents(), filter),\n sequence: (filters) => includesTraceSequence(readEvents(), filters),\n none: (filter) => readEvents().every((event) => !matchesTrace(event, filter)),\n once: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length === 1,\n uniqueBy: (filter, path) => valuesAtPathAreUnique(readEvents(), filter, path),\n };\n}\n\nexport function matchesTrace(event: TraceEvent, filter: TraceFilter): boolean {\n if (typeof filter === 'function') {\n return filter(event);\n }\n for (const [path, expected] of Object.entries(filter)) {\n const actual = readPath(event, path);\n if (!matchesValue(actual, expected)) {\n return false;\n }\n }\n return true;\n}\n\nexport function readPath(value: unknown, path: string): unknown {\n let current = value;\n for (const segment of path.split('.')) {\n if (!isRecord(current)) {\n return undefined;\n }\n current = current[segment];\n }\n return current;\n}\n\nfunction countTracesByType(traces: TraceEvent[], types?: string[]): TraceCountSummary {\n const allowedTypes = types ? new Set(types) : null;\n const counts: TraceCountSummary = {};\n for (const trace of traces) {\n if (allowedTypes && !allowedTypes.has(trace.type)) {\n continue;\n }\n counts[trace.type] = (counts[trace.type] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction findLastTrace(traces: TraceEvent[], filter: TraceFilter): TraceEvent | null {\n for (let index = traces.length - 1; index >= 0; index -= 1) {\n const trace = traces[index];\n if (trace && matchesTrace(trace, filter)) {\n return trace;\n }\n }\n return null;\n}\n\nfunction includesTraceSequence(traces: TraceEvent[], filters: TraceFilter[]): boolean {\n let filterIndex = 0;\n if (filters.length === 0) {\n return true;\n }\n for (const trace of traces) {\n const filter = filters[filterIndex];\n if (!filter || !matchesTrace(trace, filter)) {\n continue;\n }\n filterIndex += 1;\n if (filterIndex === filters.length) {\n return true;\n }\n }\n return false;\n}\n\nfunction valuesAtPathAreUnique(traces: TraceEvent[], filter: TraceFilter, path: string): boolean {\n const seen = new Set<unknown>();\n for (const trace of traces) {\n if (!matchesTrace(trace, filter)) {\n continue;\n }\n const value = readPath(trace, path);\n if (seen.has(value)) {\n return false;\n }\n seen.add(value);\n }\n return true;\n}\n\nfunction matchesValue(actual: unknown, expected: unknown): boolean {\n if (expected instanceof RegExp) {\n return typeof actual === 'string' && expected.test(actual);\n }\n if (typeof expected === 'function') {\n return Boolean((expected as (value: unknown) => boolean)(actual));\n }\n if (isRecord(expected)) {\n return isRecord(actual) && objectContains(actual, expected);\n }\n return Object.is(actual, expected);\n}\n\nfunction objectContains(actual: Record<string, unknown>, expected: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(expected)) {\n if (!matchesValue(actual[key], value)) {\n return false;\n }\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,24 @@
1
+ import { TraceEvent } from '../tracing/trace_hub.cjs';
2
+ import 'rxjs';
3
+
4
+ type TraceFilter = ((event: TraceEvent) => boolean) | Record<string, unknown>;
5
+ type TraceCountSummary = Record<string, number>;
6
+ type TraceQuery = {
7
+ all(): TraceEvent[];
8
+ filter(filter: TraceFilter): TraceEvent[];
9
+ count(filter: TraceFilter): number;
10
+ countByType(types?: string[]): TraceCountSummary;
11
+ payloads(filter: TraceFilter): Record<string, unknown>[];
12
+ first(filter: TraceFilter): TraceEvent | null;
13
+ last(filter: TraceFilter): TraceEvent | null;
14
+ sequence(filters: TraceFilter[]): boolean;
15
+ none(filter: TraceFilter): boolean;
16
+ once(filter: TraceFilter): boolean;
17
+ uniqueBy(filter: TraceFilter, path: string): boolean;
18
+ };
19
+ type TraceSource = TraceEvent[] | (() => TraceEvent[]);
20
+ declare function createTraceQuery(source: TraceSource): TraceQuery;
21
+ declare function matchesTrace(event: TraceEvent, filter: TraceFilter): boolean;
22
+ declare function readPath(value: unknown, path: string): unknown;
23
+
24
+ export { type TraceCountSummary, type TraceFilter, type TraceQuery, createTraceQuery, matchesTrace, readPath };
@@ -0,0 +1,24 @@
1
+ import { TraceEvent } from '../tracing/trace_hub.js';
2
+ import 'rxjs';
3
+
4
+ type TraceFilter = ((event: TraceEvent) => boolean) | Record<string, unknown>;
5
+ type TraceCountSummary = Record<string, number>;
6
+ type TraceQuery = {
7
+ all(): TraceEvent[];
8
+ filter(filter: TraceFilter): TraceEvent[];
9
+ count(filter: TraceFilter): number;
10
+ countByType(types?: string[]): TraceCountSummary;
11
+ payloads(filter: TraceFilter): Record<string, unknown>[];
12
+ first(filter: TraceFilter): TraceEvent | null;
13
+ last(filter: TraceFilter): TraceEvent | null;
14
+ sequence(filters: TraceFilter[]): boolean;
15
+ none(filter: TraceFilter): boolean;
16
+ once(filter: TraceFilter): boolean;
17
+ uniqueBy(filter: TraceFilter, path: string): boolean;
18
+ };
19
+ type TraceSource = TraceEvent[] | (() => TraceEvent[]);
20
+ declare function createTraceQuery(source: TraceSource): TraceQuery;
21
+ declare function matchesTrace(event: TraceEvent, filter: TraceFilter): boolean;
22
+ declare function readPath(value: unknown, path: string): unknown;
23
+
24
+ export { type TraceCountSummary, type TraceFilter, type TraceQuery, createTraceQuery, matchesTrace, readPath };
@@ -0,0 +1,118 @@
1
+ function createTraceQuery(source) {
2
+ const readEvents = () => Array.isArray(source) ? source.slice() : source().slice();
3
+ return {
4
+ all: () => readEvents(),
5
+ filter: (filter) => readEvents().filter((event) => matchesTrace(event, filter)),
6
+ count: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length,
7
+ countByType: (types) => countTracesByType(readEvents(), types),
8
+ payloads: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).map((event) => event.payload).filter((payload) => isRecord(payload)),
9
+ first: (filter) => readEvents().find((event) => matchesTrace(event, filter)) ?? null,
10
+ last: (filter) => findLastTrace(readEvents(), filter),
11
+ sequence: (filters) => includesTraceSequence(readEvents(), filters),
12
+ none: (filter) => readEvents().every((event) => !matchesTrace(event, filter)),
13
+ once: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length === 1,
14
+ uniqueBy: (filter, path) => valuesAtPathAreUnique(readEvents(), filter, path)
15
+ };
16
+ }
17
+ function matchesTrace(event, filter) {
18
+ if (typeof filter === "function") {
19
+ return filter(event);
20
+ }
21
+ for (const [path, expected] of Object.entries(filter)) {
22
+ const actual = readPath(event, path);
23
+ if (!matchesValue(actual, expected)) {
24
+ return false;
25
+ }
26
+ }
27
+ return true;
28
+ }
29
+ function readPath(value, path) {
30
+ let current = value;
31
+ for (const segment of path.split(".")) {
32
+ if (!isRecord(current)) {
33
+ return void 0;
34
+ }
35
+ current = current[segment];
36
+ }
37
+ return current;
38
+ }
39
+ function countTracesByType(traces, types) {
40
+ const allowedTypes = types ? new Set(types) : null;
41
+ const counts = {};
42
+ for (const trace of traces) {
43
+ if (allowedTypes && !allowedTypes.has(trace.type)) {
44
+ continue;
45
+ }
46
+ counts[trace.type] = (counts[trace.type] ?? 0) + 1;
47
+ }
48
+ return counts;
49
+ }
50
+ function findLastTrace(traces, filter) {
51
+ for (let index = traces.length - 1; index >= 0; index -= 1) {
52
+ const trace = traces[index];
53
+ if (trace && matchesTrace(trace, filter)) {
54
+ return trace;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+ function includesTraceSequence(traces, filters) {
60
+ let filterIndex = 0;
61
+ if (filters.length === 0) {
62
+ return true;
63
+ }
64
+ for (const trace of traces) {
65
+ const filter = filters[filterIndex];
66
+ if (!filter || !matchesTrace(trace, filter)) {
67
+ continue;
68
+ }
69
+ filterIndex += 1;
70
+ if (filterIndex === filters.length) {
71
+ return true;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+ function valuesAtPathAreUnique(traces, filter, path) {
77
+ const seen = /* @__PURE__ */ new Set();
78
+ for (const trace of traces) {
79
+ if (!matchesTrace(trace, filter)) {
80
+ continue;
81
+ }
82
+ const value = readPath(trace, path);
83
+ if (seen.has(value)) {
84
+ return false;
85
+ }
86
+ seen.add(value);
87
+ }
88
+ return true;
89
+ }
90
+ function matchesValue(actual, expected) {
91
+ if (expected instanceof RegExp) {
92
+ return typeof actual === "string" && expected.test(actual);
93
+ }
94
+ if (typeof expected === "function") {
95
+ return Boolean(expected(actual));
96
+ }
97
+ if (isRecord(expected)) {
98
+ return isRecord(actual) && objectContains(actual, expected);
99
+ }
100
+ return Object.is(actual, expected);
101
+ }
102
+ function objectContains(actual, expected) {
103
+ for (const [key, value] of Object.entries(expected)) {
104
+ if (!matchesValue(actual[key], value)) {
105
+ return false;
106
+ }
107
+ }
108
+ return true;
109
+ }
110
+ function isRecord(value) {
111
+ return typeof value === "object" && value !== null && !Array.isArray(value);
112
+ }
113
+ export {
114
+ createTraceQuery,
115
+ matchesTrace,
116
+ readPath
117
+ };
118
+ //# sourceMappingURL=trace_query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trace-testing/trace_query.ts"],"sourcesContent":["import type { TraceEvent } from '../tracing/index.js';\n\nexport type TraceFilter =\n | ((event: TraceEvent) => boolean)\n | Record<string, unknown>;\n\nexport type TraceCountSummary = Record<string, number>;\n\nexport type TraceQuery = {\n all(): TraceEvent[];\n filter(filter: TraceFilter): TraceEvent[];\n count(filter: TraceFilter): number;\n countByType(types?: string[]): TraceCountSummary;\n payloads(filter: TraceFilter): Record<string, unknown>[];\n first(filter: TraceFilter): TraceEvent | null;\n last(filter: TraceFilter): TraceEvent | null;\n sequence(filters: TraceFilter[]): boolean;\n none(filter: TraceFilter): boolean;\n once(filter: TraceFilter): boolean;\n uniqueBy(filter: TraceFilter, path: string): boolean;\n};\n\ntype TraceSource = TraceEvent[] | (() => TraceEvent[]);\n\nexport function createTraceQuery(source: TraceSource): TraceQuery {\n const readEvents = () => Array.isArray(source) ? source.slice() : source().slice();\n return {\n all: () => readEvents(),\n filter: (filter) => readEvents().filter((event) => matchesTrace(event, filter)),\n count: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length,\n countByType: (types) => countTracesByType(readEvents(), types),\n payloads: (filter) => readEvents()\n .filter((event) => matchesTrace(event, filter))\n .map((event) => event.payload)\n .filter((payload): payload is Record<string, unknown> => isRecord(payload)),\n first: (filter) => readEvents().find((event) => matchesTrace(event, filter)) ?? null,\n last: (filter) => findLastTrace(readEvents(), filter),\n sequence: (filters) => includesTraceSequence(readEvents(), filters),\n none: (filter) => readEvents().every((event) => !matchesTrace(event, filter)),\n once: (filter) => readEvents().filter((event) => matchesTrace(event, filter)).length === 1,\n uniqueBy: (filter, path) => valuesAtPathAreUnique(readEvents(), filter, path),\n };\n}\n\nexport function matchesTrace(event: TraceEvent, filter: TraceFilter): boolean {\n if (typeof filter === 'function') {\n return filter(event);\n }\n for (const [path, expected] of Object.entries(filter)) {\n const actual = readPath(event, path);\n if (!matchesValue(actual, expected)) {\n return false;\n }\n }\n return true;\n}\n\nexport function readPath(value: unknown, path: string): unknown {\n let current = value;\n for (const segment of path.split('.')) {\n if (!isRecord(current)) {\n return undefined;\n }\n current = current[segment];\n }\n return current;\n}\n\nfunction countTracesByType(traces: TraceEvent[], types?: string[]): TraceCountSummary {\n const allowedTypes = types ? new Set(types) : null;\n const counts: TraceCountSummary = {};\n for (const trace of traces) {\n if (allowedTypes && !allowedTypes.has(trace.type)) {\n continue;\n }\n counts[trace.type] = (counts[trace.type] ?? 0) + 1;\n }\n return counts;\n}\n\nfunction findLastTrace(traces: TraceEvent[], filter: TraceFilter): TraceEvent | null {\n for (let index = traces.length - 1; index >= 0; index -= 1) {\n const trace = traces[index];\n if (trace && matchesTrace(trace, filter)) {\n return trace;\n }\n }\n return null;\n}\n\nfunction includesTraceSequence(traces: TraceEvent[], filters: TraceFilter[]): boolean {\n let filterIndex = 0;\n if (filters.length === 0) {\n return true;\n }\n for (const trace of traces) {\n const filter = filters[filterIndex];\n if (!filter || !matchesTrace(trace, filter)) {\n continue;\n }\n filterIndex += 1;\n if (filterIndex === filters.length) {\n return true;\n }\n }\n return false;\n}\n\nfunction valuesAtPathAreUnique(traces: TraceEvent[], filter: TraceFilter, path: string): boolean {\n const seen = new Set<unknown>();\n for (const trace of traces) {\n if (!matchesTrace(trace, filter)) {\n continue;\n }\n const value = readPath(trace, path);\n if (seen.has(value)) {\n return false;\n }\n seen.add(value);\n }\n return true;\n}\n\nfunction matchesValue(actual: unknown, expected: unknown): boolean {\n if (expected instanceof RegExp) {\n return typeof actual === 'string' && expected.test(actual);\n }\n if (typeof expected === 'function') {\n return Boolean((expected as (value: unknown) => boolean)(actual));\n }\n if (isRecord(expected)) {\n return isRecord(actual) && objectContains(actual, expected);\n }\n return Object.is(actual, expected);\n}\n\nfunction objectContains(actual: Record<string, unknown>, expected: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(expected)) {\n if (!matchesValue(actual[key], value)) {\n return false;\n }\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":"AAwBO,SAAS,iBAAiB,QAAiC;AAChE,QAAM,aAAa,MAAM,MAAM,QAAQ,MAAM,IAAI,OAAO,MAAM,IAAI,OAAO,EAAE,MAAM;AACjF,SAAO;AAAA,IACL,KAAK,MAAM,WAAW;AAAA,IACtB,QAAQ,CAAC,WAAW,WAAW,EAAE,OAAO,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC;AAAA,IAC9E,OAAO,CAAC,WAAW,WAAW,EAAE,OAAO,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC,EAAE;AAAA,IAC/E,aAAa,CAAC,UAAU,kBAAkB,WAAW,GAAG,KAAK;AAAA,IAC7D,UAAU,CAAC,WAAW,WAAW,EAC9B,OAAO,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC,EAC7C,IAAI,CAAC,UAAU,MAAM,OAAO,EAC5B,OAAO,CAAC,YAAgD,SAAS,OAAO,CAAC;AAAA,IAC5E,OAAO,CAAC,WAAW,WAAW,EAAE,KAAK,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC,KAAK;AAAA,IAChF,MAAM,CAAC,WAAW,cAAc,WAAW,GAAG,MAAM;AAAA,IACpD,UAAU,CAAC,YAAY,sBAAsB,WAAW,GAAG,OAAO;AAAA,IAClE,MAAM,CAAC,WAAW,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC,aAAa,OAAO,MAAM,CAAC;AAAA,IAC5E,MAAM,CAAC,WAAW,WAAW,EAAE,OAAO,CAAC,UAAU,aAAa,OAAO,MAAM,CAAC,EAAE,WAAW;AAAA,IACzF,UAAU,CAAC,QAAQ,SAAS,sBAAsB,WAAW,GAAG,QAAQ,IAAI;AAAA,EAC9E;AACF;AAEO,SAAS,aAAa,OAAmB,QAA8B;AAC5E,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,MAAM,GAAG;AACrD,UAAM,SAAS,SAAS,OAAO,IAAI;AACnC,QAAI,CAAC,aAAa,QAAQ,QAAQ,GAAG;AACnC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,SAAS,OAAgB,MAAuB;AAC9D,MAAI,UAAU;AACd,aAAW,WAAW,KAAK,MAAM,GAAG,GAAG;AACrC,QAAI,CAAC,SAAS,OAAO,GAAG;AACtB,aAAO;AAAA,IACT;AACA,cAAU,QAAQ,OAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAsB,OAAqC;AACpF,QAAM,eAAe,QAAQ,IAAI,IAAI,KAAK,IAAI;AAC9C,QAAM,SAA4B,CAAC;AACnC,aAAW,SAAS,QAAQ;AAC1B,QAAI,gBAAgB,CAAC,aAAa,IAAI,MAAM,IAAI,GAAG;AACjD;AAAA,IACF;AACA,WAAO,MAAM,IAAI,KAAK,OAAO,MAAM,IAAI,KAAK,KAAK;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,cAAc,QAAsB,QAAwC;AACnF,WAAS,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC1D,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,SAAS,aAAa,OAAO,MAAM,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,QAAsB,SAAiC;AACpF,MAAI,cAAc;AAClB,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AACA,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAAS,QAAQ,WAAW;AAClC,QAAI,CAAC,UAAU,CAAC,aAAa,OAAO,MAAM,GAAG;AAC3C;AAAA,IACF;AACA,mBAAe;AACf,QAAI,gBAAgB,QAAQ,QAAQ;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,QAAsB,QAAqB,MAAuB;AAC/F,QAAM,OAAO,oBAAI,IAAa;AAC9B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,aAAa,OAAO,MAAM,GAAG;AAChC;AAAA,IACF;AACA,UAAM,QAAQ,SAAS,OAAO,IAAI;AAClC,QAAI,KAAK,IAAI,KAAK,GAAG;AACnB,aAAO;AAAA,IACT;AACA,SAAK,IAAI,KAAK;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAAS,aAAa,QAAiB,UAA4B;AACjE,MAAI,oBAAoB,QAAQ;AAC9B,WAAO,OAAO,WAAW,YAAY,SAAS,KAAK,MAAM;AAAA,EAC3D;AACA,MAAI,OAAO,aAAa,YAAY;AAClC,WAAO,QAAS,SAAyC,MAAM,CAAC;AAAA,EAClE;AACA,MAAI,SAAS,QAAQ,GAAG;AACtB,WAAO,SAAS,MAAM,KAAK,eAAe,QAAQ,QAAQ;AAAA,EAC5D;AACA,SAAO,OAAO,GAAG,QAAQ,QAAQ;AACnC;AAEA,SAAS,eAAe,QAAiC,UAA4C;AACnG,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,QAAI,CAAC,aAAa,OAAO,GAAG,GAAG,KAAK,GAAG;AACrC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;","names":[]}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var trace_scenario_exports = {};
20
+ __export(trace_scenario_exports, {
21
+ createTraceScenario: () => createTraceScenario
22
+ });
23
+ module.exports = __toCommonJS(trace_scenario_exports);
24
+ var import_trace_assertions = require("./trace_assertions.js");
25
+ var import_trace_query = require("./trace_query.js");
26
+ function createTraceScenario(options) {
27
+ const { trace, artifactPath, ...captureOptions } = options;
28
+ const capture = trace.capture(captureOptions);
29
+ const assertions = (0, import_trace_assertions.createTraceAssertions)(() => capture.events());
30
+ return {
31
+ capture,
32
+ trace: assertions,
33
+ async run(exercise) {
34
+ try {
35
+ return await exercise({
36
+ waitForTrace: (filter, waitOptions) => capture.waitFor((event) => (0, import_trace_query.matchesTrace)(event, filter), waitOptions),
37
+ trace: assertions
38
+ });
39
+ } catch (error) {
40
+ if (artifactPath) {
41
+ await capture.writeArtifact(artifactPath).catch(() => void 0);
42
+ }
43
+ throw error;
44
+ }
45
+ },
46
+ stop() {
47
+ capture.stop();
48
+ },
49
+ async writeArtifact(targetPath = artifactPath) {
50
+ if (!targetPath) {
51
+ throw new Error("Trace artifact path was not provided.");
52
+ }
53
+ await capture.writeArtifact(targetPath);
54
+ }
55
+ };
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ createTraceScenario
60
+ });
61
+ //# sourceMappingURL=trace_scenario.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trace-testing/trace_scenario.ts"],"sourcesContent":["import type { FrameworkTracer, TraceCapture, TraceCaptureOptions, TraceEvent } from '../tracing/index.js';\nimport { createTraceAssertions, type TraceAssertions } from './trace_assertions.js';\nimport { matchesTrace, type TraceFilter } from './trace_query.js';\n\nexport type TraceScenarioOptions = TraceCaptureOptions & {\n trace: FrameworkTracer;\n artifactPath?: string;\n};\n\nexport type TraceScenarioRunContext = {\n waitForTrace(filter: TraceFilter, options?: { timeoutMs?: number }): Promise<TraceEvent>;\n trace: TraceAssertions;\n};\n\nexport type TraceScenario = {\n readonly capture: TraceCapture;\n readonly trace: TraceAssertions;\n run<T>(exercise: (context: TraceScenarioRunContext) => T | Promise<T>): Promise<T>;\n stop(): void;\n writeArtifact(targetPath?: string): Promise<void>;\n};\n\nexport function createTraceScenario(options: TraceScenarioOptions): TraceScenario {\n const { trace, artifactPath, ...captureOptions } = options;\n const capture = trace.capture(captureOptions);\n const assertions = createTraceAssertions(() => capture.events());\n\n return {\n capture,\n trace: assertions,\n async run(exercise) {\n try {\n return await exercise({\n waitForTrace: (filter, waitOptions) =>\n capture.waitFor((event) => matchesTrace(event, filter), waitOptions),\n trace: assertions,\n });\n } catch (error) {\n if (artifactPath) {\n await capture.writeArtifact(artifactPath).catch(() => undefined);\n }\n throw error;\n }\n },\n stop() {\n capture.stop();\n },\n async writeArtifact(targetPath = artifactPath): Promise<void> {\n if (!targetPath) {\n throw new Error('Trace artifact path was not provided.');\n }\n await capture.writeArtifact(targetPath);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,8BAA4D;AAC5D,yBAA+C;AAoBxC,SAAS,oBAAoB,SAA8C;AAChF,QAAM,EAAE,OAAO,cAAc,GAAG,eAAe,IAAI;AACnD,QAAM,UAAU,MAAM,QAAQ,cAAc;AAC5C,QAAM,iBAAa,+CAAsB,MAAM,QAAQ,OAAO,CAAC;AAE/D,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,MAAM,IAAI,UAAU;AAClB,UAAI;AACF,eAAO,MAAM,SAAS;AAAA,UACpB,cAAc,CAAC,QAAQ,gBACrB,QAAQ,QAAQ,CAAC,cAAU,iCAAa,OAAO,MAAM,GAAG,WAAW;AAAA,UACrE,OAAO;AAAA,QACT,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YAAI,cAAc;AAChB,gBAAM,QAAQ,cAAc,YAAY,EAAE,MAAM,MAAM,MAAS;AAAA,QACjE;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,OAAO;AACL,cAAQ,KAAK;AAAA,IACf;AAAA,IACA,MAAM,cAAc,aAAa,cAA6B;AAC5D,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AACA,YAAM,QAAQ,cAAc,UAAU;AAAA,IACxC;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,27 @@
1
+ import { TraceFilter } from './trace_query.cjs';
2
+ import { TraceAssertions } from './trace_assertions.cjs';
3
+ import { TraceCapture, TraceEvent, TraceCaptureOptions } from '../tracing/trace_hub.cjs';
4
+ import { FrameworkTracer } from '../tracing/trace_provider.cjs';
5
+ import 'rxjs';
6
+ import '@noego/ioc';
7
+
8
+ type TraceScenarioOptions = TraceCaptureOptions & {
9
+ trace: FrameworkTracer;
10
+ artifactPath?: string;
11
+ };
12
+ type TraceScenarioRunContext = {
13
+ waitForTrace(filter: TraceFilter, options?: {
14
+ timeoutMs?: number;
15
+ }): Promise<TraceEvent>;
16
+ trace: TraceAssertions;
17
+ };
18
+ type TraceScenario = {
19
+ readonly capture: TraceCapture;
20
+ readonly trace: TraceAssertions;
21
+ run<T>(exercise: (context: TraceScenarioRunContext) => T | Promise<T>): Promise<T>;
22
+ stop(): void;
23
+ writeArtifact(targetPath?: string): Promise<void>;
24
+ };
25
+ declare function createTraceScenario(options: TraceScenarioOptions): TraceScenario;
26
+
27
+ export { type TraceScenario, type TraceScenarioOptions, type TraceScenarioRunContext, createTraceScenario };
@@ -0,0 +1,27 @@
1
+ import { TraceFilter } from './trace_query.js';
2
+ import { TraceAssertions } from './trace_assertions.js';
3
+ import { TraceCapture, TraceEvent, TraceCaptureOptions } from '../tracing/trace_hub.js';
4
+ import { FrameworkTracer } from '../tracing/trace_provider.js';
5
+ import 'rxjs';
6
+ import '@noego/ioc';
7
+
8
+ type TraceScenarioOptions = TraceCaptureOptions & {
9
+ trace: FrameworkTracer;
10
+ artifactPath?: string;
11
+ };
12
+ type TraceScenarioRunContext = {
13
+ waitForTrace(filter: TraceFilter, options?: {
14
+ timeoutMs?: number;
15
+ }): Promise<TraceEvent>;
16
+ trace: TraceAssertions;
17
+ };
18
+ type TraceScenario = {
19
+ readonly capture: TraceCapture;
20
+ readonly trace: TraceAssertions;
21
+ run<T>(exercise: (context: TraceScenarioRunContext) => T | Promise<T>): Promise<T>;
22
+ stop(): void;
23
+ writeArtifact(targetPath?: string): Promise<void>;
24
+ };
25
+ declare function createTraceScenario(options: TraceScenarioOptions): TraceScenario;
26
+
27
+ export { type TraceScenario, type TraceScenarioOptions, type TraceScenarioRunContext, createTraceScenario };
@@ -0,0 +1,37 @@
1
+ import { createTraceAssertions } from "./trace_assertions.js";
2
+ import { matchesTrace } from "./trace_query.js";
3
+ function createTraceScenario(options) {
4
+ const { trace, artifactPath, ...captureOptions } = options;
5
+ const capture = trace.capture(captureOptions);
6
+ const assertions = createTraceAssertions(() => capture.events());
7
+ return {
8
+ capture,
9
+ trace: assertions,
10
+ async run(exercise) {
11
+ try {
12
+ return await exercise({
13
+ waitForTrace: (filter, waitOptions) => capture.waitFor((event) => matchesTrace(event, filter), waitOptions),
14
+ trace: assertions
15
+ });
16
+ } catch (error) {
17
+ if (artifactPath) {
18
+ await capture.writeArtifact(artifactPath).catch(() => void 0);
19
+ }
20
+ throw error;
21
+ }
22
+ },
23
+ stop() {
24
+ capture.stop();
25
+ },
26
+ async writeArtifact(targetPath = artifactPath) {
27
+ if (!targetPath) {
28
+ throw new Error("Trace artifact path was not provided.");
29
+ }
30
+ await capture.writeArtifact(targetPath);
31
+ }
32
+ };
33
+ }
34
+ export {
35
+ createTraceScenario
36
+ };
37
+ //# sourceMappingURL=trace_scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trace-testing/trace_scenario.ts"],"sourcesContent":["import type { FrameworkTracer, TraceCapture, TraceCaptureOptions, TraceEvent } from '../tracing/index.js';\nimport { createTraceAssertions, type TraceAssertions } from './trace_assertions.js';\nimport { matchesTrace, type TraceFilter } from './trace_query.js';\n\nexport type TraceScenarioOptions = TraceCaptureOptions & {\n trace: FrameworkTracer;\n artifactPath?: string;\n};\n\nexport type TraceScenarioRunContext = {\n waitForTrace(filter: TraceFilter, options?: { timeoutMs?: number }): Promise<TraceEvent>;\n trace: TraceAssertions;\n};\n\nexport type TraceScenario = {\n readonly capture: TraceCapture;\n readonly trace: TraceAssertions;\n run<T>(exercise: (context: TraceScenarioRunContext) => T | Promise<T>): Promise<T>;\n stop(): void;\n writeArtifact(targetPath?: string): Promise<void>;\n};\n\nexport function createTraceScenario(options: TraceScenarioOptions): TraceScenario {\n const { trace, artifactPath, ...captureOptions } = options;\n const capture = trace.capture(captureOptions);\n const assertions = createTraceAssertions(() => capture.events());\n\n return {\n capture,\n trace: assertions,\n async run(exercise) {\n try {\n return await exercise({\n waitForTrace: (filter, waitOptions) =>\n capture.waitFor((event) => matchesTrace(event, filter), waitOptions),\n trace: assertions,\n });\n } catch (error) {\n if (artifactPath) {\n await capture.writeArtifact(artifactPath).catch(() => undefined);\n }\n throw error;\n }\n },\n stop() {\n capture.stop();\n },\n async writeArtifact(targetPath = artifactPath): Promise<void> {\n if (!targetPath) {\n throw new Error('Trace artifact path was not provided.');\n }\n await capture.writeArtifact(targetPath);\n },\n };\n}\n"],"mappings":"AACA,SAAS,6BAAmD;AAC5D,SAAS,oBAAsC;AAoBxC,SAAS,oBAAoB,SAA8C;AAChF,QAAM,EAAE,OAAO,cAAc,GAAG,eAAe,IAAI;AACnD,QAAM,UAAU,MAAM,QAAQ,cAAc;AAC5C,QAAM,aAAa,sBAAsB,MAAM,QAAQ,OAAO,CAAC;AAE/D,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,MAAM,IAAI,UAAU;AAClB,UAAI;AACF,eAAO,MAAM,SAAS;AAAA,UACpB,cAAc,CAAC,QAAQ,gBACrB,QAAQ,QAAQ,CAAC,UAAU,aAAa,OAAO,MAAM,GAAG,WAAW;AAAA,UACrE,OAAO;AAAA,QACT,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YAAI,cAAc;AAChB,gBAAM,QAAQ,cAAc,YAAY,EAAE,MAAM,MAAM,MAAS;AAAA,QACjE;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,OAAO;AACL,cAAQ,KAAK;AAAA,IACf;AAAA,IACA,MAAM,cAAc,aAAa,cAA6B;AAC5D,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AACA,YAAM,QAAQ,cAAc,UAAU;AAAA,IACxC;AAAA,EACF;AACF;","names":[]}
@@ -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 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,uBAoBO;AAEP,4BAUO;","names":[]}
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,4 +1,4 @@
1
- export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.cjs';
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';
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, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceEnabled, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.js';
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';
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 +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 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,OAQK;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 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":[]}
@@ -60,15 +60,32 @@ function normalizeTraceInput(raw) {
60
60
  const type = typeof input.type === "string" && input.type.trim().length > 0 ? input.type : "unknown";
61
61
  const message = typeof input.message === "string" ? input.message : void 0;
62
62
  const conversationId = typeof input.conversationId === "number" || typeof input.conversationId === "string" ? input.conversationId : void 0;
63
+ const windowId = typeof input.windowId === "string" && input.windowId.trim().length > 0 ? input.windowId : void 0;
64
+ const webContentsId = typeof input.webContentsId === "number" && Number.isFinite(input.webContentsId) ? input.webContentsId : void 0;
65
+ const routeKey = typeof input.routeKey === "string" && input.routeKey.trim().length > 0 ? input.routeKey : void 0;
66
+ const harnessId = typeof input.harnessId === "string" && input.harnessId.trim().length > 0 ? input.harnessId : void 0;
63
67
  const payload = isRecord(input.payload) ? { ...input.payload } : void 0;
64
68
  return {
65
69
  source,
66
70
  type,
67
71
  ...message ? { message } : {},
68
72
  ...conversationId !== void 0 ? { conversationId } : {},
73
+ ...windowId !== void 0 ? { windowId } : {},
74
+ ...webContentsId !== void 0 ? { webContentsId } : {},
75
+ ...routeKey !== void 0 ? { routeKey } : {},
76
+ ...harnessId !== void 0 ? { harnessId } : {},
69
77
  ...payload ? { payload } : {}
70
78
  };
71
79
  }
80
+ function mergeTraceRuntimeContext(input, context) {
81
+ if (!context) {
82
+ return normalizeTraceInput(input);
83
+ }
84
+ return normalizeTraceInput({
85
+ ...isRecord(input) ? input : {},
86
+ ...context
87
+ });
88
+ }
72
89
  function isRecord(value) {
73
90
  return typeof value === "object" && value !== null && !Array.isArray(value);
74
91
  }
@@ -205,10 +222,10 @@ function publishMainTrace(level, input) {
205
222
  function publishTestTrace(process, level, input) {
206
223
  return getGlobalTraceHub().publish(process, level, input);
207
224
  }
208
- function dispatchRendererTracePayload(rawPayload) {
225
+ function dispatchRendererTracePayload(rawPayload, context) {
209
226
  const payload = rawPayload ?? {};
210
227
  const level = payload.level === "debug" || payload.level === "info" || payload.level === "warn" || payload.level === "error" ? payload.level : "info";
211
- getGlobalTraceHub().publish("renderer", level, payload);
228
+ getGlobalTraceHub().publish("renderer", level, mergeTraceRuntimeContext(payload, context));
212
229
  return {
213
230
  ok: true,
214
231
  forwarded: true