@flanksource/clicky-ui 0.3.47 → 0.3.48

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 (169) hide show
  1. package/README.md +49 -0
  2. package/dist/comments/CommentSidePanel.cjs +10 -4
  3. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  4. package/dist/comments/CommentSidePanel.d.ts +2 -0
  5. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  6. package/dist/comments/CommentSidePanel.js +10 -4
  7. package/dist/comments/CommentSidePanel.js.map +1 -1
  8. package/dist/comments/CommentThread.cjs +2 -0
  9. package/dist/comments/CommentThread.cjs.map +1 -1
  10. package/dist/comments/CommentThread.d.ts +2 -1
  11. package/dist/comments/CommentThread.d.ts.map +1 -1
  12. package/dist/comments/CommentThread.js +2 -0
  13. package/dist/comments/CommentThread.js.map +1 -1
  14. package/dist/comments/CommentThreadList.cjs +3 -0
  15. package/dist/comments/CommentThreadList.cjs.map +1 -1
  16. package/dist/comments/CommentThreadList.d.ts +3 -1
  17. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  18. package/dist/comments/CommentThreadList.js +3 -0
  19. package/dist/comments/CommentThreadList.js.map +1 -1
  20. package/dist/data/CodeLine.cjs +4 -2
  21. package/dist/data/CodeLine.cjs.map +1 -1
  22. package/dist/data/CodeLine.d.ts.map +1 -1
  23. package/dist/data/CodeLine.js +4 -2
  24. package/dist/data/CodeLine.js.map +1 -1
  25. package/dist/data/SymbolBadge.cjs +61 -0
  26. package/dist/data/SymbolBadge.cjs.map +1 -0
  27. package/dist/data/SymbolBadge.d.ts +21 -0
  28. package/dist/data/SymbolBadge.d.ts.map +1 -0
  29. package/dist/data/SymbolBadge.js +61 -0
  30. package/dist/data/SymbolBadge.js.map +1 -0
  31. package/dist/data/test-runner/TestDetailPanel.cjs +26 -12
  32. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  33. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  34. package/dist/data/test-runner/TestDetailPanel.js +27 -13
  35. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  36. package/dist/data/test-runner/TestRunner.cjs +6 -0
  37. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  38. package/dist/data/test-runner/TestRunner.d.ts +3 -1
  39. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  40. package/dist/data/test-runner/TestRunner.js +6 -0
  41. package/dist/data/test-runner/TestRunner.js.map +1 -1
  42. package/dist/data/test-runner/TestTreeNode.cjs +2 -1
  43. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  44. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  45. package/dist/data/test-runner/TestTreeNode.js +2 -1
  46. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  47. package/dist/data/test-runner/adapter.cjs +4 -0
  48. package/dist/data/test-runner/adapter.cjs.map +1 -1
  49. package/dist/data/test-runner/adapter.d.ts +9 -0
  50. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  51. package/dist/data/test-runner/adapter.js +4 -0
  52. package/dist/data/test-runner/adapter.js.map +1 -1
  53. package/dist/data/test-runner/context.cjs.map +1 -1
  54. package/dist/data/test-runner/context.d.ts +2 -0
  55. package/dist/data/test-runner/context.d.ts.map +1 -1
  56. package/dist/data/test-runner/context.js.map +1 -1
  57. package/dist/data/test-runner/index.d.ts +2 -2
  58. package/dist/data/test-runner/index.d.ts.map +1 -1
  59. package/dist/data/test-runner/marks.cjs +42 -1
  60. package/dist/data/test-runner/marks.cjs.map +1 -1
  61. package/dist/data/test-runner/marks.d.ts +10 -0
  62. package/dist/data/test-runner/marks.d.ts.map +1 -1
  63. package/dist/data/test-runner/marks.js +42 -1
  64. package/dist/data/test-runner/marks.js.map +1 -1
  65. package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
  66. package/dist/data/traces/TerminalCastPlayer.d.ts.map +1 -0
  67. package/dist/data/traces/TraceHarView.d.ts +13 -0
  68. package/dist/data/traces/TraceHarView.d.ts.map +1 -0
  69. package/dist/data/traces/cast.d.ts +9 -0
  70. package/dist/data/traces/cast.d.ts.map +1 -0
  71. package/dist/data/traces/fixtures.d.ts +8 -0
  72. package/dist/data/traces/fixtures.d.ts.map +1 -0
  73. package/dist/data/traces/har-adapter.d.ts +13 -0
  74. package/dist/data/traces/har-adapter.d.ts.map +1 -0
  75. package/dist/data/traces/terminal-screen.d.ts +45 -0
  76. package/dist/data/traces/terminal-screen.d.ts.map +1 -0
  77. package/dist/data/traces/terminal-timeline.d.ts +26 -0
  78. package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
  79. package/dist/data/traces/types.d.ts +141 -0
  80. package/dist/data/traces/types.d.ts.map +1 -0
  81. package/dist/data/verification/VerificationResults.cjs +4 -0
  82. package/dist/data/verification/VerificationResults.cjs.map +1 -1
  83. package/dist/data/verification/VerificationResults.d.ts +3 -1
  84. package/dist/data/verification/VerificationResults.d.ts.map +1 -1
  85. package/dist/data/verification/VerificationResults.js +4 -0
  86. package/dist/data/verification/VerificationResults.js.map +1 -1
  87. package/dist/data/verification/adapterViews.cjs +12 -3
  88. package/dist/data/verification/adapterViews.cjs.map +1 -1
  89. package/dist/data/verification/adapterViews.d.ts +4 -1
  90. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  91. package/dist/data/verification/adapterViews.js +12 -3
  92. package/dist/data/verification/adapterViews.js.map +1 -1
  93. package/dist/data/verification/adapters.cjs +53 -10
  94. package/dist/data/verification/adapters.cjs.map +1 -1
  95. package/dist/data/verification/adapters.d.ts +7 -1
  96. package/dist/data/verification/adapters.d.ts.map +1 -1
  97. package/dist/data/verification/adapters.js +53 -10
  98. package/dist/data/verification/adapters.js.map +1 -1
  99. package/dist/data/verification/index.d.ts +4 -2
  100. package/dist/data/verification/index.d.ts.map +1 -1
  101. package/dist/data/verification/stepKind.cjs +217 -0
  102. package/dist/data/verification/stepKind.cjs.map +1 -0
  103. package/dist/data/verification/stepKind.d.ts +87 -0
  104. package/dist/data/verification/stepKind.d.ts.map +1 -0
  105. package/dist/data/verification/stepKind.js +217 -0
  106. package/dist/data/verification/stepKind.js.map +1 -0
  107. package/dist/data/verification/stepKindViews.cjs +111 -0
  108. package/dist/data/verification/stepKindViews.cjs.map +1 -0
  109. package/dist/data/verification/stepKindViews.d.ts +18 -0
  110. package/dist/data/verification/stepKindViews.d.ts.map +1 -0
  111. package/dist/data/verification/stepKindViews.js +111 -0
  112. package/dist/data/verification/stepKindViews.js.map +1 -0
  113. package/dist/data/verification/verifyReportTests.cjs +1 -0
  114. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  115. package/dist/data/verification/verifyReportTests.d.ts +2 -1
  116. package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
  117. package/dist/data/verification/verifyReportTests.js +1 -0
  118. package/dist/data/verification/verifyReportTests.js.map +1 -1
  119. package/dist/data/version-info.cjs +3 -3
  120. package/dist/data/version-info.js +3 -3
  121. package/dist/data.cjs +14 -0
  122. package/dist/data.cjs.map +1 -1
  123. package/dist/data.d.ts +1 -0
  124. package/dist/data.d.ts.map +1 -1
  125. package/dist/data.js +16 -2
  126. package/dist/data.js.map +1 -1
  127. package/dist/index.cjs +16 -0
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.js +18 -2
  130. package/dist/index.js.map +1 -1
  131. package/dist/rpc/FilterForm.cjs +9 -0
  132. package/dist/rpc/FilterForm.cjs.map +1 -1
  133. package/dist/rpc/FilterForm.d.ts +5 -1
  134. package/dist/rpc/FilterForm.d.ts.map +1 -1
  135. package/dist/rpc/FilterForm.js +9 -0
  136. package/dist/rpc/FilterForm.js.map +1 -1
  137. package/dist/rpc/OperationArgsForm.cjs +153 -0
  138. package/dist/rpc/OperationArgsForm.cjs.map +1 -0
  139. package/dist/rpc/OperationArgsForm.d.ts +16 -0
  140. package/dist/rpc/OperationArgsForm.d.ts.map +1 -0
  141. package/dist/rpc/OperationArgsForm.js +153 -0
  142. package/dist/rpc/OperationArgsForm.js.map +1 -0
  143. package/dist/rpc/OperationScheduleDialog.cjs +61 -17
  144. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  145. package/dist/rpc/OperationScheduleDialog.d.ts +3 -0
  146. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  147. package/dist/rpc/OperationScheduleDialog.js +62 -18
  148. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  149. package/dist/rpc/OperationSchedules.cjs +6 -1
  150. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  151. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  152. package/dist/rpc/OperationSchedules.js +6 -1
  153. package/dist/rpc/OperationSchedules.js.map +1 -1
  154. package/dist/rpc/operation-schedule-model.cjs +0 -7
  155. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  156. package/dist/rpc/operation-schedule-model.d.ts +0 -2
  157. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  158. package/dist/rpc/operation-schedule-model.js +0 -7
  159. package/dist/rpc/operation-schedule-model.js.map +1 -1
  160. package/dist/rpc/operation-schedule-types.d.ts +6 -1
  161. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  162. package/dist/rpc.cjs +2 -0
  163. package/dist/rpc.cjs.map +1 -1
  164. package/dist/rpc.d.ts +1 -0
  165. package/dist/rpc.d.ts.map +1 -1
  166. package/dist/rpc.js +2 -0
  167. package/dist/rpc.js.map +1 -1
  168. package/dist/styles.css +1 -1
  169. package/package.json +1 -1
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const status = require("../test-runner/status.cjs");
4
+ const WAIT_OUTCOMES = ["satisfied", "failed", "timeout"];
5
+ const WATCHER_EVENT_TYPES = ["alert", "console", "pageerror", "response"];
6
+ const STEP_KEYS = /* @__PURE__ */ new Set(["step", "outputs", "exports", "wait", "attempts", "events", "background"]);
7
+ class StepDetailError extends Error {
8
+ }
9
+ function fail(path, expectation) {
10
+ throw new StepDetailError(`${path} must be ${expectation}`);
11
+ }
12
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
13
+ function record(value, path) {
14
+ return isRecord(value) ? value : fail(path, "an object");
15
+ }
16
+ function list(value, path) {
17
+ return Array.isArray(value) ? value : fail(path, "an array");
18
+ }
19
+ function str(value, path) {
20
+ return typeof value === "string" ? value : fail(path, "a string");
21
+ }
22
+ function num(value, path) {
23
+ return typeof value === "number" && Number.isFinite(value) ? value : fail(path, "a number");
24
+ }
25
+ function bool(value, path) {
26
+ return typeof value === "boolean" ? value : fail(path, "a boolean");
27
+ }
28
+ function oneOf(value, allowed, path) {
29
+ return allowed.includes(value) ? value : fail(path, `one of ${allowed.join(", ")} (got ${JSON.stringify(value)})`);
30
+ }
31
+ function optional(source, key, read) {
32
+ return source[key] === void 0 || source[key] === null ? {} : { [key]: read(source[key]) };
33
+ }
34
+ function durationText(value, path) {
35
+ if (typeof value === "string") return value;
36
+ if (typeof value === "number") return status.formatTestDuration(value);
37
+ return fail(path, "a duration string or nanosecond number");
38
+ }
39
+ function scalarText(value, path) {
40
+ if (typeof value === "string") return value;
41
+ if (typeof value === "number") return String(value);
42
+ return fail(path, "a string or number");
43
+ }
44
+ function readPolicy(value) {
45
+ const path = "detail.wait.policy";
46
+ const policy = record(value, path);
47
+ const backoff = (raw) => {
48
+ const b = record(raw, `${path}.backoff`);
49
+ return {
50
+ ...optional(b, "factor", (v) => num(v, `${path}.backoff.factor`)),
51
+ ...optional(b, "max", (v) => durationText(v, `${path}.backoff.max`))
52
+ };
53
+ };
54
+ return {
55
+ ...optional(policy, "until", (v) => str(v, `${path}.until`)),
56
+ ...optional(policy, "failWhen", (v) => str(v, `${path}.failWhen`)),
57
+ ...optional(policy, "interval", (v) => durationText(v, `${path}.interval`)),
58
+ ...optional(policy, "backoff", backoff),
59
+ ...optional(policy, "jitter", (v) => scalarText(v, `${path}.jitter`)),
60
+ ...optional(policy, "timeout", (v) => durationText(v, `${path}.timeout`))
61
+ };
62
+ }
63
+ function readWait(value) {
64
+ const wait = record(value, "detail.wait");
65
+ return {
66
+ policy: readPolicy(wait.policy ?? {}),
67
+ outcome: oneOf(wait.outcome, WAIT_OUTCOMES, "detail.wait.outcome"),
68
+ durationMs: nonnegative(wait.durationMs, "detail.wait.durationMs"),
69
+ ...wait.outputs === void 0 ? {} : { outputs: wait.outputs },
70
+ ...optional(wait, "error", (v) => str(v, "detail.wait.error")),
71
+ ...optional(wait, "trace", (v) => str(v, "detail.wait.trace"))
72
+ };
73
+ }
74
+ function nonnegative(value, path) {
75
+ const result = num(value, path);
76
+ return result >= 0 ? result : fail(path, "non-negative");
77
+ }
78
+ function readAttemptResult(value, path) {
79
+ const node = record(value, path);
80
+ str(node.name, `${path}.name`);
81
+ for (const key of ["framework", "message", "command", "work_dir", "stdout", "stderr"]) {
82
+ if (node[key] !== void 0) str(node[key], `${path}.${key}`);
83
+ }
84
+ for (const key of ["passed", "failed", "timed_out", "warned", "skipped", "pending", "running"]) {
85
+ if (node[key] !== void 0) bool(node[key], `${path}.${key}`);
86
+ }
87
+ if (node.duration !== void 0) nonnegative(node.duration, `${path}.duration`);
88
+ if (node.children !== void 0) list(node.children, `${path}.children`).forEach((child, i) => readAttemptResult(child, `${path}.children[${i}]`));
89
+ return { ...node, name: str(node.name, `${path}.name`) };
90
+ }
91
+ function readAttempt(value, index) {
92
+ const path = `detail.attempts[${index}]`;
93
+ const a = record(value, path);
94
+ return {
95
+ attempt: num(a.attempt, `${path}.attempt`),
96
+ status: str(a.status, `${path}.status`),
97
+ ...optional(a, "error", (v) => str(v, `${path}.error`)),
98
+ ...optional(a, "durationMs", (v) => nonnegative(v, `${path}.durationMs`)),
99
+ ...optional(a, "result", (v) => readAttemptResult(v, `${path}.result`))
100
+ };
101
+ }
102
+ function readAttempts(value) {
103
+ const attempts = list(value, "detail.attempts").map(readAttempt);
104
+ attempts.forEach((attempt, index) => {
105
+ if (attempt.attempt !== index + 1) fail(`detail.attempts[${index}].attempt`, `the sequence number ${index + 1}`);
106
+ });
107
+ return attempts;
108
+ }
109
+ function readExports(value) {
110
+ return Object.entries(record(value, "detail.exports")).map(([name, raw]) => {
111
+ const path = `detail.exports.${name}`;
112
+ const entry = record(raw, path);
113
+ return { name, value: entry.value, step: str(entry.step, `${path}.step`) };
114
+ });
115
+ }
116
+ function readEvent(value, index) {
117
+ const path = `detail.events[${index}]`;
118
+ const e = record(value, path);
119
+ return {
120
+ type: oneOf(e.type, WATCHER_EVENT_TYPES, `${path}.type`),
121
+ ...optional(e, "text", (v) => str(v, `${path}.text`)),
122
+ ...optional(e, "url", (v) => str(v, `${path}.url`)),
123
+ ...optional(e, "status", (v) => num(v, `${path}.status`)),
124
+ ...optional(e, "detail", (v) => str(v, `${path}.detail`))
125
+ };
126
+ }
127
+ function readStep(detail) {
128
+ const ref = record(detail.step, "detail.step");
129
+ const rest = Object.fromEntries(Object.entries(detail).filter(([key]) => !STEP_KEYS.has(key)));
130
+ return {
131
+ step: { id: str(ref.id, "detail.step.id"), kind: str(ref.kind, "detail.step.kind") },
132
+ ...detail.outputs === void 0 ? {} : { outputs: detail.outputs },
133
+ exports: detail.exports == null ? [] : readExports(detail.exports),
134
+ ...optional(detail, "wait", readWait),
135
+ attempts: readAttempts(detail.attempts ?? []),
136
+ events: list(detail.events ?? [], "detail.events").map(readEvent),
137
+ background: bool(detail.background ?? false, "detail.background"),
138
+ rest
139
+ };
140
+ }
141
+ function readStepDetail(detail) {
142
+ if (!isRecord(detail) || detail.step === void 0) return { kind: "none" };
143
+ try {
144
+ return { kind: "step", step: readStep(detail) };
145
+ } catch (error) {
146
+ if (error instanceof StepDetailError) return { kind: "invalid", error: error.message };
147
+ throw error;
148
+ }
149
+ }
150
+ function hasStepDetail(detail) {
151
+ return readStepDetail(detail).kind !== "none";
152
+ }
153
+ function clockTime(at) {
154
+ var _a;
155
+ return ((_a = /T(\d{2}:\d{2}:\d{2})/.exec(at)) == null ? void 0 : _a[1]) ?? at;
156
+ }
157
+ function formatDelay(ms) {
158
+ return ms <= 0 ? "0ms" : status.formatTestDuration(ms * 1e6);
159
+ }
160
+ function policySummary(policy) {
161
+ var _a, _b;
162
+ const backoff = [
163
+ ((_a = policy.backoff) == null ? void 0 : _a.factor) !== void 0 && `×${policy.backoff.factor}`,
164
+ ((_b = policy.backoff) == null ? void 0 : _b.max) && `up to ${policy.backoff.max}`
165
+ ].filter(Boolean);
166
+ return [
167
+ policy.interval && `every ${policy.interval}`,
168
+ backoff.length > 0 && `backoff ${backoff.join(" ")}`,
169
+ policy.jitter && `jitter ±${policy.jitter}`,
170
+ policy.timeout && `timeout ${policy.timeout}`
171
+ ].filter(Boolean).join(" · ");
172
+ }
173
+ function formatExportValue(value) {
174
+ if (value === void 0) return "";
175
+ return typeof value === "string" ? value : JSON.stringify(value);
176
+ }
177
+ function waitCopy(wait) {
178
+ const { policy } = wait;
179
+ const lines = [
180
+ `outcome: ${wait.outcome}`,
181
+ `elapsed: ${formatDelay(wait.durationMs)}`,
182
+ `policy: ${policySummary(policy)}`,
183
+ policy.until && `until: ${policy.until}`,
184
+ policy.failWhen && `failWhen: ${policy.failWhen}`,
185
+ wait.error && `error: ${wait.error}`,
186
+ wait.trace && `trace: ${wait.trace}`,
187
+ wait.outputs !== void 0 && `outputs: ${JSON.stringify(wait.outputs)}`
188
+ ];
189
+ return { title: "Wait", body: lines.filter(Boolean).join("\n") };
190
+ }
191
+ function attemptLine(a) {
192
+ const head = [`#${a.attempt}`, a.status, a.durationMs !== void 0 && formatDelay(a.durationMs)];
193
+ return `${head.filter(Boolean).join(" ")}${a.error ? ` — ${a.error}` : ""}`;
194
+ }
195
+ function eventLine(e) {
196
+ const body = [e.status, e.text, e.url].filter((part) => part !== void 0).join(" ");
197
+ return `[${e.type}]${body ? ` ${body}` : ""}${e.detail ? ` — ${e.detail}` : ""}`;
198
+ }
199
+ function stepKindCopy(step) {
200
+ return [
201
+ ...step.outputs !== void 0 ? [{ title: "Outputs", body: JSON.stringify(step.outputs, null, 2), lang: "json" }] : [],
202
+ ...step.wait ? [waitCopy(step.wait)] : [],
203
+ ...step.attempts.length > 0 ? [{ title: "Attempts", body: step.attempts.map(attemptLine).join("\n") }] : [],
204
+ ...step.exports.length > 0 ? [{ title: "Exports", body: step.exports.map((e) => `${e.name}=${formatExportValue(e.value)} (from ${e.step})`).join("\n") }] : [],
205
+ ...step.events.length > 0 ? [{ title: "Events", body: step.events.map(eventLine).join("\n") }] : []
206
+ ];
207
+ }
208
+ exports.WAIT_OUTCOMES = WAIT_OUTCOMES;
209
+ exports.WATCHER_EVENT_TYPES = WATCHER_EVENT_TYPES;
210
+ exports.clockTime = clockTime;
211
+ exports.formatDelay = formatDelay;
212
+ exports.formatExportValue = formatExportValue;
213
+ exports.hasStepDetail = hasStepDetail;
214
+ exports.policySummary = policySummary;
215
+ exports.readStepDetail = readStepDetail;
216
+ exports.stepKindCopy = stepKindCopy;
217
+ //# sourceMappingURL=stepKind.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepKind.cjs","sources":["../../../src/data/verification/stepKind.ts"],"sourcesContent":["// The typed step-kind detail gavel's fixture verifier attaches to a node\n// (fixtures/verifier/report.go): `detail.step` names the kind and id, beside\n// the structured `wait`, `attempts`, `exports`, `outputs` and (for a\n// background Playwright watcher) `events`. Parsed here, once, so the detail\n// view and the copy brief read the same typed shape. A present-but-malformed\n// field is reported by path instead of being guessed at.\n\nimport type { BriefSection } from \"../test-runner\";\nimport { formatTestDuration } from \"../test-runner\";\nimport type { VerifyNode } from \"./verify-report\";\n\nexport type StepRef = { id: string; kind: string };\n\nexport type WaitPolicy = {\n until?: string;\n failWhen?: string;\n interval?: string;\n backoff?: { factor?: number; max?: string };\n jitter?: string;\n timeout?: string;\n};\n\nexport const WAIT_OUTCOMES = [\"satisfied\", \"failed\", \"timeout\"] as const;\nexport type WaitOutcome = (typeof WAIT_OUTCOMES)[number];\n\nexport type WaitDetail = { policy: WaitPolicy; outcome: WaitOutcome; durationMs: number; outputs?: unknown; error?: string; trace?: string };\n\nexport type StepAttempt = { attempt: number; status: string; error?: string; durationMs?: number; result?: VerifyNode };\n\nexport type StepExport = { name: string; value: unknown; step: string };\n\nexport const WATCHER_EVENT_TYPES = [\"alert\", \"console\", \"pageerror\", \"response\"] as const;\nexport type WatcherEventType = (typeof WATCHER_EVENT_TYPES)[number];\n\nexport type WatcherEvent = {\n type: WatcherEventType;\n text?: string;\n url?: string;\n status?: number;\n detail?: string;\n};\n\nexport type StepDetail = {\n step: StepRef;\n outputs?: unknown;\n exports: StepExport[];\n wait?: WaitDetail;\n attempts: StepAttempt[];\n events: WatcherEvent[];\n /** Whether the step runs in the background until teardown (a watcher). */\n background: boolean;\n /** Everything else in `node.detail` (cel_trace, run, recordings, …). */\n rest: Record<string, unknown>;\n};\n\nexport type StepDetailResult =\n | { kind: \"none\" }\n | { kind: \"step\"; step: StepDetail }\n | { kind: \"invalid\"; error: string };\n\nconst STEP_KEYS = new Set([\"step\", \"outputs\", \"exports\", \"wait\", \"attempts\", \"events\", \"background\"]);\n\nclass StepDetailError extends Error {}\n\nfunction fail(path: string, expectation: string): never {\n throw new StepDetailError(`${path} must be ${expectation}`);\n}\n\ntype Rec = Record<string, unknown>;\n\nconst isRecord = (value: unknown): value is Rec =>\n value !== null && typeof value === \"object\" && !Array.isArray(value);\n\nfunction record(value: unknown, path: string): Rec {\n return isRecord(value) ? value : fail(path, \"an object\");\n}\n\nfunction list(value: unknown, path: string): unknown[] {\n return Array.isArray(value) ? value : fail(path, \"an array\");\n}\n\nfunction str(value: unknown, path: string): string {\n return typeof value === \"string\" ? value : fail(path, \"a string\");\n}\n\nfunction num(value: unknown, path: string): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : fail(path, \"a number\");\n}\n\nfunction bool(value: unknown, path: string): boolean {\n return typeof value === \"boolean\" ? value : fail(path, \"a boolean\");\n}\n\nfunction oneOf<T extends string>(value: unknown, allowed: readonly T[], path: string): T {\n return allowed.includes(value as T)\n ? (value as T)\n : fail(path, `one of ${allowed.join(\", \")} (got ${JSON.stringify(value)})`);\n}\n\n/** `{ [key]: read(value) }` when the optional field is present, else `{}` — absent stays an absent key. */\nfunction optional<K extends string, T>(source: Rec, key: K, read: (value: unknown) => T): { [P in K]?: T } {\n return source[key] === undefined || source[key] === null ? {} : ({ [key]: read(source[key]) } as { [P in K]?: T });\n}\n\n/** Durations arrive as Go-style strings (\"15s\"); a bare number is nanoseconds like every other duration on the wire. */\nfunction durationText(value: unknown, path: string): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return formatTestDuration(value);\n return fail(path, \"a duration string or nanosecond number\");\n}\n\nfunction scalarText(value: unknown, path: string): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return String(value);\n return fail(path, \"a string or number\");\n}\n\nfunction readPolicy(value: unknown): WaitPolicy {\n const path = \"detail.wait.policy\";\n const policy = record(value, path);\n const backoff = (raw: unknown) => {\n const b = record(raw, `${path}.backoff`);\n return {\n ...optional(b, \"factor\", (v) => num(v, `${path}.backoff.factor`)),\n ...optional(b, \"max\", (v) => durationText(v, `${path}.backoff.max`)),\n };\n };\n return {\n ...optional(policy, \"until\", (v) => str(v, `${path}.until`)),\n ...optional(policy, \"failWhen\", (v) => str(v, `${path}.failWhen`)),\n ...optional(policy, \"interval\", (v) => durationText(v, `${path}.interval`)),\n ...optional(policy, \"backoff\", backoff),\n ...optional(policy, \"jitter\", (v) => scalarText(v, `${path}.jitter`)),\n ...optional(policy, \"timeout\", (v) => durationText(v, `${path}.timeout`)),\n };\n}\n\nfunction readWait(value: unknown): WaitDetail {\n const wait = record(value, \"detail.wait\");\n return {\n policy: readPolicy(wait.policy ?? {}),\n outcome: oneOf(wait.outcome, WAIT_OUTCOMES, \"detail.wait.outcome\"),\n durationMs: nonnegative(wait.durationMs, \"detail.wait.durationMs\"),\n ...(wait.outputs === undefined ? {} : { outputs: wait.outputs }),\n ...optional(wait, \"error\", (v) => str(v, \"detail.wait.error\")),\n ...optional(wait, \"trace\", (v) => str(v, \"detail.wait.trace\")),\n };\n}\n\nfunction nonnegative(value: unknown, path: string): number {\n const result = num(value, path);\n return result >= 0 ? result : fail(path, \"non-negative\");\n}\n\nfunction readAttemptResult(value: unknown, path: string): VerifyNode {\n const node = record(value, path);\n str(node.name, `${path}.name`);\n for (const key of [\"framework\", \"message\", \"command\", \"work_dir\", \"stdout\", \"stderr\"]) {\n if (node[key] !== undefined) str(node[key], `${path}.${key}`);\n }\n for (const key of [\"passed\", \"failed\", \"timed_out\", \"warned\", \"skipped\", \"pending\", \"running\"]) {\n if (node[key] !== undefined) bool(node[key], `${path}.${key}`);\n }\n if (node.duration !== undefined) nonnegative(node.duration, `${path}.duration`);\n if (node.children !== undefined) list(node.children, `${path}.children`).forEach((child, i) => readAttemptResult(child, `${path}.children[${i}]`));\n return { ...node, name: str(node.name, `${path}.name`) } as VerifyNode;\n}\n\nfunction readAttempt(value: unknown, index: number): StepAttempt {\n const path = `detail.attempts[${index}]`;\n const a = record(value, path);\n return {\n attempt: num(a.attempt, `${path}.attempt`),\n status: str(a.status, `${path}.status`),\n ...optional(a, \"error\", (v) => str(v, `${path}.error`)),\n ...optional(a, \"durationMs\", (v) => nonnegative(v, `${path}.durationMs`)),\n ...optional(a, \"result\", (v) => readAttemptResult(v, `${path}.result`)),\n };\n}\n\nfunction readAttempts(value: unknown): StepAttempt[] {\n const attempts = list(value, \"detail.attempts\").map(readAttempt);\n attempts.forEach((attempt, index) => {\n if (attempt.attempt !== index + 1) fail(`detail.attempts[${index}].attempt`, `the sequence number ${index + 1}`);\n });\n return attempts;\n}\n\nfunction readExports(value: unknown): StepExport[] {\n return Object.entries(record(value, \"detail.exports\")).map(([name, raw]) => {\n const path = `detail.exports.${name}`;\n const entry = record(raw, path);\n return { name, value: entry.value, step: str(entry.step, `${path}.step`) };\n });\n}\n\nfunction readEvent(value: unknown, index: number): WatcherEvent {\n const path = `detail.events[${index}]`;\n const e = record(value, path);\n return {\n type: oneOf(e.type, WATCHER_EVENT_TYPES, `${path}.type`),\n ...optional(e, \"text\", (v) => str(v, `${path}.text`)),\n ...optional(e, \"url\", (v) => str(v, `${path}.url`)),\n ...optional(e, \"status\", (v) => num(v, `${path}.status`)),\n ...optional(e, \"detail\", (v) => str(v, `${path}.detail`)),\n };\n}\n\nfunction readStep(detail: Rec): StepDetail {\n const ref = record(detail.step, \"detail.step\");\n const rest = Object.fromEntries(Object.entries(detail).filter(([key]) => !STEP_KEYS.has(key)));\n return {\n step: { id: str(ref.id, \"detail.step.id\"), kind: str(ref.kind, \"detail.step.kind\") },\n ...(detail.outputs === undefined ? {} : { outputs: detail.outputs }),\n exports: detail.exports == null ? [] : readExports(detail.exports),\n ...optional(detail, \"wait\", readWait),\n attempts: readAttempts(detail.attempts ?? []),\n events: list(detail.events ?? [], \"detail.events\").map(readEvent),\n background: bool(detail.background ?? false, \"detail.background\"),\n rest,\n };\n}\n\n/**\n * Whether `node.detail` carries a typed step (`detail.step`), and if so its\n * parsed contents. A node without `detail.step` is \"none\" whatever else its\n * detail holds; a `step` whose fields violate the contract is \"invalid\" with\n * the offending path, so the view can say so rather than render a guess.\n */\nexport function readStepDetail(detail: unknown): StepDetailResult {\n if (!isRecord(detail) || detail.step === undefined) return { kind: \"none\" };\n try {\n return { kind: \"step\", step: readStep(detail) };\n } catch (error) {\n if (error instanceof StepDetailError) return { kind: \"invalid\", error: error.message };\n throw error;\n }\n}\n\n/** The step detail when there is one, for matchers that only need to know. */\nexport function hasStepDetail(detail: unknown): boolean {\n return readStepDetail(detail).kind !== \"none\";\n}\n\n/** `09:00:04` from an RFC 3339 timestamp, as written (no timezone conversion); anything else verbatim. */\nexport function clockTime(at: string): string {\n return /T(\\d{2}:\\d{2}:\\d{2})/.exec(at)?.[1] ?? at;\n}\n\nexport function formatDelay(ms: number): string {\n return ms <= 0 ? \"0ms\" : formatTestDuration(ms * 1e6);\n}\n\n/** `every 1s · backoff ×1.5 up to 10s · jitter ±20% · timeout 3m`, skipping what the policy leaves unset. */\nexport function policySummary(policy: WaitPolicy): string {\n const backoff = [\n policy.backoff?.factor !== undefined && `×${policy.backoff.factor}`,\n policy.backoff?.max && `up to ${policy.backoff.max}`,\n ].filter(Boolean);\n return [\n policy.interval && `every ${policy.interval}`,\n backoff.length > 0 && `backoff ${backoff.join(\" \")}`,\n policy.jitter && `jitter ±${policy.jitter}`,\n policy.timeout && `timeout ${policy.timeout}`,\n ]\n .filter(Boolean)\n .join(\" · \");\n}\n\nexport function formatExportValue(value: unknown): string {\n if (value === undefined) return \"\";\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nfunction waitCopy(wait: WaitDetail): BriefSection {\n const { policy } = wait;\n const lines = [\n `outcome: ${wait.outcome}`,\n `elapsed: ${formatDelay(wait.durationMs)}`,\n `policy: ${policySummary(policy)}`,\n policy.until && `until: ${policy.until}`,\n policy.failWhen && `failWhen: ${policy.failWhen}`,\n wait.error && `error: ${wait.error}`,\n wait.trace && `trace: ${wait.trace}`,\n wait.outputs !== undefined && `outputs: ${JSON.stringify(wait.outputs)}`,\n ];\n return { title: \"Wait\", body: lines.filter(Boolean).join(\"\\n\") };\n}\n\nfunction attemptLine(a: StepAttempt): string {\n const head = [`#${a.attempt}`, a.status, a.durationMs !== undefined && formatDelay(a.durationMs)];\n return `${head.filter(Boolean).join(\" \")}${a.error ? ` — ${a.error}` : \"\"}`;\n}\n\nfunction eventLine(e: WatcherEvent): string {\n const body = [e.status, e.text, e.url].filter((part) => part !== undefined).join(\" \");\n return `[${e.type}]${body ? ` ${body}` : \"\"}${e.detail ? ` — ${e.detail}` : \"\"}`;\n}\n\n/** Brief sections for the \"Copy details\" button: wait trace, retry attempts, exports and watcher events. */\nexport function stepKindCopy(step: StepDetail): BriefSection[] {\n return [\n ...(step.outputs !== undefined ? [{ title: \"Outputs\", body: JSON.stringify(step.outputs, null, 2), lang: \"json\" }] : []),\n ...(step.wait ? [waitCopy(step.wait)] : []),\n ...(step.attempts.length > 0 ? [{ title: \"Attempts\", body: step.attempts.map(attemptLine).join(\"\\n\") }] : []),\n ...(step.exports.length > 0\n ? [{ title: \"Exports\", body: step.exports.map((e) => `${e.name}=${formatExportValue(e.value)} (from ${e.step})`).join(\"\\n\") }]\n : []),\n ...(step.events.length > 0 ? [{ title: \"Events\", body: step.events.map(eventLine).join(\"\\n\") }] : []),\n ];\n}\n"],"names":["formatTestDuration"],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { BriefSection } from '../test-runner/index.js';
2
+ import { VerifyNode } from './verify-report.js';
3
+ export type StepRef = {
4
+ id: string;
5
+ kind: string;
6
+ };
7
+ export type WaitPolicy = {
8
+ until?: string;
9
+ failWhen?: string;
10
+ interval?: string;
11
+ backoff?: {
12
+ factor?: number;
13
+ max?: string;
14
+ };
15
+ jitter?: string;
16
+ timeout?: string;
17
+ };
18
+ export declare const WAIT_OUTCOMES: readonly ["satisfied", "failed", "timeout"];
19
+ export type WaitOutcome = (typeof WAIT_OUTCOMES)[number];
20
+ export type WaitDetail = {
21
+ policy: WaitPolicy;
22
+ outcome: WaitOutcome;
23
+ durationMs: number;
24
+ outputs?: unknown;
25
+ error?: string;
26
+ trace?: string;
27
+ };
28
+ export type StepAttempt = {
29
+ attempt: number;
30
+ status: string;
31
+ error?: string;
32
+ durationMs?: number;
33
+ result?: VerifyNode;
34
+ };
35
+ export type StepExport = {
36
+ name: string;
37
+ value: unknown;
38
+ step: string;
39
+ };
40
+ export declare const WATCHER_EVENT_TYPES: readonly ["alert", "console", "pageerror", "response"];
41
+ export type WatcherEventType = (typeof WATCHER_EVENT_TYPES)[number];
42
+ export type WatcherEvent = {
43
+ type: WatcherEventType;
44
+ text?: string;
45
+ url?: string;
46
+ status?: number;
47
+ detail?: string;
48
+ };
49
+ export type StepDetail = {
50
+ step: StepRef;
51
+ outputs?: unknown;
52
+ exports: StepExport[];
53
+ wait?: WaitDetail;
54
+ attempts: StepAttempt[];
55
+ events: WatcherEvent[];
56
+ /** Whether the step runs in the background until teardown (a watcher). */
57
+ background: boolean;
58
+ /** Everything else in `node.detail` (cel_trace, run, recordings, …). */
59
+ rest: Record<string, unknown>;
60
+ };
61
+ export type StepDetailResult = {
62
+ kind: "none";
63
+ } | {
64
+ kind: "step";
65
+ step: StepDetail;
66
+ } | {
67
+ kind: "invalid";
68
+ error: string;
69
+ };
70
+ /**
71
+ * Whether `node.detail` carries a typed step (`detail.step`), and if so its
72
+ * parsed contents. A node without `detail.step` is "none" whatever else its
73
+ * detail holds; a `step` whose fields violate the contract is "invalid" with
74
+ * the offending path, so the view can say so rather than render a guess.
75
+ */
76
+ export declare function readStepDetail(detail: unknown): StepDetailResult;
77
+ /** The step detail when there is one, for matchers that only need to know. */
78
+ export declare function hasStepDetail(detail: unknown): boolean;
79
+ /** `09:00:04` from an RFC 3339 timestamp, as written (no timezone conversion); anything else verbatim. */
80
+ export declare function clockTime(at: string): string;
81
+ export declare function formatDelay(ms: number): string;
82
+ /** `every 1s · backoff ×1.5 up to 10s · jitter ±20% · timeout 3m`, skipping what the policy leaves unset. */
83
+ export declare function policySummary(policy: WaitPolicy): string;
84
+ export declare function formatExportValue(value: unknown): string;
85
+ /** Brief sections for the "Copy details" button: wait trace, retry attempts, exports and watcher events. */
86
+ export declare function stepKindCopy(step: StepDetail): BriefSection[];
87
+ //# sourceMappingURL=stepKind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepKind.d.ts","sourceRoot":"","sources":["../../../src/data/verification/stepKind.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,aAAa,6CAA8C,CAAC;AACzE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7I,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC;AAExH,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,eAAO,MAAM,mBAAmB,wDAAyD,CAAC;AAC1F,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAqKvC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAQhE;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED,0GAA0G;AAC1G,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,6GAA6G;AAC7G,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAaxD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGxD;AA2BD,4GAA4G;AAC5G,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,EAAE,CAU7D"}
@@ -0,0 +1,217 @@
1
+ import { formatTestDuration } from "../test-runner/status.js";
2
+ const WAIT_OUTCOMES = ["satisfied", "failed", "timeout"];
3
+ const WATCHER_EVENT_TYPES = ["alert", "console", "pageerror", "response"];
4
+ const STEP_KEYS = /* @__PURE__ */ new Set(["step", "outputs", "exports", "wait", "attempts", "events", "background"]);
5
+ class StepDetailError extends Error {
6
+ }
7
+ function fail(path, expectation) {
8
+ throw new StepDetailError(`${path} must be ${expectation}`);
9
+ }
10
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
11
+ function record(value, path) {
12
+ return isRecord(value) ? value : fail(path, "an object");
13
+ }
14
+ function list(value, path) {
15
+ return Array.isArray(value) ? value : fail(path, "an array");
16
+ }
17
+ function str(value, path) {
18
+ return typeof value === "string" ? value : fail(path, "a string");
19
+ }
20
+ function num(value, path) {
21
+ return typeof value === "number" && Number.isFinite(value) ? value : fail(path, "a number");
22
+ }
23
+ function bool(value, path) {
24
+ return typeof value === "boolean" ? value : fail(path, "a boolean");
25
+ }
26
+ function oneOf(value, allowed, path) {
27
+ return allowed.includes(value) ? value : fail(path, `one of ${allowed.join(", ")} (got ${JSON.stringify(value)})`);
28
+ }
29
+ function optional(source, key, read) {
30
+ return source[key] === void 0 || source[key] === null ? {} : { [key]: read(source[key]) };
31
+ }
32
+ function durationText(value, path) {
33
+ if (typeof value === "string") return value;
34
+ if (typeof value === "number") return formatTestDuration(value);
35
+ return fail(path, "a duration string or nanosecond number");
36
+ }
37
+ function scalarText(value, path) {
38
+ if (typeof value === "string") return value;
39
+ if (typeof value === "number") return String(value);
40
+ return fail(path, "a string or number");
41
+ }
42
+ function readPolicy(value) {
43
+ const path = "detail.wait.policy";
44
+ const policy = record(value, path);
45
+ const backoff = (raw) => {
46
+ const b = record(raw, `${path}.backoff`);
47
+ return {
48
+ ...optional(b, "factor", (v) => num(v, `${path}.backoff.factor`)),
49
+ ...optional(b, "max", (v) => durationText(v, `${path}.backoff.max`))
50
+ };
51
+ };
52
+ return {
53
+ ...optional(policy, "until", (v) => str(v, `${path}.until`)),
54
+ ...optional(policy, "failWhen", (v) => str(v, `${path}.failWhen`)),
55
+ ...optional(policy, "interval", (v) => durationText(v, `${path}.interval`)),
56
+ ...optional(policy, "backoff", backoff),
57
+ ...optional(policy, "jitter", (v) => scalarText(v, `${path}.jitter`)),
58
+ ...optional(policy, "timeout", (v) => durationText(v, `${path}.timeout`))
59
+ };
60
+ }
61
+ function readWait(value) {
62
+ const wait = record(value, "detail.wait");
63
+ return {
64
+ policy: readPolicy(wait.policy ?? {}),
65
+ outcome: oneOf(wait.outcome, WAIT_OUTCOMES, "detail.wait.outcome"),
66
+ durationMs: nonnegative(wait.durationMs, "detail.wait.durationMs"),
67
+ ...wait.outputs === void 0 ? {} : { outputs: wait.outputs },
68
+ ...optional(wait, "error", (v) => str(v, "detail.wait.error")),
69
+ ...optional(wait, "trace", (v) => str(v, "detail.wait.trace"))
70
+ };
71
+ }
72
+ function nonnegative(value, path) {
73
+ const result = num(value, path);
74
+ return result >= 0 ? result : fail(path, "non-negative");
75
+ }
76
+ function readAttemptResult(value, path) {
77
+ const node = record(value, path);
78
+ str(node.name, `${path}.name`);
79
+ for (const key of ["framework", "message", "command", "work_dir", "stdout", "stderr"]) {
80
+ if (node[key] !== void 0) str(node[key], `${path}.${key}`);
81
+ }
82
+ for (const key of ["passed", "failed", "timed_out", "warned", "skipped", "pending", "running"]) {
83
+ if (node[key] !== void 0) bool(node[key], `${path}.${key}`);
84
+ }
85
+ if (node.duration !== void 0) nonnegative(node.duration, `${path}.duration`);
86
+ if (node.children !== void 0) list(node.children, `${path}.children`).forEach((child, i) => readAttemptResult(child, `${path}.children[${i}]`));
87
+ return { ...node, name: str(node.name, `${path}.name`) };
88
+ }
89
+ function readAttempt(value, index) {
90
+ const path = `detail.attempts[${index}]`;
91
+ const a = record(value, path);
92
+ return {
93
+ attempt: num(a.attempt, `${path}.attempt`),
94
+ status: str(a.status, `${path}.status`),
95
+ ...optional(a, "error", (v) => str(v, `${path}.error`)),
96
+ ...optional(a, "durationMs", (v) => nonnegative(v, `${path}.durationMs`)),
97
+ ...optional(a, "result", (v) => readAttemptResult(v, `${path}.result`))
98
+ };
99
+ }
100
+ function readAttempts(value) {
101
+ const attempts = list(value, "detail.attempts").map(readAttempt);
102
+ attempts.forEach((attempt, index) => {
103
+ if (attempt.attempt !== index + 1) fail(`detail.attempts[${index}].attempt`, `the sequence number ${index + 1}`);
104
+ });
105
+ return attempts;
106
+ }
107
+ function readExports(value) {
108
+ return Object.entries(record(value, "detail.exports")).map(([name, raw]) => {
109
+ const path = `detail.exports.${name}`;
110
+ const entry = record(raw, path);
111
+ return { name, value: entry.value, step: str(entry.step, `${path}.step`) };
112
+ });
113
+ }
114
+ function readEvent(value, index) {
115
+ const path = `detail.events[${index}]`;
116
+ const e = record(value, path);
117
+ return {
118
+ type: oneOf(e.type, WATCHER_EVENT_TYPES, `${path}.type`),
119
+ ...optional(e, "text", (v) => str(v, `${path}.text`)),
120
+ ...optional(e, "url", (v) => str(v, `${path}.url`)),
121
+ ...optional(e, "status", (v) => num(v, `${path}.status`)),
122
+ ...optional(e, "detail", (v) => str(v, `${path}.detail`))
123
+ };
124
+ }
125
+ function readStep(detail) {
126
+ const ref = record(detail.step, "detail.step");
127
+ const rest = Object.fromEntries(Object.entries(detail).filter(([key]) => !STEP_KEYS.has(key)));
128
+ return {
129
+ step: { id: str(ref.id, "detail.step.id"), kind: str(ref.kind, "detail.step.kind") },
130
+ ...detail.outputs === void 0 ? {} : { outputs: detail.outputs },
131
+ exports: detail.exports == null ? [] : readExports(detail.exports),
132
+ ...optional(detail, "wait", readWait),
133
+ attempts: readAttempts(detail.attempts ?? []),
134
+ events: list(detail.events ?? [], "detail.events").map(readEvent),
135
+ background: bool(detail.background ?? false, "detail.background"),
136
+ rest
137
+ };
138
+ }
139
+ function readStepDetail(detail) {
140
+ if (!isRecord(detail) || detail.step === void 0) return { kind: "none" };
141
+ try {
142
+ return { kind: "step", step: readStep(detail) };
143
+ } catch (error) {
144
+ if (error instanceof StepDetailError) return { kind: "invalid", error: error.message };
145
+ throw error;
146
+ }
147
+ }
148
+ function hasStepDetail(detail) {
149
+ return readStepDetail(detail).kind !== "none";
150
+ }
151
+ function clockTime(at) {
152
+ var _a;
153
+ return ((_a = /T(\d{2}:\d{2}:\d{2})/.exec(at)) == null ? void 0 : _a[1]) ?? at;
154
+ }
155
+ function formatDelay(ms) {
156
+ return ms <= 0 ? "0ms" : formatTestDuration(ms * 1e6);
157
+ }
158
+ function policySummary(policy) {
159
+ var _a, _b;
160
+ const backoff = [
161
+ ((_a = policy.backoff) == null ? void 0 : _a.factor) !== void 0 && `×${policy.backoff.factor}`,
162
+ ((_b = policy.backoff) == null ? void 0 : _b.max) && `up to ${policy.backoff.max}`
163
+ ].filter(Boolean);
164
+ return [
165
+ policy.interval && `every ${policy.interval}`,
166
+ backoff.length > 0 && `backoff ${backoff.join(" ")}`,
167
+ policy.jitter && `jitter ±${policy.jitter}`,
168
+ policy.timeout && `timeout ${policy.timeout}`
169
+ ].filter(Boolean).join(" · ");
170
+ }
171
+ function formatExportValue(value) {
172
+ if (value === void 0) return "";
173
+ return typeof value === "string" ? value : JSON.stringify(value);
174
+ }
175
+ function waitCopy(wait) {
176
+ const { policy } = wait;
177
+ const lines = [
178
+ `outcome: ${wait.outcome}`,
179
+ `elapsed: ${formatDelay(wait.durationMs)}`,
180
+ `policy: ${policySummary(policy)}`,
181
+ policy.until && `until: ${policy.until}`,
182
+ policy.failWhen && `failWhen: ${policy.failWhen}`,
183
+ wait.error && `error: ${wait.error}`,
184
+ wait.trace && `trace: ${wait.trace}`,
185
+ wait.outputs !== void 0 && `outputs: ${JSON.stringify(wait.outputs)}`
186
+ ];
187
+ return { title: "Wait", body: lines.filter(Boolean).join("\n") };
188
+ }
189
+ function attemptLine(a) {
190
+ const head = [`#${a.attempt}`, a.status, a.durationMs !== void 0 && formatDelay(a.durationMs)];
191
+ return `${head.filter(Boolean).join(" ")}${a.error ? ` — ${a.error}` : ""}`;
192
+ }
193
+ function eventLine(e) {
194
+ const body = [e.status, e.text, e.url].filter((part) => part !== void 0).join(" ");
195
+ return `[${e.type}]${body ? ` ${body}` : ""}${e.detail ? ` — ${e.detail}` : ""}`;
196
+ }
197
+ function stepKindCopy(step) {
198
+ return [
199
+ ...step.outputs !== void 0 ? [{ title: "Outputs", body: JSON.stringify(step.outputs, null, 2), lang: "json" }] : [],
200
+ ...step.wait ? [waitCopy(step.wait)] : [],
201
+ ...step.attempts.length > 0 ? [{ title: "Attempts", body: step.attempts.map(attemptLine).join("\n") }] : [],
202
+ ...step.exports.length > 0 ? [{ title: "Exports", body: step.exports.map((e) => `${e.name}=${formatExportValue(e.value)} (from ${e.step})`).join("\n") }] : [],
203
+ ...step.events.length > 0 ? [{ title: "Events", body: step.events.map(eventLine).join("\n") }] : []
204
+ ];
205
+ }
206
+ export {
207
+ WAIT_OUTCOMES,
208
+ WATCHER_EVENT_TYPES,
209
+ clockTime,
210
+ formatDelay,
211
+ formatExportValue,
212
+ hasStepDetail,
213
+ policySummary,
214
+ readStepDetail,
215
+ stepKindCopy
216
+ };
217
+ //# sourceMappingURL=stepKind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepKind.js","sources":["../../../src/data/verification/stepKind.ts"],"sourcesContent":["// The typed step-kind detail gavel's fixture verifier attaches to a node\n// (fixtures/verifier/report.go): `detail.step` names the kind and id, beside\n// the structured `wait`, `attempts`, `exports`, `outputs` and (for a\n// background Playwright watcher) `events`. Parsed here, once, so the detail\n// view and the copy brief read the same typed shape. A present-but-malformed\n// field is reported by path instead of being guessed at.\n\nimport type { BriefSection } from \"../test-runner\";\nimport { formatTestDuration } from \"../test-runner\";\nimport type { VerifyNode } from \"./verify-report\";\n\nexport type StepRef = { id: string; kind: string };\n\nexport type WaitPolicy = {\n until?: string;\n failWhen?: string;\n interval?: string;\n backoff?: { factor?: number; max?: string };\n jitter?: string;\n timeout?: string;\n};\n\nexport const WAIT_OUTCOMES = [\"satisfied\", \"failed\", \"timeout\"] as const;\nexport type WaitOutcome = (typeof WAIT_OUTCOMES)[number];\n\nexport type WaitDetail = { policy: WaitPolicy; outcome: WaitOutcome; durationMs: number; outputs?: unknown; error?: string; trace?: string };\n\nexport type StepAttempt = { attempt: number; status: string; error?: string; durationMs?: number; result?: VerifyNode };\n\nexport type StepExport = { name: string; value: unknown; step: string };\n\nexport const WATCHER_EVENT_TYPES = [\"alert\", \"console\", \"pageerror\", \"response\"] as const;\nexport type WatcherEventType = (typeof WATCHER_EVENT_TYPES)[number];\n\nexport type WatcherEvent = {\n type: WatcherEventType;\n text?: string;\n url?: string;\n status?: number;\n detail?: string;\n};\n\nexport type StepDetail = {\n step: StepRef;\n outputs?: unknown;\n exports: StepExport[];\n wait?: WaitDetail;\n attempts: StepAttempt[];\n events: WatcherEvent[];\n /** Whether the step runs in the background until teardown (a watcher). */\n background: boolean;\n /** Everything else in `node.detail` (cel_trace, run, recordings, …). */\n rest: Record<string, unknown>;\n};\n\nexport type StepDetailResult =\n | { kind: \"none\" }\n | { kind: \"step\"; step: StepDetail }\n | { kind: \"invalid\"; error: string };\n\nconst STEP_KEYS = new Set([\"step\", \"outputs\", \"exports\", \"wait\", \"attempts\", \"events\", \"background\"]);\n\nclass StepDetailError extends Error {}\n\nfunction fail(path: string, expectation: string): never {\n throw new StepDetailError(`${path} must be ${expectation}`);\n}\n\ntype Rec = Record<string, unknown>;\n\nconst isRecord = (value: unknown): value is Rec =>\n value !== null && typeof value === \"object\" && !Array.isArray(value);\n\nfunction record(value: unknown, path: string): Rec {\n return isRecord(value) ? value : fail(path, \"an object\");\n}\n\nfunction list(value: unknown, path: string): unknown[] {\n return Array.isArray(value) ? value : fail(path, \"an array\");\n}\n\nfunction str(value: unknown, path: string): string {\n return typeof value === \"string\" ? value : fail(path, \"a string\");\n}\n\nfunction num(value: unknown, path: string): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : fail(path, \"a number\");\n}\n\nfunction bool(value: unknown, path: string): boolean {\n return typeof value === \"boolean\" ? value : fail(path, \"a boolean\");\n}\n\nfunction oneOf<T extends string>(value: unknown, allowed: readonly T[], path: string): T {\n return allowed.includes(value as T)\n ? (value as T)\n : fail(path, `one of ${allowed.join(\", \")} (got ${JSON.stringify(value)})`);\n}\n\n/** `{ [key]: read(value) }` when the optional field is present, else `{}` — absent stays an absent key. */\nfunction optional<K extends string, T>(source: Rec, key: K, read: (value: unknown) => T): { [P in K]?: T } {\n return source[key] === undefined || source[key] === null ? {} : ({ [key]: read(source[key]) } as { [P in K]?: T });\n}\n\n/** Durations arrive as Go-style strings (\"15s\"); a bare number is nanoseconds like every other duration on the wire. */\nfunction durationText(value: unknown, path: string): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return formatTestDuration(value);\n return fail(path, \"a duration string or nanosecond number\");\n}\n\nfunction scalarText(value: unknown, path: string): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return String(value);\n return fail(path, \"a string or number\");\n}\n\nfunction readPolicy(value: unknown): WaitPolicy {\n const path = \"detail.wait.policy\";\n const policy = record(value, path);\n const backoff = (raw: unknown) => {\n const b = record(raw, `${path}.backoff`);\n return {\n ...optional(b, \"factor\", (v) => num(v, `${path}.backoff.factor`)),\n ...optional(b, \"max\", (v) => durationText(v, `${path}.backoff.max`)),\n };\n };\n return {\n ...optional(policy, \"until\", (v) => str(v, `${path}.until`)),\n ...optional(policy, \"failWhen\", (v) => str(v, `${path}.failWhen`)),\n ...optional(policy, \"interval\", (v) => durationText(v, `${path}.interval`)),\n ...optional(policy, \"backoff\", backoff),\n ...optional(policy, \"jitter\", (v) => scalarText(v, `${path}.jitter`)),\n ...optional(policy, \"timeout\", (v) => durationText(v, `${path}.timeout`)),\n };\n}\n\nfunction readWait(value: unknown): WaitDetail {\n const wait = record(value, \"detail.wait\");\n return {\n policy: readPolicy(wait.policy ?? {}),\n outcome: oneOf(wait.outcome, WAIT_OUTCOMES, \"detail.wait.outcome\"),\n durationMs: nonnegative(wait.durationMs, \"detail.wait.durationMs\"),\n ...(wait.outputs === undefined ? {} : { outputs: wait.outputs }),\n ...optional(wait, \"error\", (v) => str(v, \"detail.wait.error\")),\n ...optional(wait, \"trace\", (v) => str(v, \"detail.wait.trace\")),\n };\n}\n\nfunction nonnegative(value: unknown, path: string): number {\n const result = num(value, path);\n return result >= 0 ? result : fail(path, \"non-negative\");\n}\n\nfunction readAttemptResult(value: unknown, path: string): VerifyNode {\n const node = record(value, path);\n str(node.name, `${path}.name`);\n for (const key of [\"framework\", \"message\", \"command\", \"work_dir\", \"stdout\", \"stderr\"]) {\n if (node[key] !== undefined) str(node[key], `${path}.${key}`);\n }\n for (const key of [\"passed\", \"failed\", \"timed_out\", \"warned\", \"skipped\", \"pending\", \"running\"]) {\n if (node[key] !== undefined) bool(node[key], `${path}.${key}`);\n }\n if (node.duration !== undefined) nonnegative(node.duration, `${path}.duration`);\n if (node.children !== undefined) list(node.children, `${path}.children`).forEach((child, i) => readAttemptResult(child, `${path}.children[${i}]`));\n return { ...node, name: str(node.name, `${path}.name`) } as VerifyNode;\n}\n\nfunction readAttempt(value: unknown, index: number): StepAttempt {\n const path = `detail.attempts[${index}]`;\n const a = record(value, path);\n return {\n attempt: num(a.attempt, `${path}.attempt`),\n status: str(a.status, `${path}.status`),\n ...optional(a, \"error\", (v) => str(v, `${path}.error`)),\n ...optional(a, \"durationMs\", (v) => nonnegative(v, `${path}.durationMs`)),\n ...optional(a, \"result\", (v) => readAttemptResult(v, `${path}.result`)),\n };\n}\n\nfunction readAttempts(value: unknown): StepAttempt[] {\n const attempts = list(value, \"detail.attempts\").map(readAttempt);\n attempts.forEach((attempt, index) => {\n if (attempt.attempt !== index + 1) fail(`detail.attempts[${index}].attempt`, `the sequence number ${index + 1}`);\n });\n return attempts;\n}\n\nfunction readExports(value: unknown): StepExport[] {\n return Object.entries(record(value, \"detail.exports\")).map(([name, raw]) => {\n const path = `detail.exports.${name}`;\n const entry = record(raw, path);\n return { name, value: entry.value, step: str(entry.step, `${path}.step`) };\n });\n}\n\nfunction readEvent(value: unknown, index: number): WatcherEvent {\n const path = `detail.events[${index}]`;\n const e = record(value, path);\n return {\n type: oneOf(e.type, WATCHER_EVENT_TYPES, `${path}.type`),\n ...optional(e, \"text\", (v) => str(v, `${path}.text`)),\n ...optional(e, \"url\", (v) => str(v, `${path}.url`)),\n ...optional(e, \"status\", (v) => num(v, `${path}.status`)),\n ...optional(e, \"detail\", (v) => str(v, `${path}.detail`)),\n };\n}\n\nfunction readStep(detail: Rec): StepDetail {\n const ref = record(detail.step, \"detail.step\");\n const rest = Object.fromEntries(Object.entries(detail).filter(([key]) => !STEP_KEYS.has(key)));\n return {\n step: { id: str(ref.id, \"detail.step.id\"), kind: str(ref.kind, \"detail.step.kind\") },\n ...(detail.outputs === undefined ? {} : { outputs: detail.outputs }),\n exports: detail.exports == null ? [] : readExports(detail.exports),\n ...optional(detail, \"wait\", readWait),\n attempts: readAttempts(detail.attempts ?? []),\n events: list(detail.events ?? [], \"detail.events\").map(readEvent),\n background: bool(detail.background ?? false, \"detail.background\"),\n rest,\n };\n}\n\n/**\n * Whether `node.detail` carries a typed step (`detail.step`), and if so its\n * parsed contents. A node without `detail.step` is \"none\" whatever else its\n * detail holds; a `step` whose fields violate the contract is \"invalid\" with\n * the offending path, so the view can say so rather than render a guess.\n */\nexport function readStepDetail(detail: unknown): StepDetailResult {\n if (!isRecord(detail) || detail.step === undefined) return { kind: \"none\" };\n try {\n return { kind: \"step\", step: readStep(detail) };\n } catch (error) {\n if (error instanceof StepDetailError) return { kind: \"invalid\", error: error.message };\n throw error;\n }\n}\n\n/** The step detail when there is one, for matchers that only need to know. */\nexport function hasStepDetail(detail: unknown): boolean {\n return readStepDetail(detail).kind !== \"none\";\n}\n\n/** `09:00:04` from an RFC 3339 timestamp, as written (no timezone conversion); anything else verbatim. */\nexport function clockTime(at: string): string {\n return /T(\\d{2}:\\d{2}:\\d{2})/.exec(at)?.[1] ?? at;\n}\n\nexport function formatDelay(ms: number): string {\n return ms <= 0 ? \"0ms\" : formatTestDuration(ms * 1e6);\n}\n\n/** `every 1s · backoff ×1.5 up to 10s · jitter ±20% · timeout 3m`, skipping what the policy leaves unset. */\nexport function policySummary(policy: WaitPolicy): string {\n const backoff = [\n policy.backoff?.factor !== undefined && `×${policy.backoff.factor}`,\n policy.backoff?.max && `up to ${policy.backoff.max}`,\n ].filter(Boolean);\n return [\n policy.interval && `every ${policy.interval}`,\n backoff.length > 0 && `backoff ${backoff.join(\" \")}`,\n policy.jitter && `jitter ±${policy.jitter}`,\n policy.timeout && `timeout ${policy.timeout}`,\n ]\n .filter(Boolean)\n .join(\" · \");\n}\n\nexport function formatExportValue(value: unknown): string {\n if (value === undefined) return \"\";\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nfunction waitCopy(wait: WaitDetail): BriefSection {\n const { policy } = wait;\n const lines = [\n `outcome: ${wait.outcome}`,\n `elapsed: ${formatDelay(wait.durationMs)}`,\n `policy: ${policySummary(policy)}`,\n policy.until && `until: ${policy.until}`,\n policy.failWhen && `failWhen: ${policy.failWhen}`,\n wait.error && `error: ${wait.error}`,\n wait.trace && `trace: ${wait.trace}`,\n wait.outputs !== undefined && `outputs: ${JSON.stringify(wait.outputs)}`,\n ];\n return { title: \"Wait\", body: lines.filter(Boolean).join(\"\\n\") };\n}\n\nfunction attemptLine(a: StepAttempt): string {\n const head = [`#${a.attempt}`, a.status, a.durationMs !== undefined && formatDelay(a.durationMs)];\n return `${head.filter(Boolean).join(\" \")}${a.error ? ` — ${a.error}` : \"\"}`;\n}\n\nfunction eventLine(e: WatcherEvent): string {\n const body = [e.status, e.text, e.url].filter((part) => part !== undefined).join(\" \");\n return `[${e.type}]${body ? ` ${body}` : \"\"}${e.detail ? ` — ${e.detail}` : \"\"}`;\n}\n\n/** Brief sections for the \"Copy details\" button: wait trace, retry attempts, exports and watcher events. */\nexport function stepKindCopy(step: StepDetail): BriefSection[] {\n return [\n ...(step.outputs !== undefined ? [{ title: \"Outputs\", body: JSON.stringify(step.outputs, null, 2), lang: \"json\" }] : []),\n ...(step.wait ? [waitCopy(step.wait)] : []),\n ...(step.attempts.length > 0 ? [{ title: \"Attempts\", body: step.attempts.map(attemptLine).join(\"\\n\") }] : []),\n ...(step.exports.length > 0\n ? [{ title: \"Exports\", body: step.exports.map((e) => `${e.name}=${formatExportValue(e.value)} (from ${e.step})`).join(\"\\n\") }]\n : []),\n ...(step.events.length > 0 ? [{ title: \"Events\", body: step.events.map(eventLine).join(\"\\n\") }] : []),\n ];\n}\n"],"names":[],"mappings":";AAsBO,MAAM,gBAAgB,CAAC,aAAa,UAAU,SAAS;AASvD,MAAM,sBAAsB,CAAC,SAAS,WAAW,aAAa,UAAU;AA6B/E,MAAM,YAAY,oBAAI,IAAI,CAAC,QAAQ,WAAW,WAAW,QAAQ,YAAY,UAAU,YAAY,CAAC;AAEpG,MAAM,wBAAwB,MAAM;AAAC;AAErC,SAAS,KAAK,MAAc,aAA4B;AACtD,QAAM,IAAI,gBAAgB,GAAG,IAAI,YAAY,WAAW,EAAE;AAC5D;AAIA,MAAM,WAAW,CAAC,UAChB,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAErE,SAAS,OAAO,OAAgB,MAAmB;AACjD,SAAO,SAAS,KAAK,IAAI,QAAQ,KAAK,MAAM,WAAW;AACzD;AAEA,SAAS,KAAK,OAAgB,MAAyB;AACrD,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,KAAK,MAAM,UAAU;AAC7D;AAEA,SAAS,IAAI,OAAgB,MAAsB;AACjD,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,MAAM,UAAU;AAClE;AAEA,SAAS,IAAI,OAAgB,MAAsB;AACjD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ,KAAK,MAAM,UAAU;AAC5F;AAEA,SAAS,KAAK,OAAgB,MAAuB;AACnD,SAAO,OAAO,UAAU,YAAY,QAAQ,KAAK,MAAM,WAAW;AACpE;AAEA,SAAS,MAAwB,OAAgB,SAAuB,MAAiB;AACvF,SAAO,QAAQ,SAAS,KAAU,IAC7B,QACD,KAAK,MAAM,UAAU,QAAQ,KAAK,IAAI,CAAC,SAAS,KAAK,UAAU,KAAK,CAAC,GAAG;AAC9E;AAGA,SAAS,SAA8B,QAAa,KAAQ,MAA+C;AACzG,SAAO,OAAO,GAAG,MAAM,UAAa,OAAO,GAAG,MAAM,OAAO,CAAA,IAAM,EAAE,CAAC,GAAG,GAAG,KAAK,OAAO,GAAG,CAAC,EAAA;AAC5F;AAGA,SAAS,aAAa,OAAgB,MAAsB;AAC1D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,SAAU,QAAO,mBAAmB,KAAK;AAC9D,SAAO,KAAK,MAAM,wCAAwC;AAC5D;AAEA,SAAS,WAAW,OAAgB,MAAsB;AACxD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,SAAO,KAAK,MAAM,oBAAoB;AACxC;AAEA,SAAS,WAAW,OAA4B;AAC9C,QAAM,OAAO;AACb,QAAM,SAAS,OAAO,OAAO,IAAI;AACjC,QAAM,UAAU,CAAC,QAAiB;AAChC,UAAM,IAAI,OAAO,KAAK,GAAG,IAAI,UAAU;AACvC,WAAO;AAAA,MACL,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,iBAAiB,CAAC;AAAA,MAChE,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,aAAa,GAAG,GAAG,IAAI,cAAc,CAAC;AAAA,IAAA;AAAA,EAEvE;AACA,SAAO;AAAA,IACL,GAAG,SAAS,QAAQ,SAAS,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,QAAQ,CAAC;AAAA,IAC3D,GAAG,SAAS,QAAQ,YAAY,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,WAAW,CAAC;AAAA,IACjE,GAAG,SAAS,QAAQ,YAAY,CAAC,MAAM,aAAa,GAAG,GAAG,IAAI,WAAW,CAAC;AAAA,IAC1E,GAAG,SAAS,QAAQ,WAAW,OAAO;AAAA,IACtC,GAAG,SAAS,QAAQ,UAAU,CAAC,MAAM,WAAW,GAAG,GAAG,IAAI,SAAS,CAAC;AAAA,IACpE,GAAG,SAAS,QAAQ,WAAW,CAAC,MAAM,aAAa,GAAG,GAAG,IAAI,UAAU,CAAC;AAAA,EAAA;AAE5E;AAEA,SAAS,SAAS,OAA4B;AAC5C,QAAM,OAAO,OAAO,OAAO,aAAa;AACxC,SAAO;AAAA,IACL,QAAQ,WAAW,KAAK,UAAU,CAAA,CAAE;AAAA,IACpC,SAAS,MAAM,KAAK,SAAS,eAAe,qBAAqB;AAAA,IACjE,YAAY,YAAY,KAAK,YAAY,wBAAwB;AAAA,IACjE,GAAI,KAAK,YAAY,SAAY,CAAA,IAAK,EAAE,SAAS,KAAK,QAAA;AAAA,IACtD,GAAG,SAAS,MAAM,SAAS,CAAC,MAAM,IAAI,GAAG,mBAAmB,CAAC;AAAA,IAC7D,GAAG,SAAS,MAAM,SAAS,CAAC,MAAM,IAAI,GAAG,mBAAmB,CAAC;AAAA,EAAA;AAEjE;AAEA,SAAS,YAAY,OAAgB,MAAsB;AACzD,QAAM,SAAS,IAAI,OAAO,IAAI;AAC9B,SAAO,UAAU,IAAI,SAAS,KAAK,MAAM,cAAc;AACzD;AAEA,SAAS,kBAAkB,OAAgB,MAA0B;AACnE,QAAM,OAAO,OAAO,OAAO,IAAI;AAC/B,MAAI,KAAK,MAAM,GAAG,IAAI,OAAO;AAC7B,aAAW,OAAO,CAAC,aAAa,WAAW,WAAW,YAAY,UAAU,QAAQ,GAAG;AACrF,QAAI,KAAK,GAAG,MAAM,OAAW,KAAI,KAAK,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,EAC9D;AACA,aAAW,OAAO,CAAC,UAAU,UAAU,aAAa,UAAU,WAAW,WAAW,SAAS,GAAG;AAC9F,QAAI,KAAK,GAAG,MAAM,OAAW,MAAK,KAAK,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,EAC/D;AACA,MAAI,KAAK,aAAa,OAAW,aAAY,KAAK,UAAU,GAAG,IAAI,WAAW;AAC9E,MAAI,KAAK,aAAa,OAAW,MAAK,KAAK,UAAU,GAAG,IAAI,WAAW,EAAE,QAAQ,CAAC,OAAO,MAAM,kBAAkB,OAAO,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC;AACjJ,SAAO,EAAE,GAAG,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG,IAAI,OAAO,EAAA;AACvD;AAEA,SAAS,YAAY,OAAgB,OAA4B;AAC/D,QAAM,OAAO,mBAAmB,KAAK;AACrC,QAAM,IAAI,OAAO,OAAO,IAAI;AAC5B,SAAO;AAAA,IACL,SAAS,IAAI,EAAE,SAAS,GAAG,IAAI,UAAU;AAAA,IACzC,QAAQ,IAAI,EAAE,QAAQ,GAAG,IAAI,SAAS;AAAA,IACtC,GAAG,SAAS,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,QAAQ,CAAC;AAAA,IACtD,GAAG,SAAS,GAAG,cAAc,CAAC,MAAM,YAAY,GAAG,GAAG,IAAI,aAAa,CAAC;AAAA,IACxE,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,kBAAkB,GAAG,GAAG,IAAI,SAAS,CAAC;AAAA,EAAA;AAE1E;AAEA,SAAS,aAAa,OAA+B;AACnD,QAAM,WAAW,KAAK,OAAO,iBAAiB,EAAE,IAAI,WAAW;AAC/D,WAAS,QAAQ,CAAC,SAAS,UAAU;AACnC,QAAI,QAAQ,YAAY,QAAQ,EAAG,MAAK,mBAAmB,KAAK,aAAa,uBAAuB,QAAQ,CAAC,EAAE;AAAA,EACjH,CAAC;AACD,SAAO;AACT;AAEA,SAAS,YAAY,OAA8B;AACjD,SAAO,OAAO,QAAQ,OAAO,OAAO,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AAC1E,UAAM,OAAO,kBAAkB,IAAI;AACnC,UAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,WAAO,EAAE,MAAM,OAAO,MAAM,OAAO,MAAM,IAAI,MAAM,MAAM,GAAG,IAAI,OAAO,EAAA;AAAA,EACzE,CAAC;AACH;AAEA,SAAS,UAAU,OAAgB,OAA6B;AAC9D,QAAM,OAAO,iBAAiB,KAAK;AACnC,QAAM,IAAI,OAAO,OAAO,IAAI;AAC5B,SAAO;AAAA,IACL,MAAM,MAAM,EAAE,MAAM,qBAAqB,GAAG,IAAI,OAAO;AAAA,IACvD,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,OAAO,CAAC;AAAA,IACpD,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,CAAC;AAAA,IAClD,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,SAAS,CAAC;AAAA,IACxD,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,SAAS,CAAC;AAAA,EAAA;AAE5D;AAEA,SAAS,SAAS,QAAyB;AACzC,QAAM,MAAM,OAAO,OAAO,MAAM,aAAa;AAC7C,QAAM,OAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;AAC7F,SAAO;AAAA,IACL,MAAM,EAAE,IAAI,IAAI,IAAI,IAAI,gBAAgB,GAAG,MAAM,IAAI,IAAI,MAAM,kBAAkB,EAAA;AAAA,IACjF,GAAI,OAAO,YAAY,SAAY,CAAA,IAAK,EAAE,SAAS,OAAO,QAAA;AAAA,IAC1D,SAAS,OAAO,WAAW,OAAO,CAAA,IAAK,YAAY,OAAO,OAAO;AAAA,IACjE,GAAG,SAAS,QAAQ,QAAQ,QAAQ;AAAA,IACpC,UAAU,aAAa,OAAO,YAAY,CAAA,CAAE;AAAA,IAC5C,QAAQ,KAAK,OAAO,UAAU,CAAA,GAAI,eAAe,EAAE,IAAI,SAAS;AAAA,IAChE,YAAY,KAAK,OAAO,cAAc,OAAO,mBAAmB;AAAA,IAChE;AAAA,EAAA;AAEJ;AAQO,SAAS,eAAe,QAAmC;AAChE,MAAI,CAAC,SAAS,MAAM,KAAK,OAAO,SAAS,OAAW,QAAO,EAAE,MAAM,OAAA;AACnE,MAAI;AACF,WAAO,EAAE,MAAM,QAAQ,MAAM,SAAS,MAAM,EAAA;AAAA,EAC9C,SAAS,OAAO;AACd,QAAI,iBAAiB,gBAAiB,QAAO,EAAE,MAAM,WAAW,OAAO,MAAM,QAAA;AAC7E,UAAM;AAAA,EACR;AACF;AAGO,SAAS,cAAc,QAA0B;AACtD,SAAO,eAAe,MAAM,EAAE,SAAS;AACzC;AAGO,SAAS,UAAU,IAAoB;;AAC5C,WAAO,4BAAuB,KAAK,EAAE,MAA9B,mBAAkC,OAAM;AACjD;AAEO,SAAS,YAAY,IAAoB;AAC9C,SAAO,MAAM,IAAI,QAAQ,mBAAmB,KAAK,GAAG;AACtD;AAGO,SAAS,cAAc,QAA4B;;AACxD,QAAM,UAAU;AAAA,MACd,YAAO,YAAP,mBAAgB,YAAW,UAAa,IAAI,OAAO,QAAQ,MAAM;AAAA,MACjE,YAAO,YAAP,mBAAgB,QAAO,SAAS,OAAO,QAAQ,GAAG;AAAA,EAAA,EAClD,OAAO,OAAO;AAChB,SAAO;AAAA,IACL,OAAO,YAAY,SAAS,OAAO,QAAQ;AAAA,IAC3C,QAAQ,SAAS,KAAK,WAAW,QAAQ,KAAK,GAAG,CAAC;AAAA,IAClD,OAAO,UAAU,WAAW,OAAO,MAAM;AAAA,IACzC,OAAO,WAAW,WAAW,OAAO,OAAO;AAAA,EAAA,EAE1C,OAAO,OAAO,EACd,KAAK,KAAK;AACf;AAEO,SAAS,kBAAkB,OAAwB;AACxD,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACjE;AAEA,SAAS,SAAS,MAAgC;AAChD,QAAM,EAAE,WAAW;AACnB,QAAM,QAAQ;AAAA,IACZ,YAAY,KAAK,OAAO;AAAA,IACxB,YAAY,YAAY,KAAK,UAAU,CAAC;AAAA,IACxC,WAAW,cAAc,MAAM,CAAC;AAAA,IAChC,OAAO,SAAS,UAAU,OAAO,KAAK;AAAA,IACtC,OAAO,YAAY,aAAa,OAAO,QAAQ;AAAA,IAC/C,KAAK,SAAS,UAAU,KAAK,KAAK;AAAA,IAClC,KAAK,SAAS,UAAU,KAAK,KAAK;AAAA,IAClC,KAAK,YAAY,UAAa,YAAY,KAAK,UAAU,KAAK,OAAO,CAAC;AAAA,EAAA;AAExE,SAAO,EAAE,OAAO,QAAQ,MAAM,MAAM,OAAO,OAAO,EAAE,KAAK,IAAI,EAAA;AAC/D;AAEA,SAAS,YAAY,GAAwB;AAC3C,QAAM,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,QAAQ,EAAE,eAAe,UAAa,YAAY,EAAE,UAAU,CAAC;AAChG,SAAO,GAAG,KAAK,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC,GAAG,EAAE,QAAQ,MAAM,EAAE,KAAK,KAAK,EAAE;AAC3E;AAEA,SAAS,UAAU,GAAyB;AAC1C,QAAM,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,SAAS,MAAS,EAAE,KAAK,GAAG;AACpF,SAAO,IAAI,EAAE,IAAI,IAAI,OAAO,IAAI,IAAI,KAAK,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,MAAM,KAAK,EAAE;AAChF;AAGO,SAAS,aAAa,MAAkC;AAC7D,SAAO;AAAA,IACL,GAAI,KAAK,YAAY,SAAY,CAAC,EAAE,OAAO,WAAW,MAAM,KAAK,UAAU,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,IACrH,GAAI,KAAK,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI,CAAA;AAAA,IACxC,GAAI,KAAK,SAAS,SAAS,IAAI,CAAC,EAAE,OAAO,YAAY,MAAM,KAAK,SAAS,IAAI,WAAW,EAAE,KAAK,IAAI,EAAA,CAAG,IAAI,CAAA;AAAA,IAC1G,GAAI,KAAK,QAAQ,SAAS,IACtB,CAAC,EAAE,OAAO,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,kBAAkB,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,GAAG,EAAE,KAAK,IAAI,EAAA,CAAG,IAC3H,CAAA;AAAA,IACJ,GAAI,KAAK,OAAO,SAAS,IAAI,CAAC,EAAE,OAAO,UAAU,MAAM,KAAK,OAAO,IAAI,SAAS,EAAE,KAAK,IAAI,EAAA,CAAG,IAAI,CAAA;AAAA,EAAC;AAEvG;"}