waygraph 0.15.24 → 0.15.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine/blocks/effect.d.ts +41 -0
- package/dist/engine/blocks/effect.js +23 -0
- package/dist/engine/blocks/method.d.ts +90 -0
- package/dist/engine/blocks/method.js +70 -0
- package/dist/engine/blocks/nav.d.ts +138 -0
- package/dist/engine/blocks/nav.js +110 -0
- package/dist/engine/blocks/page.d.ts +59 -0
- package/dist/engine/blocks/page.js +91 -0
- package/dist/engine/compose.d.ts +75 -0
- package/dist/engine/compose.js +76 -0
- package/dist/engine/config.d.ts +55 -0
- package/dist/engine/config.js +17 -0
- package/dist/engine/core.d.ts +92 -0
- package/dist/engine/core.js +256 -0
- package/dist/engine/engine-class.d.ts +289 -0
- package/dist/engine/engine-class.js +257 -0
- package/dist/engine/flow.d.ts +266 -0
- package/dist/engine/flow.js +387 -0
- package/dist/engine/locate.d.ts +26 -0
- package/dist/engine/locate.js +62 -0
- package/dist/engine/run-graph.d.ts +147 -0
- package/dist/engine/run-graph.js +223 -0
- package/dist/engine.d.ts +11 -1224
- package/dist/engine.js +12 -1550
- package/dist/highlights/css.d.ts +14 -0
- package/dist/highlights/css.js +58 -0
- package/dist/highlights/demo-pace.d.ts +56 -0
- package/dist/highlights/demo-pace.js +184 -0
- package/dist/highlights/device.d.ts +29 -0
- package/dist/highlights/device.js +171 -0
- package/dist/highlights/merge.d.ts +8 -0
- package/dist/highlights/merge.js +173 -0
- package/dist/highlights/run-phase.d.ts +43 -0
- package/dist/highlights/run-phase.js +211 -0
- package/dist/highlights/stub-ctx.d.ts +10 -0
- package/dist/highlights/stub-ctx.js +281 -0
- package/dist/highlights/style.d.ts +27 -0
- package/dist/highlights/style.js +84 -0
- package/dist/highlights/todo-dock.d.ts +52 -0
- package/dist/highlights/todo-dock.js +248 -0
- package/dist/highlights/types.d.ts +536 -0
- package/dist/highlights/types.js +1 -0
- package/dist/highlights.d.ts +9 -734
- package/dist/highlights.js +10 -1416
- package/examples/saucedemo/.waygraph-auto/008f4e6e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/22fefa13.log +0 -0
- package/package.json +1 -1
package/dist/engine.d.ts
CHANGED
|
@@ -1,1224 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* that flow. It does not see Blocks only reachable through `branch()` routing,
|
|
13
|
-
* since those depend on a runtime decision that hasn't happened yet.
|
|
14
|
-
*/
|
|
15
|
-
export declare function preflight(mem: MemPage, block: Block<any, any>): void;
|
|
16
|
-
/**
|
|
17
|
-
* A cross-cutting, automatically-enforced verify - the real engine
|
|
18
|
-
* primitive behind "persistent UI" (a sidebar, a header, anything that's
|
|
19
|
-
* supposed to be present on many/most Checkpoints, not just one page's own
|
|
20
|
-
* Block). Deliberately NOT tied to any folder convention - `appliesTo`
|
|
21
|
-
* matches by Checkpoint tag, explicitly, so this works the same whether a
|
|
22
|
-
* project uses the Waygraph Map folder convention or the older freeform
|
|
23
|
-
* "manual mode" layout real production consumers (pia-waygraph,
|
|
24
|
-
* zsign-atomic-waygraph) already use - registering a Layout with an Engine
|
|
25
|
-
* is the only requirement, folder structure is irrelevant to it.
|
|
26
|
-
*
|
|
27
|
-
* Not a Block: no `act`/`resolve`/Checkpoint of its own, never a graph
|
|
28
|
-
* node - it only ever adds extra `verify` Traits to Checkpoints something
|
|
29
|
-
* else already resolved to, the same way `runVerify` already runs after
|
|
30
|
-
* any Block's own `resolve()` (see `runGraph`'s own verify step, just
|
|
31
|
-
* below) - a Layout is that mechanism made reusable across many
|
|
32
|
-
* Checkpoints instead of hand-repeated per Block.
|
|
33
|
-
*/
|
|
34
|
-
export interface Layout {
|
|
35
|
-
name: string;
|
|
36
|
-
description?: string;
|
|
37
|
-
appliesTo: (tag: string) => boolean;
|
|
38
|
-
/** Function form gets the full resolved Checkpoint, same shape `runVerify`/a Block's own `verify` already use - not just the tag. */
|
|
39
|
-
verify: Trait[] | ((out: Checkpoint<string>) => Trait[]);
|
|
40
|
-
}
|
|
41
|
-
export interface LayoutOptions {
|
|
42
|
-
name: string;
|
|
43
|
-
description?: string;
|
|
44
|
-
/** A fixed tag list, or a predicate for open-ended matching (e.g. a naming pattern). */
|
|
45
|
-
appliesTo: readonly string[] | ((tag: string) => boolean);
|
|
46
|
-
verify: Trait[] | ((out: Checkpoint<string>) => Trait[]);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* @example
|
|
50
|
-
* const AppShellLayout = defineLayout({
|
|
51
|
-
* name: "app-shell",
|
|
52
|
-
* appliesTo: ["AppHome", "Chats", "Notifications", "Settings"],
|
|
53
|
-
* verify: [Trait.visible(SidebarSel.root)],
|
|
54
|
-
* });
|
|
55
|
-
* const engine = new Engine({ layouts: [AppShellLayout] });
|
|
56
|
-
* // Now every Block resolving to one of those four Checkpoints, in any
|
|
57
|
-
* // Flow this engine defines, also gets AppShellLayout's own verify run
|
|
58
|
-
* // automatically - a page that silently drops the sidebar fails loud,
|
|
59
|
-
* // even though no individual Block's own `verify` mentions it.
|
|
60
|
-
*/
|
|
61
|
-
export declare function defineLayout(options: LayoutOptions): Layout;
|
|
62
|
-
/**
|
|
63
|
-
* Runs `entry` against a fresh tab and returns the resulting terminal Checkpoint.
|
|
64
|
-
* The engine owns the tab's lifecycle, not any individual Block: the tab is
|
|
65
|
-
* created before the first `act` runs and closed in `finally`, so it closes even
|
|
66
|
-
* if a step throws.
|
|
67
|
-
*
|
|
68
|
-
* After each Block resolves, its `next` (if any, from `branch()`) is followed to
|
|
69
|
-
* the following Block, in the same tab - a Block with no `next` runs exactly once,
|
|
70
|
-
* unchanged from before `branch()` existed. `next` returning the same Block is a
|
|
71
|
-
* self-loop; `maxSteps` bounds the loop so a routing bug fails loud instead of
|
|
72
|
-
* hanging.
|
|
73
|
-
*
|
|
74
|
-
* `terminals`, if given, is a sanity check: the Checkpoint the run stops on must be
|
|
75
|
-
* one of the tags the caller actually expects, or the run fails loud instead of
|
|
76
|
-
* silently returning an unexpected result. Omit it when there is only ever one
|
|
77
|
-
* reachable outcome by construction (as with a `defineFlow`-built Flow, which has
|
|
78
|
-
* no routing at all) - there is nothing to validate against.
|
|
79
|
-
*/
|
|
80
|
-
export declare function runGraph<TOut extends Checkpoint<string>>(entry: Block<Checkpoint<"__start__">, TOut>, terminals: ReadonlySet<string> | undefined, context: BrowserContext, mem: MemPage, maxSteps?: number, options?: RunGraphOptions): Promise<TOut>;
|
|
81
|
-
/** Options for `runGraph`'s trailing `options` arg and for {@link Flow.run}'s `options` overload. */
|
|
82
|
-
export interface RunGraphOptions {
|
|
83
|
-
/**
|
|
84
|
-
* Drive this already-open page instead of opening a new one via
|
|
85
|
-
* `context.newPage()`. Lets a run continue on a tab the caller already
|
|
86
|
-
* has open (e.g. one that's already logged in), instead of every run
|
|
87
|
-
* being forced to start its own fresh tab and lose access to whatever was
|
|
88
|
-
* already there.
|
|
89
|
-
*/
|
|
90
|
-
page?: Page;
|
|
91
|
-
/**
|
|
92
|
-
* `Flow.run` defaults this to `true` only when it opened the page itself
|
|
93
|
-
* (no `page` given) - matching every call from before this option
|
|
94
|
-
* existed. If you pass your own `page`, it defaults to `false` instead:
|
|
95
|
-
* a page you opened is yours to close, not this run's to close out from
|
|
96
|
-
* under you. Either way an explicit value here always wins. `runGraph`
|
|
97
|
-
* itself has no such page-aware default (its caller already decided
|
|
98
|
-
* `page` and `closeOnFinish` together) - it just does what you ask.
|
|
99
|
-
*/
|
|
100
|
-
closeOnFinish?: boolean;
|
|
101
|
-
/**
|
|
102
|
-
* Layouts (see {@link defineLayout}) whose `verify` runs automatically
|
|
103
|
-
* after any Block in this run resolves to a Checkpoint they apply to -
|
|
104
|
-
* `Flow.run` threads this in from `EngineConfig.layouts` by default; pass
|
|
105
|
-
* it directly here to call `runGraph` standalone (outside a `Flow`) with
|
|
106
|
-
* layouts still enforced.
|
|
107
|
-
*/
|
|
108
|
-
layouts?: readonly Layout[];
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Drives a genuinely separate second tab through its own Block/Flow, in the
|
|
112
|
-
* same browser context an existing `page` already belongs to - the primitive
|
|
113
|
-
* `observe()` is specifically allowed to reach for (see {@link Instruction.observe}),
|
|
114
|
-
* since `act`/`resolve` can't touch `page.context()` at all. A thin, named
|
|
115
|
-
* wrapper around `runGraph` (which already opens its own page from whatever
|
|
116
|
-
* context it's given) rather than a new mechanism - the point is making the
|
|
117
|
-
* pattern discoverable and giving it a real name, not inventing new tab-lifecycle
|
|
118
|
-
* logic. The spawned tab is closed (by `runGraph`'s own `finally`) before this
|
|
119
|
-
* resolves; the original `page` is never touched.
|
|
120
|
-
* @example
|
|
121
|
-
* async observe(page, mem) {
|
|
122
|
-
* const receipt = await spawnTab(EmailReceiptFlow, page, mem);
|
|
123
|
-
* mem.set(ReceiptCode, receipt.__state);
|
|
124
|
-
* }
|
|
125
|
-
*/
|
|
126
|
-
export declare function spawnTab<TOut extends Checkpoint<string>>(entry: Block<Checkpoint<"__start__">, TOut>, page: Page, mem: MemPage, maxSteps?: number): Promise<TOut>;
|
|
127
|
-
/**
|
|
128
|
-
* Wraps one `act()` interaction with a caption and highlight, for a Block
|
|
129
|
-
* author who wants to explicitly narrate a specific step rather than rely
|
|
130
|
-
* on the generic per-fill/per-click narration `waygraph chain
|
|
131
|
-
* WAYGRAPH_STEP=1` already does automatically -
|
|
132
|
-
* `await narrate(submitButton, "confirms the order", () => submitButton.click())`
|
|
133
|
-
* reads at the call site instead of being inferred.
|
|
134
|
-
*
|
|
135
|
-
* A true no-op everywhere except inside a `WAYGRAPH_STEP=1` run: it checks
|
|
136
|
-
* for a `window.__wgPositionRing` hook the step-mode overlay installs on
|
|
137
|
-
* the page before doing anything, so a headless/CI/automated run (nobody
|
|
138
|
-
* watching, per-character delays and highlight pauses would just be wasted
|
|
139
|
-
* time) pays zero extra cost - not even the boundingBox() lookup runs. The
|
|
140
|
-
* `action` itself always runs regardless; only the narration is
|
|
141
|
-
* conditional.
|
|
142
|
-
* @example await narrate(submitButton, "confirms the order", () => submitButton.click())
|
|
143
|
-
*/
|
|
144
|
-
export declare function narrate<T>(locator: Locator, caption: string, action: () => Promise<T>): Promise<T>;
|
|
145
|
-
/** Reserved markers bookending a `defineFlow([start, ...blocks, end])` call. */
|
|
146
|
-
export declare const start: unique symbol;
|
|
147
|
-
export declare const end: unique symbol;
|
|
148
|
-
type StartMarker = typeof start;
|
|
149
|
-
type EndMarker = typeof end;
|
|
150
|
-
/**
|
|
151
|
-
* A composed, runnable flow. Always begins from Checkpoint<"__start__">, same as
|
|
152
|
-
* runGraph's `entry`. `run(context, mem)` uses a context you already have (the
|
|
153
|
-
* usual case inside a `@playwright/test` file, via its `context` fixture) -
|
|
154
|
-
* there's no browser for this Flow to launch, so no config to pass. `run(mem,
|
|
155
|
-
* config?)` - no context - has the Engine launch and own its own browser for
|
|
156
|
-
* this one run instead, and closes it in `finally`; use this outside a
|
|
157
|
-
* Playwright test file, or when a flow genuinely needs its own browser instance
|
|
158
|
-
* rather than sharing the test's. `config` here overrides, per key, whatever
|
|
159
|
-
* `new Engine(...)` was constructed with - so one flow (module-level, imported
|
|
160
|
-
* by many specs) can still have every run choose its own `headless`/`slowMo`
|
|
161
|
-
* rather than being stuck with whatever the flow's own file happened to set.
|
|
162
|
-
*
|
|
163
|
-
* `withBlockVerify`/`modBlockVerify` do what {@link withVerify}/{@link modVerify}
|
|
164
|
-
* do for a single Block, one level up - a spec that only imports the finished
|
|
165
|
-
* Flow (not necessarily the individual Blocks it was built from) can still
|
|
166
|
-
* patch one Block's verify for just that call, without editing the flow's own
|
|
167
|
-
* file or hand-rebuilding its Block list. Addressed the same three ways
|
|
168
|
-
* `modVerify` already addresses a Trait - the Block reference itself
|
|
169
|
-
* (`LoginBlock`, imported like any other Block; typo-proof, refactor-safe,
|
|
170
|
-
* jump-to-definition works), a plain string name, or a numeric index into this
|
|
171
|
-
* Flow's Block list (position between `start`/`end`, 0-based) for a spec that
|
|
172
|
-
* genuinely doesn't have the Block imported and doesn't want to spell its
|
|
173
|
-
* name. A reference or string resolves by `.name` under the hood (a Block's
|
|
174
|
-
* own stable identity in this codebase, same as every error message elsewhere
|
|
175
|
-
* in this file already uses) rather than object identity - it stays
|
|
176
|
-
* resolvable even after an earlier patch already swapped that slot for a new
|
|
177
|
-
* object, since the name survives every `withVerify`/`modVerify` in the
|
|
178
|
-
* chain; an index is checked fresh against this Flow's current Block list
|
|
179
|
-
* each call, so it's still correct after a patch too. Returns a new Flow -
|
|
180
|
-
* the original is untouched, same as every other decorator in this module.
|
|
181
|
-
*/
|
|
182
|
-
/**
|
|
183
|
-
* One Block's identity as exposed by graph introspection - {@link Flow.blocks},
|
|
184
|
-
* {@link ComposedBlock.steps} - without needing to execute anything. Does not
|
|
185
|
-
* include the Block's literal Checkpoint `In`/`Out` tags: those are TypeScript
|
|
186
|
-
* literal types, erased at runtime, and can only be recovered by a build-time
|
|
187
|
-
* static-analysis tool reading the source's own type annotations - see the
|
|
188
|
-
* `graph-visualization` openspec change for that piece.
|
|
189
|
-
*/
|
|
190
|
-
export interface BlockInfo {
|
|
191
|
-
name: string;
|
|
192
|
-
/** `branch()`'s routing table, if this Block has one - see {@link Block.routes}. */
|
|
193
|
-
routes?: Readonly<Record<string, string | null>>;
|
|
194
|
-
/**
|
|
195
|
-
* True when {@link chainFlow} inserted a session-reset boundary
|
|
196
|
-
* immediately before this Block - i.e. this is the first Block of a
|
|
197
|
-
* sub-flow that was wrapped in {@link withSessionReset}, and it isn't
|
|
198
|
-
* the very first sub-flow in the chain. Absent (not just false) from
|
|
199
|
-
* `Flow.blocks()` on an ordinary, non-chained Flow.
|
|
200
|
-
*/
|
|
201
|
-
resetSessionBefore?: boolean;
|
|
202
|
-
/**
|
|
203
|
-
* The actual Block, re-runnable on its own via
|
|
204
|
-
* `engine.defineFlow([start, info.block, end])` - e.g. step-through
|
|
205
|
-
* tooling that runs a Flow's Blocks one at a time. Introspection that only
|
|
206
|
-
* wants to read the shape (a visualizer) can ignore this and use `name`/
|
|
207
|
-
* `routes` alone.
|
|
208
|
-
*/
|
|
209
|
-
block: Block<any, any>;
|
|
210
|
-
}
|
|
211
|
-
export interface Flow<Out extends Checkpoint<string>> {
|
|
212
|
-
/**
|
|
213
|
-
* True once this Flow has been wrapped in {@link withSessionReset} - a
|
|
214
|
-
* hint for `chainFlow`, not something `run()` itself checks: it marks
|
|
215
|
-
* this Flow as one that expects to start from a genuinely fresh,
|
|
216
|
-
* unauthenticated browser state (e.g. a login flow meant to be
|
|
217
|
-
* re-entered later in a longer chain). `chainFlow` clears cookies and
|
|
218
|
-
* storage right before this Flow's first Block runs, but only when this
|
|
219
|
-
* Flow isn't the very first thing in the chain (nothing to reset yet).
|
|
220
|
-
*/
|
|
221
|
-
readonly resetSession: boolean;
|
|
222
|
-
/**
|
|
223
|
-
* Set once this Flow has been wrapped in {@link withTitle} - a display
|
|
224
|
-
* hint for a step-through overlay/showcase (e.g. "Ticket #123"), not
|
|
225
|
-
* something `run()` itself uses.
|
|
226
|
-
*/
|
|
227
|
-
readonly title?: string;
|
|
228
|
-
/**
|
|
229
|
-
* Set once this Flow has been wrapped in {@link withExpectedFailure} - a
|
|
230
|
-
* display hint for a step-through overlay: this Flow is DESIGNED to throw
|
|
231
|
-
* (e.g. a blocked user's login attempt genuinely failing), not a bug in
|
|
232
|
-
* the demo itself. `run()` never reads this - the Flow still throws
|
|
233
|
-
* exactly as it would otherwise; only the overlay's error panel reads it,
|
|
234
|
-
* to show an informational "this is the point" panel instead of an
|
|
235
|
-
* alarming one indistinguishable from a real break.
|
|
236
|
-
*/
|
|
237
|
-
readonly expectedFailureReason?: string;
|
|
238
|
-
/**
|
|
239
|
-
* Set once this Flow has been wrapped in {@link withHighlightFixtures} -
|
|
240
|
-
* demo narration overrides (unlimited purposes on `.flow.ts`) keyed by
|
|
241
|
-
* block.name. `run()` never reads this; step/`demo` merges onto block stubs.
|
|
242
|
-
*/
|
|
243
|
-
readonly highlightFixtures?: import("./highlights.js").HighlightFixtureMap;
|
|
244
|
-
/**
|
|
245
|
-
* Demo pacing for this Flow's episode (`withDemoPace`).
|
|
246
|
-
* `run()` ignores; step/demo applies per Block in the episode.
|
|
247
|
-
*/
|
|
248
|
-
readonly demoPace?: import("./highlights.js").DemoPace;
|
|
249
|
-
/**
|
|
250
|
-
* Default highlight size/weight/tone for this Flow's episode (`withHighlightStyle`).
|
|
251
|
-
* Per-slot stub/fixture values win. `run()` ignores.
|
|
252
|
-
*/
|
|
253
|
-
readonly highlightStyle?: import("./highlights.js").HighlightStyleDefaults;
|
|
254
|
-
/**
|
|
255
|
-
* Set once this Flow has been wrapped in {@link withMemStub} - opts into
|
|
256
|
-
* auto-filling `requires` keys with registered fake values
|
|
257
|
-
* (`registerMemStub`, `src/mem-stub.ts`) instead of failing preflight when
|
|
258
|
-
* the caller didn't supply them. `run()` never reads this - the CLI's own
|
|
259
|
-
* `--data`/`--mem-stub` seeding, or a bare-library caller's own explicit
|
|
260
|
-
* `seedMemStub(mem, flow)` call, is what actually fills mem before `run()`.
|
|
261
|
-
*/
|
|
262
|
-
readonly memStub?: boolean;
|
|
263
|
-
/**
|
|
264
|
-
* This Flow's constituent Blocks, in order between `start`/`end`, as plain
|
|
265
|
-
* data - for introspection/visualization tools, without running anything.
|
|
266
|
-
* @example loginFlow.blocks() // [{ name: "login" }, { name: "add-to-cart", routes: {...} }]
|
|
267
|
-
*/
|
|
268
|
-
blocks(): readonly BlockInfo[];
|
|
269
|
-
run(context: BrowserContext, mem: MemPage): Promise<Out>;
|
|
270
|
-
/**
|
|
271
|
-
* `options.closeOnFinish: false` hands the driven page back instead of
|
|
272
|
-
* closing it - use this overload (a literal `false`, not a `boolean`) to
|
|
273
|
-
* get the `{ result, page }` shape typed correctly.
|
|
274
|
-
* @example const { result, page } = await loginFlow.run(context, mem, { closeOnFinish: false });
|
|
275
|
-
*/
|
|
276
|
-
run(context: BrowserContext, mem: MemPage, options: RunGraphOptions & {
|
|
277
|
-
closeOnFinish: false;
|
|
278
|
-
}): Promise<{
|
|
279
|
-
result: Out;
|
|
280
|
-
page: Page;
|
|
281
|
-
}>;
|
|
282
|
-
/**
|
|
283
|
-
* `options.page` drives that already-open page instead of opening a new
|
|
284
|
-
* one - see {@link RunGraphOptions}.
|
|
285
|
-
* @example await loginFlow.run(context, mem, { page: existingPage });
|
|
286
|
-
*/
|
|
287
|
-
run(context: BrowserContext, mem: MemPage, options?: RunGraphOptions): Promise<Out>;
|
|
288
|
-
run(mem: MemPage, config?: EngineConfig): Promise<Out>;
|
|
289
|
-
/**
|
|
290
|
-
* Replaces the given Block's whole verify list, wherever it sits in this
|
|
291
|
-
* Flow - same rules as {@link withVerify}. Throws if no Block in this Flow
|
|
292
|
-
* matches.
|
|
293
|
-
* @example checkoutFlow.withBlockVerify(LoginBlock, [])
|
|
294
|
-
* @example checkoutFlow.withBlockVerify("login", [])
|
|
295
|
-
* @example checkoutFlow.withBlockVerify(0, [])
|
|
296
|
-
*/
|
|
297
|
-
withBlockVerify(block: Block<any, any> | string | number, verify: Trait[] | ((out: any) => Trait[])): Flow<Out>;
|
|
298
|
-
/**
|
|
299
|
-
* Replaces one Trait inside the given Block's verify list - same rules as
|
|
300
|
-
* {@link modVerify}. Throws if no Block in this Flow matches, or if that
|
|
301
|
-
* Block has no verify trait at the given name/index.
|
|
302
|
-
* @example checkoutFlow.modBlockVerify(LoginBlock, "url-matches", Trait.url({ pathname: "/inventory.html" }))
|
|
303
|
-
*/
|
|
304
|
-
modBlockVerify(block: Block<any, any> | string | number, nameOrIndex: string | number, newCheck: Trait["check"] | Trait): Flow<Out>;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Marks a Flow as expecting to start from a genuinely fresh, unauthenticated
|
|
308
|
-
* browser state - e.g. a login flow meant to be re-entered later in a longer
|
|
309
|
-
* showcase. Non-destructive, same pattern as {@link withVerify}: returns a
|
|
310
|
-
* new Flow: the original is untouched, and the flag survives any further
|
|
311
|
-
* `withBlockVerify`/`modBlockVerify` patch applied to the result.
|
|
312
|
-
*
|
|
313
|
-
* By itself this does nothing - `Flow.run()` never reads `resetSession`.
|
|
314
|
-
* It's a hint {@link chainFlow} looks for: right before this Flow's first
|
|
315
|
-
* Block runs (skipped if it's the very first thing in the chain - nothing
|
|
316
|
-
* to reset yet), chainFlow clears cookies and storage so this Flow starts
|
|
317
|
-
* exactly as if a human had opened the app fresh, not wherever the
|
|
318
|
-
* previous Flow in the chain happened to leave the page.
|
|
319
|
-
* @example const loginFlow = withSessionReset(engine.defineFlow([start, LoginBlock, end]));
|
|
320
|
-
*/
|
|
321
|
-
export declare function withSessionReset<Out extends Checkpoint<string>>(flow: Flow<Out>): Flow<Out>;
|
|
322
|
-
/**
|
|
323
|
-
* Names a Flow for display - a step-through overlay/showcase (waygraph's
|
|
324
|
-
* `chain --step`) shows this as the running banner while this Flow's own
|
|
325
|
-
* Blocks are executing, instead of one fixed title for the whole run.
|
|
326
|
-
* Non-destructive, same pattern as {@link withSessionReset}.
|
|
327
|
-
* @example const ticket123 = withTitle(loginFlow, "Ticket #123 - Sales rep signs in");
|
|
328
|
-
*/
|
|
329
|
-
export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out>, title: string): Flow<Out>;
|
|
330
|
-
/**
|
|
331
|
-
* Opts this Flow into memStub: `requires` keys the caller didn't supply get
|
|
332
|
-
* filled from `registerMemStub`'s registry (`src/mem-stub.ts`) instead of
|
|
333
|
-
* failing preflight, for any key that has a registered fake generator - a
|
|
334
|
-
* required key with no registration still fails exactly as before.
|
|
335
|
-
* Non-destructive, same pattern as {@link withTitle}. `run()` never reads
|
|
336
|
-
* this itself - the CLI's `--data`/`--mem-stub` seeding, or a bare-library
|
|
337
|
-
* caller's own explicit `seedMemStub(mem, flow)` call, does the filling.
|
|
338
|
-
* @example const demoLogin = withMemStub(loginFlow);
|
|
339
|
-
*/
|
|
340
|
-
export declare function withMemStub<Out extends Checkpoint<string>>(flow: Flow<Out>): Flow<Out>;
|
|
341
|
-
/**
|
|
342
|
-
* Demo pacing for a whole Flow episode (fast review vs slow gap/wrong walkthrough).
|
|
343
|
-
* Non-destructive. `fastForwardComposeBlock` is always blitz for its own step;
|
|
344
|
-
* use this when an entire episode should be fast or slow.
|
|
345
|
-
* @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
|
|
346
|
-
* @example withDemoPace(happyFlow, 0.5) // 2x faster than normal
|
|
347
|
-
* @example withDemoPace(gapFlow, 2.5) // 2.5x slower
|
|
348
|
-
* @example withDemoPace(gapFlow, 4500) // absolute ~4.5s gates/dwells
|
|
349
|
-
*/
|
|
350
|
-
export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: DemoPace): Flow<Out>;
|
|
351
|
-
/**
|
|
352
|
-
* Default highlight look for a Flow episode (size / weight / optional tone).
|
|
353
|
-
* Per-slot stub or {@link withHighlightFixtures} values win when set.
|
|
354
|
-
* @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
|
|
355
|
-
*/
|
|
356
|
-
export declare function withHighlightStyle<Out extends Checkpoint<string>>(flow: Flow<Out>, style: HighlightStyleDefaults): Flow<Out>;
|
|
357
|
-
/**
|
|
358
|
-
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
359
|
-
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
360
|
-
*/
|
|
361
|
-
export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace: DemoPace): Block<In, Out>;
|
|
362
|
-
/**
|
|
363
|
-
* Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
|
|
364
|
-
* login attempt genuinely failing, demonstrating the app's own real
|
|
365
|
-
* behavior rather than a bug in the demo. Non-destructive, same pattern as
|
|
366
|
-
* {@link withTitle}.
|
|
367
|
-
*
|
|
368
|
-
* By itself this changes nothing about how the Flow runs - it still throws
|
|
369
|
-
* Marks a Flow whose last step is an intentional product failure (demo overlay).
|
|
370
|
-
* Step mode shows stubOnError rings + an amber "expected outcome" panel when:
|
|
371
|
-
* - the last block **throws**, or
|
|
372
|
-
* - the last block **succeeds** on the fail branch (e.g. LoginPage + error banner
|
|
373
|
-
* after submit-login branched instead of throwing).
|
|
374
|
-
* Headless `run()` is unchanged - branching success returns the checkpoint.
|
|
375
|
-
* @example const viewerBlockedFlow = withExpectedFailure(
|
|
376
|
-
* engine.defineFlow([start, NavLoginBlock, SubmitLoginActionBlock, end]),
|
|
377
|
-
* "locked_out_user stays on LoginPage with the error banner - working as intended.",
|
|
378
|
-
* );
|
|
379
|
-
*/
|
|
380
|
-
export declare function withExpectedFailure<Out extends Checkpoint<string>>(flow: Flow<Out>, reason: string): Flow<Out>;
|
|
381
|
-
/**
|
|
382
|
-
* Attaches demo highlight fixtures to a Flow - unlimited purposes on `.flow.ts`
|
|
383
|
-
* (AC copy, BUG/GATE tags, detail) merged onto each block's stubBefore/stubAfter/
|
|
384
|
-
* stubOnError slots. Non-destructive, same pattern as {@link withTitle}.
|
|
385
|
-
* Demo/`chain --step` reads `flow.highlightFixtures`; `run()` ignores it.
|
|
386
|
-
* @example withHighlightFixtures(issueFlow, { "submit-login": { stubBefore: { email: { label: "AC-1" } } } })
|
|
387
|
-
*/
|
|
388
|
-
export declare function withHighlightFixtures<Out extends Checkpoint<string>>(flow: Flow<Out>, fixtures: import("./highlights.js").HighlightFixtureMap): Flow<Out>;
|
|
389
|
-
/**
|
|
390
|
-
* Runs several complete, independent Flows one after another, reusing the
|
|
391
|
-
* same page/context/mem in order - each remains its own validated
|
|
392
|
-
* start-to-end unit (a Flow's own `[start, ...blocks, end]` contract is
|
|
393
|
-
* untouched), this only sequences whole Flows. Deliberately NOT the same
|
|
394
|
-
* thing as {@link composeBlock}: composeBlock nests several Blocks into
|
|
395
|
-
* one Block that can drop back into another `defineFlow([...])` - a
|
|
396
|
-
* chainFlow result is a Flow, but not meant to be nested inside another
|
|
397
|
-
* Flow's own Block list. Recursive nesting stays composeBlock's job alone;
|
|
398
|
-
* chainFlow is a flat, one-level sequencing of complete showcases (e.g.
|
|
399
|
-
* "ticket #123 end to end, then ticket #456 end to end").
|
|
400
|
-
*
|
|
401
|
-
* A sub-flow wrapped in {@link withSessionReset} gets its cookies/storage
|
|
402
|
-
* cleared right before it runs (skipped for the very first flow in the
|
|
403
|
-
* chain - nothing to reset yet). The combined result is whatever the LAST
|
|
404
|
-
* flow resolved to.
|
|
405
|
-
* @example chainFlow(ticket123Flow, ticket456Flow).run(context, mem)
|
|
406
|
-
*/
|
|
407
|
-
export declare function chainFlow(...flows: readonly Flow<any>[]): Flow<any>;
|
|
408
|
-
/**
|
|
409
|
-
* A Block guaranteed to have `withStepVerify`/`modStepVerify` attached - what
|
|
410
|
-
* {@link composeBlock} returns. Extends plain `Block`, so it drops straight into
|
|
411
|
-
* `defineFlow([start, ..., composed, ..., end])` like any other Block; no special
|
|
412
|
-
* casing needed anywhere that only expects a `Block`.
|
|
413
|
-
*/
|
|
414
|
-
export interface ComposedBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> extends Block<In, Out> {
|
|
415
|
-
/**
|
|
416
|
-
* This composed Block's constituent steps, in order, as plain data - same
|
|
417
|
-
* shape and purpose as {@link Flow.blocks}.
|
|
418
|
-
* @example GovFormBlock.steps() // [{ name: "step-1-name" }, { name: "step-2-address" }, ...]
|
|
419
|
-
*/
|
|
420
|
-
steps(): readonly BlockInfo[];
|
|
421
|
-
/**
|
|
422
|
-
* Replaces one step's whole verify list, wherever it sits in this composed
|
|
423
|
-
* Block - same rules as {@link withVerify}. Throws if no step matches.
|
|
424
|
-
* @example GovFormBlock.withStepVerify("step-2-address", [])
|
|
425
|
-
*/
|
|
426
|
-
withStepVerify(step: Block<any, any> | string | number, verify: Trait[] | ((out: any) => Trait[])): ComposedBlock<In, Out>;
|
|
427
|
-
/**
|
|
428
|
-
* Replaces one Trait inside one step's verify list - same rules as
|
|
429
|
-
* {@link modVerify}. Throws if no step matches, or that step has no verify
|
|
430
|
-
* trait at the given name/index.
|
|
431
|
-
* @example GovFormBlock.modStepVerify("step-2-address", "zip-visible", Trait.visible("#zip-confirmed"))
|
|
432
|
-
*/
|
|
433
|
-
modStepVerify(step: Block<any, any> | string | number, nameOrIndex: string | number, newCheck: Trait["check"] | Trait): ComposedBlock<In, Out>;
|
|
434
|
-
}
|
|
435
|
-
/**
|
|
436
|
-
* Chains several Blocks into one named, exported unit - what a naturally
|
|
437
|
-
* multi-step feature (a stepper form with several pages, say) wants instead of
|
|
438
|
-
* either one giant Block with no per-step confirmation, or several separately
|
|
439
|
-
* exported Blocks the caller has to wire together by hand every time. Each
|
|
440
|
-
* step keeps its own real `act`/`resolve`/`verify`, chained the same way
|
|
441
|
-
* `connect()` already chains any two Blocks - `composeBlock` is not a new
|
|
442
|
-
* execution mechanism, just `connect()` reduced over the list plus a name and
|
|
443
|
-
* the same step-list closure `Flow` already keeps for its own Block list, so
|
|
444
|
-
* `withStepVerify`/`modStepVerify` can patch one step from outside without the
|
|
445
|
-
* caller needing to hand-rebuild the chain. Resolution is by `.name`, not
|
|
446
|
-
* object identity, so a step reference stays valid even after an earlier patch
|
|
447
|
-
* swapped that slot for a new object - see {@link Flow.withBlockVerify} for
|
|
448
|
-
* the identical guarantee one level up. Each call returns a new composed
|
|
449
|
-
* Block; the original is untouched.
|
|
450
|
-
* @example composeBlock("gov-form", [step1, step2, step3, step4])
|
|
451
|
-
*/
|
|
452
|
-
export declare function composeBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, Out>]): ComposedBlock<In, Out>;
|
|
453
|
-
export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, Out>]): ComposedBlock<In, Out>;
|
|
454
|
-
export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, Out>]): ComposedBlock<In, Out>;
|
|
455
|
-
export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, Out>]): ComposedBlock<In, Out>;
|
|
456
|
-
export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, E>, Block<E, Out>]): ComposedBlock<In, Out>;
|
|
457
|
-
export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, E>, Block<E, F>, Block<F, Out>]): ComposedBlock<In, Out>;
|
|
458
|
-
/**
|
|
459
|
-
* Same shape as {@link composeBlock}, marked {@link FastForwardComposedBlock.fastForward}
|
|
460
|
-
* so demo/run/traverse treat it as **one opaque step** that **blitzes wall-clock**
|
|
461
|
-
* (skip overlay theater + no Playwright slowMo on that step's acts) unless
|
|
462
|
-
* `--ff-expand` / `WAYGRAPH_FF_EXPAND=1`. Inner acts still run for real;
|
|
463
|
-
* failures are prefixed `ff-name > …` so the locus names both the FF unit and
|
|
464
|
-
* the inner step. Prefer this for boring or heavy-check prefixes (auth, seed,
|
|
465
|
-
* dashboard settle) — you may put **several** FF units in one Flow with normal
|
|
466
|
-
* Blocks between them.
|
|
467
|
-
* @example fastForwardComposeBlock("ff-owner-auth", [NavLoginBlock, SubmitLoginForFlow])
|
|
468
|
-
*/
|
|
469
|
-
export interface FastForwardComposedBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> extends ComposedBlock<In, Out> {
|
|
470
|
-
readonly fastForward: true;
|
|
471
|
-
}
|
|
472
|
-
/** True when `block` came from {@link fastForwardComposeBlock}. */
|
|
473
|
-
export declare function isFastForwardBlock(block: Block<any, any>): block is FastForwardComposedBlock<any, any>;
|
|
474
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, Out>]): FastForwardComposedBlock<In, Out>;
|
|
475
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, Out>]): FastForwardComposedBlock<In, Out>;
|
|
476
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, Out>]): FastForwardComposedBlock<In, Out>;
|
|
477
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, Out>]): FastForwardComposedBlock<In, Out>;
|
|
478
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, E>, Block<E, Out>]): FastForwardComposedBlock<In, Out>;
|
|
479
|
-
export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, E>, Block<E, F>, Block<F, Out>]): FastForwardComposedBlock<In, Out>;
|
|
480
|
-
/** Configures how an Engine launches its own browser - only used by `Flow.run(mem)` (no context given); ignored by `Flow.run(context, mem)`, since that context is already launched. */
|
|
481
|
-
export interface EngineConfig {
|
|
482
|
-
/** Default `true`, matching Playwright's own default. */
|
|
483
|
-
headless?: boolean;
|
|
484
|
-
/** Default `"chromium"`. */
|
|
485
|
-
browserName?: "chromium" | "firefox" | "webkit";
|
|
486
|
-
/** Milliseconds Playwright pauses before each operation - for watching a non-headless run with your own eyes, not for real runs. Default `0`. */
|
|
487
|
-
slowMo?: number;
|
|
488
|
-
/**
|
|
489
|
-
* Overrides which `BrowserType` actually launches, per browser name -
|
|
490
|
-
* default is the real `@playwright/test` export for whichever one
|
|
491
|
-
* `browserName` picks. Accepts anything shaped like Playwright's own
|
|
492
|
-
* `chromium`/`firefox`/`webkit` (same `.launch()` signature) - a
|
|
493
|
-
* stealth-patched or otherwise customized launcher (e.g. `playwright-extra`
|
|
494
|
-
* plus a stealth plugin) drops in here unmodified. Puppeteer is a
|
|
495
|
-
* different `Page`/`BrowserContext` shape entirely and isn't supported by
|
|
496
|
-
* this seam.
|
|
497
|
-
* @example new Engine({ browsers: { chromium: stealthChromium } })
|
|
498
|
-
*/
|
|
499
|
-
browsers?: Partial<Record<"chromium" | "firefox" | "webkit", BrowserType>>;
|
|
500
|
-
/**
|
|
501
|
-
* Playwright `recordVideo` - saves a `.webm` when the context closes.
|
|
502
|
-
* Works headless. Lighter than a full clip-engine pipeline (no overlay/ffmpeg).
|
|
503
|
-
* @example new Engine({ recordVideo: { dir: "./videos" } })
|
|
504
|
-
*/
|
|
505
|
-
recordVideo?: {
|
|
506
|
-
dir: string;
|
|
507
|
-
size?: {
|
|
508
|
-
width: number;
|
|
509
|
-
height: number;
|
|
510
|
-
};
|
|
511
|
-
};
|
|
512
|
-
/**
|
|
513
|
-
* Cross-cutting, automatically-enforced verify (see {@link defineLayout})
|
|
514
|
-
* - applies to every Flow this Engine defines. Works the same regardless
|
|
515
|
-
* of folder convention (Waygraph Map or freeform "manual mode") since
|
|
516
|
-
* matching is by Checkpoint tag, never by file path.
|
|
517
|
-
* @example new Engine({ layouts: [AppShellLayout] })
|
|
518
|
-
*/
|
|
519
|
-
layouts?: readonly Layout[];
|
|
520
|
-
}
|
|
521
|
-
type S = Checkpoint<"__start__">;
|
|
522
|
-
/**
|
|
523
|
-
* Holds engine-level configuration shared across every flow defined from it -
|
|
524
|
-
* for now, just how to launch a browser when a Flow owns its own
|
|
525
|
-
* (`headless`/`browserName`/`slowMo`); traits/interstitials/watchers land here
|
|
526
|
-
* in a later change.
|
|
527
|
-
* @example const engine = new Engine({ headless: false, slowMo: 250 });
|
|
528
|
-
*/
|
|
529
|
-
export declare class Engine {
|
|
530
|
-
private readonly config;
|
|
531
|
-
constructor(config?: EngineConfig);
|
|
532
|
-
/**
|
|
533
|
-
* Builds a runnable {@link Flow} from `[start, ...Blocks, end]`, typechecked
|
|
534
|
-
* so each Block's `In` must match the previous Block's `Out` - the same
|
|
535
|
-
* check `connect()` does, just declared as a flat array instead of hand-nested
|
|
536
|
-
* calls. Overloaded for 2-9 array slots (1-8 real Blocks between `start`/`end`)
|
|
537
|
-
* rather than one fully-generic recursive tuple type, so each arity is as
|
|
538
|
-
* reliably checked as `connect<A,B,C>` itself.
|
|
539
|
-
* @example engine.defineFlow([start, LoginBlock, AddToCartBlock, end])
|
|
540
|
-
*/
|
|
541
|
-
defineFlow<B extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, EndMarker]): Flow<B>;
|
|
542
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, Block<B, C>, EndMarker]): Flow<C>;
|
|
543
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, Block<B, C>, Block<C, D>, EndMarker]): Flow<D>;
|
|
544
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, Block<B, C>, Block<C, D>, Block<D, E>, EndMarker]): Flow<E>;
|
|
545
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>>(blocks: readonly [
|
|
546
|
-
StartMarker,
|
|
547
|
-
Block<S, B>,
|
|
548
|
-
Block<B, C>,
|
|
549
|
-
Block<C, D>,
|
|
550
|
-
Block<D, E>,
|
|
551
|
-
Block<E, F>,
|
|
552
|
-
EndMarker
|
|
553
|
-
]): Flow<F>;
|
|
554
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>>(blocks: readonly [
|
|
555
|
-
StartMarker,
|
|
556
|
-
Block<S, B>,
|
|
557
|
-
Block<B, C>,
|
|
558
|
-
Block<C, D>,
|
|
559
|
-
Block<D, E>,
|
|
560
|
-
Block<E, F>,
|
|
561
|
-
Block<F, G>,
|
|
562
|
-
EndMarker
|
|
563
|
-
]): Flow<G>;
|
|
564
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>>(blocks: readonly [
|
|
565
|
-
StartMarker,
|
|
566
|
-
Block<S, B>,
|
|
567
|
-
Block<B, C>,
|
|
568
|
-
Block<C, D>,
|
|
569
|
-
Block<D, E>,
|
|
570
|
-
Block<E, F>,
|
|
571
|
-
Block<F, G>,
|
|
572
|
-
Block<G, H>,
|
|
573
|
-
EndMarker
|
|
574
|
-
]): Flow<H>;
|
|
575
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>>(blocks: readonly [
|
|
576
|
-
StartMarker,
|
|
577
|
-
Block<S, B>,
|
|
578
|
-
Block<B, C>,
|
|
579
|
-
Block<C, D>,
|
|
580
|
-
Block<D, E>,
|
|
581
|
-
Block<E, F>,
|
|
582
|
-
Block<F, G>,
|
|
583
|
-
Block<G, H>,
|
|
584
|
-
Block<H, I>,
|
|
585
|
-
EndMarker
|
|
586
|
-
]): Flow<I>;
|
|
587
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>>(blocks: readonly [
|
|
588
|
-
StartMarker,
|
|
589
|
-
Block<S, B>,
|
|
590
|
-
Block<B, C>,
|
|
591
|
-
Block<C, D>,
|
|
592
|
-
Block<D, E>,
|
|
593
|
-
Block<E, F>,
|
|
594
|
-
Block<F, G>,
|
|
595
|
-
Block<G, H>,
|
|
596
|
-
Block<H, I>,
|
|
597
|
-
Block<I, J>,
|
|
598
|
-
EndMarker
|
|
599
|
-
]): Flow<J>;
|
|
600
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>>(blocks: readonly [
|
|
601
|
-
StartMarker,
|
|
602
|
-
Block<S, B>,
|
|
603
|
-
Block<B, C>,
|
|
604
|
-
Block<C, D>,
|
|
605
|
-
Block<D, E>,
|
|
606
|
-
Block<E, F>,
|
|
607
|
-
Block<F, G>,
|
|
608
|
-
Block<G, H>,
|
|
609
|
-
Block<H, I>,
|
|
610
|
-
Block<I, J>,
|
|
611
|
-
Block<J, K>,
|
|
612
|
-
EndMarker
|
|
613
|
-
]): Flow<K>;
|
|
614
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>>(blocks: readonly [
|
|
615
|
-
StartMarker,
|
|
616
|
-
Block<S, B>,
|
|
617
|
-
Block<B, C>,
|
|
618
|
-
Block<C, D>,
|
|
619
|
-
Block<D, E>,
|
|
620
|
-
Block<E, F>,
|
|
621
|
-
Block<F, G>,
|
|
622
|
-
Block<G, H>,
|
|
623
|
-
Block<H, I>,
|
|
624
|
-
Block<I, J>,
|
|
625
|
-
Block<J, K>,
|
|
626
|
-
Block<K, L>,
|
|
627
|
-
EndMarker
|
|
628
|
-
]): Flow<L>;
|
|
629
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>>(blocks: readonly [
|
|
630
|
-
StartMarker,
|
|
631
|
-
Block<S, B>,
|
|
632
|
-
Block<B, C>,
|
|
633
|
-
Block<C, D>,
|
|
634
|
-
Block<D, E>,
|
|
635
|
-
Block<E, F>,
|
|
636
|
-
Block<F, G>,
|
|
637
|
-
Block<G, H>,
|
|
638
|
-
Block<H, I>,
|
|
639
|
-
Block<I, J>,
|
|
640
|
-
Block<J, K>,
|
|
641
|
-
Block<K, L>,
|
|
642
|
-
Block<L, M>,
|
|
643
|
-
EndMarker
|
|
644
|
-
]): Flow<M>;
|
|
645
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>, N extends Checkpoint<string>>(blocks: readonly [
|
|
646
|
-
StartMarker,
|
|
647
|
-
Block<S, B>,
|
|
648
|
-
Block<B, C>,
|
|
649
|
-
Block<C, D>,
|
|
650
|
-
Block<D, E>,
|
|
651
|
-
Block<E, F>,
|
|
652
|
-
Block<F, G>,
|
|
653
|
-
Block<G, H>,
|
|
654
|
-
Block<H, I>,
|
|
655
|
-
Block<I, J>,
|
|
656
|
-
Block<J, K>,
|
|
657
|
-
Block<K, L>,
|
|
658
|
-
Block<L, M>,
|
|
659
|
-
Block<M, N>,
|
|
660
|
-
EndMarker
|
|
661
|
-
]): Flow<N>;
|
|
662
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>, N extends Checkpoint<string>, O extends Checkpoint<string>>(blocks: readonly [
|
|
663
|
-
StartMarker,
|
|
664
|
-
Block<S, B>,
|
|
665
|
-
Block<B, C>,
|
|
666
|
-
Block<C, D>,
|
|
667
|
-
Block<D, E>,
|
|
668
|
-
Block<E, F>,
|
|
669
|
-
Block<F, G>,
|
|
670
|
-
Block<G, H>,
|
|
671
|
-
Block<H, I>,
|
|
672
|
-
Block<I, J>,
|
|
673
|
-
Block<J, K>,
|
|
674
|
-
Block<K, L>,
|
|
675
|
-
Block<L, M>,
|
|
676
|
-
Block<M, N>,
|
|
677
|
-
Block<N, O>,
|
|
678
|
-
EndMarker
|
|
679
|
-
]): Flow<O>;
|
|
680
|
-
/**
|
|
681
|
-
* Fluent, kind-checked alternative to `defineFlow([start, ...blocks, end])` -
|
|
682
|
-
* see {@link MapBuilder}. Real, direct request this responds to: pia/zsign's
|
|
683
|
-
* own agents kept hand-editing/hand-composing Blocks into ad hoc shapes
|
|
684
|
-
* ("locks" convention tried, still got broken) - `map()` forces every step
|
|
685
|
-
* through this Engine's own `define*Block` factories (checked by the same
|
|
686
|
-
* `__waygraphKind`/`__waygraphSalt` runtime markers `graph.ts`/`map-check.ts`
|
|
687
|
-
* already trust), so a hand-rolled plain-object Block can never silently
|
|
688
|
-
* pass as a real navigation/assertion/method step. `homeOrigin`, if given,
|
|
689
|
-
* also gates `.gotoPage()`/`.gotoExternal()` against each Nav/Page Block's
|
|
690
|
-
* own static `url` (skipped, honestly, for click-based/dynamic nav - not
|
|
691
|
-
* statically checkable, same limitation `map-check.ts` already documents).
|
|
692
|
-
* @example
|
|
693
|
-
* const flow = engine.map({ homeOrigin: "https://app.example.com" })
|
|
694
|
-
* .start()
|
|
695
|
-
* .gotoPage(NavHomeBlock)
|
|
696
|
-
* .assert(AssertHelloBlock)
|
|
697
|
-
* .gotoExternal(NavMailpitBlock)
|
|
698
|
-
* .end();
|
|
699
|
-
*/
|
|
700
|
-
map(options?: MapBuilderOptions): MapBuilder<S>;
|
|
701
|
-
}
|
|
702
|
-
export interface MapBuilderOptions {
|
|
703
|
-
/**
|
|
704
|
-
* This project's own origin (e.g. `"https://app.example.com"`) - enables
|
|
705
|
-
* `.gotoPage()`/`.gotoExternal()`'s origin check against a Block's static
|
|
706
|
-
* `url`. Omit to skip that check entirely (still fully kind-checked either
|
|
707
|
-
* way; only the internal/external origin distinction is opt-in).
|
|
708
|
-
*/
|
|
709
|
-
homeOrigin?: string;
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* Fluent builder over {@link Engine.defineFlow} - see `map()`'s own doc
|
|
713
|
-
* comment for why this exists. Each step method is scoped to exactly the
|
|
714
|
-
* Block kind its name promises, checked at RUNTIME against the
|
|
715
|
-
* `__waygraphKind`/`__waygraphSalt` markers `defineNavBlock`/`definePageBlock`/
|
|
716
|
-
* `defineAssertBlock`/`defineMethodBlock`/`defineEffectBlock` already set
|
|
717
|
-
* (the same markers `graph.ts` and `map-check.ts` trust) - not just a type
|
|
718
|
-
* hint, since a hand-rolled object can satisfy the TypeScript `Block<In,Out>`
|
|
719
|
-
* shape without ever going through a real factory. Each call also
|
|
720
|
-
* typechecks the accumulated Checkpoint chain exactly like `defineFlow`'s
|
|
721
|
-
* own tuple overloads do (a step's `In` must equal the previous step's
|
|
722
|
-
* `Out`) - this is what "no teleporting" means: there is no method on this
|
|
723
|
-
* builder that can skip from one Checkpoint to an unrelated one without a
|
|
724
|
-
* real, kind-correct Block in between.
|
|
725
|
-
*/
|
|
726
|
-
export declare class MapBuilder<Out extends Checkpoint<string>> {
|
|
727
|
-
private readonly engine;
|
|
728
|
-
private readonly steps;
|
|
729
|
-
private readonly homeOrigin;
|
|
730
|
-
private readonly ff;
|
|
731
|
-
private constructor();
|
|
732
|
-
/** @internal - use `engine.map()` or the standalone `map()` export. */
|
|
733
|
-
static begin(engine: Engine, homeOrigin: string | undefined): MapBuilder<S>;
|
|
734
|
-
/** Readable chain-opener - mirrors `defineFlow`'s leading `start` sentinel. Returns `this` unchanged; entirely optional. */
|
|
735
|
-
start(): MapBuilder<Out>;
|
|
736
|
-
/**
|
|
737
|
-
* Open a fast-forward window - steps until {@link ffEnd} collapse into one
|
|
738
|
-
* opaque `fastForwardComposeBlock` (blitz theater). Kind/salt checks still
|
|
739
|
-
* run on each inner step as it is added.
|
|
740
|
-
*/
|
|
741
|
-
ffStart(name?: string): MapBuilder<Out>;
|
|
742
|
-
/**
|
|
743
|
-
* Close the current fast-forward window and append one FFCompose step.
|
|
744
|
-
* Throws if empty or if {@link ffStart} was never opened.
|
|
745
|
-
*/
|
|
746
|
-
ffEnd(): MapBuilder<Out>;
|
|
747
|
-
private appendStep;
|
|
748
|
-
/**
|
|
749
|
-
* Appends an internal navigation/page-arrival step - requires a Block from
|
|
750
|
-
* `defineNavBlock`/`defineMemNavBlock`/`definePageBlock`. Throws if given
|
|
751
|
-
* anything else, including a `homeOrigin`-mismatched static `url`.
|
|
752
|
-
* Compile-time: {@link NavBlock} or {@link PageBlock} only (not Assert/Method).
|
|
753
|
-
*/
|
|
754
|
-
gotoPage<NextOut extends Checkpoint<string>>(block: (NavBlock<NextOut> | PageBlock<NextOut>) & {
|
|
755
|
-
name: string;
|
|
756
|
-
}): MapBuilder<NextOut>;
|
|
757
|
-
/**
|
|
758
|
-
* Appends a genuinely cross-origin navigation step (e.g. `(external)/`
|
|
759
|
-
* Blocks in the Waygraph Map convention: mailpit, maildrop.cc) - same
|
|
760
|
-
* kind requirement as {@link gotoPage}, plus the inverse `homeOrigin` check.
|
|
761
|
-
* Compile-time: {@link NavBlock} or {@link PageBlock} only.
|
|
762
|
-
*/
|
|
763
|
-
gotoExternal<NextOut extends Checkpoint<string>>(block: (NavBlock<NextOut> | PageBlock<NextOut>) & {
|
|
764
|
-
name: string;
|
|
765
|
-
}): MapBuilder<NextOut>;
|
|
766
|
-
/**
|
|
767
|
-
* Appends a self-loop verification step - requires a Block from
|
|
768
|
-
* `defineAssertBlock`. Compile-time: {@link AssertBlock} only (not `.method()`).
|
|
769
|
-
*/
|
|
770
|
-
assert(block: AssertBlock<Out> & {
|
|
771
|
-
name: string;
|
|
772
|
-
}): MapBuilder<Out>;
|
|
773
|
-
/**
|
|
774
|
-
* Appends a non-navigating page action (submit, upload, add/remove an
|
|
775
|
-
* instance) - requires a Block from `defineMethodBlock`/`defineActionBlock`/
|
|
776
|
-
* `defineEffectBlock`/`defineMemEffectBlock`.
|
|
777
|
-
* Compile-time: {@link MethodBlock} or {@link EffectBlock} only - Assert
|
|
778
|
-
* Blocks must use `.assert()`. Runtime also rejects `__waygraphKind =
|
|
779
|
-
* "assert"` (those still carry method salt from the factory internals).
|
|
780
|
-
*/
|
|
781
|
-
method<NextOut extends Checkpoint<string>>(block: (MethodBlock<Out, NextOut> | EffectBlock<Out, NextOut>) & {
|
|
782
|
-
name: string;
|
|
783
|
-
}): MapBuilder<NextOut>;
|
|
784
|
-
/**
|
|
785
|
-
* Finalizes this chain into a real, runnable {@link Flow} - same object
|
|
786
|
-
* `defineFlow` returns, so `withBlockVerify`/`modBlockVerify` and every
|
|
787
|
-
* `withTitle`/`withHighlightFixtures`/etc. decorator still apply exactly
|
|
788
|
-
* as they do today; this builder only changes how the chain is assembled,
|
|
789
|
-
* never what it produces. Throws if no step was ever added - an empty map
|
|
790
|
-
* isn't a flow.
|
|
791
|
-
*/
|
|
792
|
-
end(): Flow<Out>;
|
|
793
|
-
}
|
|
794
|
-
/**
|
|
795
|
-
* Standalone convenience for `new Engine(config).map(options)` - use this
|
|
796
|
-
* when a call site doesn't otherwise need its own `Engine` instance (no
|
|
797
|
-
* shared `headless`/`slowMo`/`layouts` across several flows).
|
|
798
|
-
* @example const flow = map({ homeOrigin: "https://app.example.com" }).gotoPage(NavHomeBlock).end();
|
|
799
|
-
*/
|
|
800
|
-
export declare function map(options?: MapBuilderOptions & EngineConfig): MapBuilder<S>;
|
|
801
|
-
/**
|
|
802
|
-
* Attaches routing to `block` without touching its act/observe/resolve/verify -
|
|
803
|
-
* `routes` must cover every tag of `block`'s output (a missing route is a compile
|
|
804
|
-
* error), and the returned Block runs exactly as `block` always did, just followed
|
|
805
|
-
* by whichever next Block the resolved tag routes to. `null` for a tag means that
|
|
806
|
-
* tag is terminal - the run stops there, same as a Block with no routing at all.
|
|
807
|
-
* A route pointing back at `block` itself is a self-loop; see `runGraph`'s
|
|
808
|
-
* `maxSteps` for its safety net. The return type is deliberately `Block<In, any>` -
|
|
809
|
-
* a route can lead anywhere, including back through itself, so there is no fixed
|
|
810
|
-
* Out type to express; state the expected outcomes to `runGraph` via `terminals`
|
|
811
|
-
* instead.
|
|
812
|
-
*/
|
|
813
|
-
export declare function branch<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, routes: {
|
|
814
|
-
[K in Out["__state"]]: Block<Extract<Out, Checkpoint<K>>, any> | null;
|
|
815
|
-
}): DefinedBlock<In, any>;
|
|
816
|
-
/**
|
|
817
|
-
* Builds a Block with `withVerify`/`modVerify`/`modVerifyAll` attached as
|
|
818
|
-
* methods - `LoginBlock.withVerify([...])`, discoverable by typing
|
|
819
|
-
* `LoginBlock.` in an editor, not just callable as `withVerify(LoginBlock, ...)`
|
|
820
|
-
* if you already know it exists. A raw object literal is still a perfectly
|
|
821
|
-
* valid Block (every test fixture in this codebase is one) - it just won't have
|
|
822
|
-
* these attached. The methods are thin: they delegate to the identically-named
|
|
823
|
-
* free functions, which remain the one place this logic actually lives.
|
|
824
|
-
*/
|
|
825
|
-
export declare function defineBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: {
|
|
826
|
-
name: string;
|
|
827
|
-
description?: Block<In, Out>["description"];
|
|
828
|
-
instruction: Omit<Instruction<In, Out, any>, "act"> & {
|
|
829
|
-
act(page: ActionPage, input: In, mem: MemPage): Promise<void>;
|
|
830
|
-
};
|
|
831
|
-
next?: Block<In, Out>["next"];
|
|
832
|
-
requires?: Block<In, Out>["requires"];
|
|
833
|
-
routes?: Block<In, Out>["routes"];
|
|
834
|
-
instanceOptions?: Block<In, Out>["instanceOptions"];
|
|
835
|
-
}): DefinedBlock<In, Out>;
|
|
836
|
-
/**
|
|
837
|
-
* A Block whose only possible action is navigating to a URL - built via
|
|
838
|
-
* {@link defineNavBlock}, never with a hand-authored `act()`. Extends `Block`
|
|
839
|
-
* (same shape `DefinedBlock`/`ComposedBlock` already use), so it drops into
|
|
840
|
-
* `defineFlow([...])`, `connect()`, `composeBlock()` exactly like any other
|
|
841
|
-
* Block - no special-casing needed anywhere that only expects a `Block`.
|
|
842
|
-
* See `openspec/specs/nav-block-and-check/spec.md` for why this exists.
|
|
843
|
-
*
|
|
844
|
-
* `__wgFactory` is a TypeScript-only brand so {@link MapBuilder.gotoPage} /
|
|
845
|
-
* {@link MapBuilder.gotoExternal} can reject Assert/Method Blocks at compile
|
|
846
|
-
* time (runtime still checks `__waygraphKind`). Decorate methods are re-stated
|
|
847
|
-
* (via Omit) so `.stubBefore()` / `.withVerify()` keep the brand.
|
|
848
|
-
*/
|
|
849
|
-
export type NavBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpoint<string>, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
850
|
-
readonly __wgFactory?: "nav";
|
|
851
|
-
withVerify(verify: Trait[] | ((out: Out) => Trait[])): NavBlock<Out>;
|
|
852
|
-
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): NavBlock<Out>;
|
|
853
|
-
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): NavBlock<Out>;
|
|
854
|
-
stubBefore(stub: import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
855
|
-
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
856
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
857
|
-
stubAfter(stub: import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
858
|
-
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
859
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
860
|
-
stubOnError(stub: import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
861
|
-
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
862
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
863
|
-
};
|
|
864
|
-
/**
|
|
865
|
-
* `defineNavBlock`'s own options - exactly one of `url`/`click` required,
|
|
866
|
-
* enforced at compile time (giving both, or neither, is a type error - see
|
|
867
|
-
* `typecheck/nav-block.types.ts`). `checkpoint` is the tag this NavBlock
|
|
868
|
-
* resolves to once navigation completes - a NavBlock never branches on
|
|
869
|
-
* observed evidence the way a regular Block can, so there's no `resolve`
|
|
870
|
-
* logic to author; it always just declares "arrived."
|
|
871
|
-
*/
|
|
872
|
-
export type NavBlockOptions<Out extends Checkpoint<string>> = {
|
|
873
|
-
name: string;
|
|
874
|
-
description?: string;
|
|
875
|
-
checkpoint: Out["__state"];
|
|
876
|
-
requires?: readonly MemKey<any>[];
|
|
877
|
-
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
878
|
-
stubBefore?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
879
|
-
stubAfter?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
880
|
-
stubOnError?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
881
|
-
/** @deprecated Prefer stubAfter. */
|
|
882
|
-
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
883
|
-
/**
|
|
884
|
-
* Live per-instance menu rows for `waygraph auto` (see {@link Block.instanceOptions}).
|
|
885
|
-
* When set, the explore menu lists one row per option instead of a single
|
|
886
|
-
* generic nav edge - used by {@link defineMemNavBlock}.
|
|
887
|
-
*/
|
|
888
|
-
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
889
|
-
} & ({
|
|
890
|
-
/**
|
|
891
|
-
* Direct URL navigation. Accepts a plain string or a function
|
|
892
|
-
* `(mem) => string` for parameterized routes (e.g.
|
|
893
|
-
* `/dashboard/requests/:id` with a real id read from mem). The
|
|
894
|
-
* escape hatch for the few real cases with no click path to get
|
|
895
|
-
* there (a deep link from an email, a public share link) - not for
|
|
896
|
-
* skipping past navigation an agent didn't feel like finding. Prefer
|
|
897
|
-
* `click` whenever the target app actually has one.
|
|
898
|
-
*/
|
|
899
|
-
url: string | ((mem: MemPage) => string);
|
|
900
|
-
click?: never;
|
|
901
|
-
} | {
|
|
902
|
-
/**
|
|
903
|
-
* Navigates by clicking a real element already on the page (a nav
|
|
904
|
-
* link, a sidebar item) instead of teleporting straight to a URL -
|
|
905
|
-
* the opinionated default. Accepts a Playwright selector string, or
|
|
906
|
-
* a function `(mem) => selector` for a target that depends on mem
|
|
907
|
-
* (e.g. clicking the row for a specific id). Verifying arrival is
|
|
908
|
-
* `verify`'s job (typically `Trait.url(...)`), same as a `url`-based
|
|
909
|
-
* NavBlock - the click itself is only ever awaited for its own
|
|
910
|
-
* completion, not for whatever navigation it triggers.
|
|
911
|
-
*/
|
|
912
|
-
click: string | ((mem: MemPage) => string);
|
|
913
|
-
url?: never;
|
|
914
|
-
});
|
|
915
|
-
/**
|
|
916
|
-
* Builds a {@link NavBlock}. The generated `act()` is always exactly
|
|
917
|
-
* `page.goto(url)` or `page.locator(click).click()` - never anything else,
|
|
918
|
-
* never author-supplied. Callers get a real `Page` here internally (the one
|
|
919
|
-
* legitimate place navigation belongs); `defineBlock`'s own `ActionPage`
|
|
920
|
-
* narrowing is what discourages navigation everywhere else, and never
|
|
921
|
-
* applies to this generated function since no author ever writes it by
|
|
922
|
-
* hand.
|
|
923
|
-
* @example defineNavBlock({ name: "nav-web-login", checkpoint: "LoginForm", url: "/login" })
|
|
924
|
-
* @example defineNavBlock({ name: "nav-web-request-detail", checkpoint: "RequestDetail", url: (mem) => `/dashboard/requests/${mem.get(RequestId.key)}` })
|
|
925
|
-
* @example defineNavClickBlock({ name: "nav-web-documents", checkpoint: "DocumentsList", click: "nav >> text=Documents" })
|
|
926
|
-
* For click-nav in app code prefer {@link defineNavClickBlock} (url stays here).
|
|
927
|
-
*/
|
|
928
|
-
export declare function defineNavBlock<Out extends Checkpoint<string>>(options: NavBlockOptions<Out>): NavBlock<Out>;
|
|
929
|
-
/**
|
|
930
|
-
* Click-only {@link NavBlock}. Same runtime as {@link defineNavBlock} with
|
|
931
|
-
* `click` - use this in app code so you never wonder whether a Nav is url or
|
|
932
|
-
* click (no `__waygraphNavClick` sniffing at author time). Prefer
|
|
933
|
-
* {@link defineNavBlock} only for `url` / `goto` deep links.
|
|
934
|
-
*/
|
|
935
|
-
export type NavClickBlockOptions<Out extends Checkpoint<string>> = {
|
|
936
|
-
name: string;
|
|
937
|
-
description?: string;
|
|
938
|
-
checkpoint: Out["__state"];
|
|
939
|
-
click: string | ((mem: MemPage) => string);
|
|
940
|
-
requires?: readonly MemKey<any>[];
|
|
941
|
-
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
942
|
-
stubBefore?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
943
|
-
stubAfter?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
944
|
-
stubOnError?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
945
|
-
/** @deprecated Prefer stubAfter. */
|
|
946
|
-
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
947
|
-
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
948
|
-
};
|
|
949
|
-
export type NavClickBlock<Out extends Checkpoint<string>> = NavBlock<Out>;
|
|
950
|
-
/** @see {@link NavClickBlockOptions} */
|
|
951
|
-
export declare function defineNavClickBlock<Out extends Checkpoint<string>>(options: NavClickBlockOptions<Out>): NavClickBlock<Out>;
|
|
952
|
-
/**
|
|
953
|
-
* TypeScript salt over {@link defineBlock} for one-shot non-nav app steps
|
|
954
|
-
* (submit, upload, finish, logout) - **methods** on a page. Same runtime Block;
|
|
955
|
-
* marks `__waygraphSalt = "method"` so auto/docs can tell Method from bare
|
|
956
|
-
* {@link defineBlock}. Does not force `instanceOptions` - use
|
|
957
|
-
* {@link defineEffectBlock} when the auto menu should spawn one row per live
|
|
958
|
-
* DOM instance. Prefer hanging methods off a {@link definePageBlock} hub.
|
|
959
|
-
*/
|
|
960
|
-
export type MethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = Omit<DefinedBlock<In, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
961
|
-
readonly __wgFactory?: "method";
|
|
962
|
-
withVerify(verify: Trait[] | ((out: Out) => Trait[])): MethodBlock<In, Out>;
|
|
963
|
-
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): MethodBlock<In, Out>;
|
|
964
|
-
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): MethodBlock<In, Out>;
|
|
965
|
-
stubBefore(stub: import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
966
|
-
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
967
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
968
|
-
stubAfter(stub: import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
969
|
-
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
970
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
971
|
-
stubOnError(stub: import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
972
|
-
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
973
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
974
|
-
};
|
|
975
|
-
/** @deprecated Prefer {@link MethodBlock} - same type; Action was the 0.7 name. */
|
|
976
|
-
export type ActionBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = MethodBlock<In, Out>;
|
|
977
|
-
export declare function defineMethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: Parameters<typeof defineBlock<In, Out>>[0]): MethodBlock<In, Out>;
|
|
978
|
-
/** @deprecated Prefer {@link defineMethodBlock} - identical helper (0.7 name). */
|
|
979
|
-
export declare const defineActionBlock: typeof defineMethodBlock;
|
|
980
|
-
export interface AssertBlockOptions<Out extends Checkpoint<string> = Checkpoint<string>> {
|
|
981
|
-
name: string;
|
|
982
|
-
description?: string;
|
|
983
|
-
/** Self-loop target - the Checkpoint this assertion runs on and returns to. */
|
|
984
|
-
checkpoint: Out["__state"];
|
|
985
|
-
/**
|
|
986
|
-
* Shorthand for the wait-then-assert shape found repeatedly in hand-written
|
|
987
|
-
* assertion Blocks: waits for a heading with this accessible name before
|
|
988
|
-
* `verify` runs. Omit for a pure "assert whatever is already on the page"
|
|
989
|
-
* check with no wait. Not a general `act()` override - a Block that needs
|
|
990
|
-
* more than this stays a plain `defineMethodBlock`.
|
|
991
|
-
*/
|
|
992
|
-
waitForHeading?: string;
|
|
993
|
-
verify: Trait[] | ((out: Out) => Trait[]);
|
|
994
|
-
/** Mem keys this assertion's `verify` reads (e.g. a mem-aware Trait) - checked by preflight before the flow runs. */
|
|
995
|
-
requires?: readonly MemKey<any>[];
|
|
996
|
-
stubBefore?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
997
|
-
stubAfter?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
998
|
-
stubOnError?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
999
|
-
/** Multi-step yap slides (demo only) - same field `Instruction.slides` exposes elsewhere. */
|
|
1000
|
-
slides?: import("./highlights.js").WaygraphSlidesOrFn<Out>;
|
|
1001
|
-
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Sugar for a self-loop-only "pure assertion" Block: no hand-written
|
|
1004
|
-
* `act`/`resolve`, just a name, a `checkpoint` tag, and a `verify` array.
|
|
1005
|
-
* `resolve` is generated from the one `checkpoint` field given, closing the
|
|
1006
|
-
* copy/rename footgun where a hand-restated checkpoint string can silently
|
|
1007
|
-
* drift wrong across a copy/pasted file. Mirrors `definePageBlock`'s own
|
|
1008
|
-
* construction pattern (flat options in, `defineBlock` built internally).
|
|
1009
|
-
* See openspec/changes/waygraph-agent-skill-hardening/spec.md.
|
|
1010
|
-
* @example
|
|
1011
|
-
* defineAssertBlock({
|
|
1012
|
-
* name: "assert-raw-materials-table",
|
|
1013
|
-
* checkpoint: "RawMaterials",
|
|
1014
|
-
* waitForHeading: "Raw Materials & Lead Times",
|
|
1015
|
-
* verify: [Trait.visible(RawMaterialsSel.reorderBadge)],
|
|
1016
|
-
* });
|
|
1017
|
-
*/
|
|
1018
|
-
export declare function defineAssertBlock<Out extends Checkpoint<string> = Checkpoint<string>>(options: AssertBlockOptions<Out>): AssertBlock<Out>;
|
|
1019
|
-
/**
|
|
1020
|
-
* Self-loop verify Block from {@link defineAssertBlock}. Branded for
|
|
1021
|
-
* {@link MapBuilder.assert} (not accepted by `.method()`).
|
|
1022
|
-
*/
|
|
1023
|
-
export type AssertBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Out, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
1024
|
-
readonly __wgFactory?: "assert";
|
|
1025
|
-
withVerify(verify: Trait[] | ((out: Out) => Trait[])): AssertBlock<Out>;
|
|
1026
|
-
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): AssertBlock<Out>;
|
|
1027
|
-
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): AssertBlock<Out>;
|
|
1028
|
-
stubBefore(stub: import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1029
|
-
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
1030
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1031
|
-
stubAfter(stub: import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1032
|
-
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
1033
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1034
|
-
stubOnError(stub: import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1035
|
-
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
1036
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
1037
|
-
};
|
|
1038
|
-
/** One Block (or lazy factory) registered on a {@link PageBlock}. */
|
|
1039
|
-
export type PageMethodEntry = DefinedBlock<any, any> | (() => DefinedBlock<any, any>);
|
|
1040
|
-
export type PageBlockOptions<Out extends Checkpoint<string>> = {
|
|
1041
|
-
name: string;
|
|
1042
|
-
description?: string;
|
|
1043
|
-
/** Checkpoint tag for this screen (hub). */
|
|
1044
|
-
checkpoint: Out["__state"];
|
|
1045
|
-
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
1046
|
-
stubBefore?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
1047
|
-
stubAfter?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
1048
|
-
stubOnError?: import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
1049
|
-
/** @deprecated Prefer stubAfter. */
|
|
1050
|
-
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
1051
|
-
requires?: readonly MemKey<any>[];
|
|
1052
|
-
/**
|
|
1053
|
-
* Methods available on this page. Array, or a record of Blocks / `() => Block`
|
|
1054
|
-
* factories (lazy so the page object can colocate method definitions).
|
|
1055
|
-
*/
|
|
1056
|
-
methods?: readonly PageMethodEntry[] | Record<string, PageMethodEntry>;
|
|
1057
|
-
/**
|
|
1058
|
-
* Optional deep-link onto this page (`goto`). XOR with `click`. Omit when the
|
|
1059
|
-
* hub is arrival-only (previous Block already resolved here).
|
|
1060
|
-
*/
|
|
1061
|
-
url?: string | ((mem: MemPage) => string);
|
|
1062
|
-
/** Optional click-nav onto this page. XOR with `url`. */
|
|
1063
|
-
click?: string | ((mem: MemPage) => string);
|
|
1064
|
-
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
1065
|
-
};
|
|
1066
|
-
/**
|
|
1067
|
-
* Page hub Block: one Checkpoint = this screen; methods hang off the hub for
|
|
1068
|
-
* readability / auto grouping. Runtime is still a Block (`__waygraphKind = "page"`).
|
|
1069
|
-
* `act` is goto/click when `url`/`click` is set, otherwise a no-op (already here).
|
|
1070
|
-
* Child methods stay ordinary Blocks for graph edges - the page only registers them.
|
|
1071
|
-
* Branded `__wgFactory: "page"` (not `"nav"`) - both are accepted by
|
|
1072
|
-
* {@link MapBuilder.gotoPage} / {@link MapBuilder.gotoExternal}.
|
|
1073
|
-
*/
|
|
1074
|
-
export type PageBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpoint<string>, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
1075
|
-
readonly __wgFactory?: "page";
|
|
1076
|
-
/** Resolved method Blocks registered at define time. */
|
|
1077
|
-
readonly methods: readonly DefinedBlock<any, any>[];
|
|
1078
|
-
withVerify(verify: Trait[] | ((out: Out) => Trait[])): PageBlock<Out>;
|
|
1079
|
-
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): PageBlock<Out>;
|
|
1080
|
-
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): PageBlock<Out>;
|
|
1081
|
-
stubBefore(stub: import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1082
|
-
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
1083
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1084
|
-
stubAfter(stub: import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1085
|
-
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
1086
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1087
|
-
stubOnError(stub: import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1088
|
-
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
1089
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
1090
|
-
};
|
|
1091
|
-
/** @see {@link PageBlockOptions} */
|
|
1092
|
-
export declare function definePageBlock<Out extends Checkpoint<string>>(options: PageBlockOptions<Out>): PageBlock<Out>;
|
|
1093
|
-
/**
|
|
1094
|
-
* TypeScript salt over {@link defineBlock}: same runtime Block, but the type
|
|
1095
|
-
* forces `requires` + `instanceOptions` so `waygraph auto` can list one menu
|
|
1096
|
-
* row per live instance (add/remove/toggle). Not a separate engine concept -
|
|
1097
|
-
* everything is still a Block.
|
|
1098
|
-
*/
|
|
1099
|
-
export type EffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = Omit<DefinedBlock<In, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
1100
|
-
readonly __wgFactory?: "effect";
|
|
1101
|
-
requires: readonly MemKey<any>[];
|
|
1102
|
-
instanceOptions: NonNullable<Block<In, Out>["instanceOptions"]>;
|
|
1103
|
-
withVerify(verify: Trait[] | ((out: Out) => Trait[])): EffectBlock<In, Out>;
|
|
1104
|
-
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): EffectBlock<In, Out>;
|
|
1105
|
-
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): EffectBlock<In, Out>;
|
|
1106
|
-
stubBefore(stub: import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1107
|
-
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
1108
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1109
|
-
stubAfter(stub: import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1110
|
-
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
1111
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1112
|
-
stubOnError(stub: import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1113
|
-
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
1114
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
1115
|
-
};
|
|
1116
|
-
/** @deprecated Prefer {@link EffectBlock} - same type; Mem* was an early name. */
|
|
1117
|
-
export type MemEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = EffectBlock<In, Out>;
|
|
1118
|
-
/**
|
|
1119
|
-
* TypeScript salt over {@link defineNavBlock}: mem-picked destination
|
|
1120
|
-
* (which product row / which request id). Still a NavBlock / Block at runtime.
|
|
1121
|
-
*/
|
|
1122
|
-
export type MemNavBlock<Out extends Checkpoint<string>> = NavBlock<Out> & {
|
|
1123
|
-
requires: readonly MemKey<any>[];
|
|
1124
|
-
instanceOptions: NonNullable<Block<Checkpoint<string>, Out>["instanceOptions"]>;
|
|
1125
|
-
};
|
|
1126
|
-
/**
|
|
1127
|
-
* {@link defineBlock} constrained for effect-style instance menus: `requires` +
|
|
1128
|
-
* `instanceOptions` are mandatory. Prefer this when the Block adds / removes /
|
|
1129
|
-
* toggles a live instance rather than navigating. Runtime result is an ordinary
|
|
1130
|
-
* Block - the helper is TypeScript salt only.
|
|
1131
|
-
*/
|
|
1132
|
-
export declare function defineEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: Parameters<typeof defineBlock<In, Out>>[0] & {
|
|
1133
|
-
requires: readonly MemKey<any>[];
|
|
1134
|
-
instanceOptions: NonNullable<Block<In, Out>["instanceOptions"]>;
|
|
1135
|
-
}): EffectBlock<In, Out>;
|
|
1136
|
-
/** @deprecated Prefer {@link defineEffectBlock} - identical helper. */
|
|
1137
|
-
export declare const defineMemEffectBlock: typeof defineEffectBlock;
|
|
1138
|
-
/**
|
|
1139
|
-
* {@link defineNavBlock} constrained to mem-picked navigation: requires +
|
|
1140
|
-
* instanceOptions mandatory, and `click`/`url` should depend on that mem
|
|
1141
|
-
* (typically `click: (mem) => …`). Prefer this when the Block opens one of
|
|
1142
|
-
* several live rows/items rather than a fixed nav target. Still a Block.
|
|
1143
|
-
*/
|
|
1144
|
-
export declare function defineMemNavBlock<Out extends Checkpoint<string>>(options: NavBlockOptions<Out> & {
|
|
1145
|
-
requires: readonly MemKey<any>[];
|
|
1146
|
-
instanceOptions: NonNullable<Block<Checkpoint<string>, Out>["instanceOptions"]>;
|
|
1147
|
-
}): MemNavBlock<Out>;
|
|
1148
|
-
/**
|
|
1149
|
-
* "Where am I" - reverse-matches a live `page` against every NavBlock /
|
|
1150
|
-
* PageBlock in `library`, in order, returning the first one whose own `verify`
|
|
1151
|
-
* Traits all pass (its `checkpoint`), or `null` if none match. Deliberately
|
|
1152
|
-
* Nav/Page hubs only: each has exactly one fixed `checkpoint` and a `verify`
|
|
1153
|
-
* list whose whole job is already "confirm arrival here," so it's a reliable
|
|
1154
|
-
* fingerprint - a regular `defineBlock` can branch to different `Out` tags
|
|
1155
|
-
* depending on runtime evidence, so its `verify` alone doesn't identify a
|
|
1156
|
-
* single state the way a hub's does.
|
|
1157
|
-
*
|
|
1158
|
-
* The primitive `waygraph auto`'s discovered graph is *for* - the graph says
|
|
1159
|
-
* what pages exist and how to reach them; `locate()` is how an autonomous
|
|
1160
|
-
* run figures out which one it's actually looking at right now, without a
|
|
1161
|
-
* human telling it.
|
|
1162
|
-
*
|
|
1163
|
-
* More than one NavBlock matching is a real possibility (two Checkpoints
|
|
1164
|
-
* whose `verify` Traits are both satisfied by the same page) - `locate()`
|
|
1165
|
-
* returns the first match rather than treating that as an error; resolving
|
|
1166
|
-
* genuine ambiguity is a follow-up, not solved here.
|
|
1167
|
-
* @example const here = await locate(page, [NavLoginBlock, NavDashboardBlock]);
|
|
1168
|
-
*/
|
|
1169
|
-
export declare function locate(page: Page, library: readonly NavBlock<any>[], options?: {
|
|
1170
|
-
timeoutMs?: number;
|
|
1171
|
-
}): Promise<string | null>;
|
|
1172
|
-
/**
|
|
1173
|
-
* Returns a new Block that runs exactly like `block` - same act/observe/resolve,
|
|
1174
|
-
* same routing - but with `verify` replaced. For giving one flow stricter (or
|
|
1175
|
-
* looser, or just different) confirmation on a Block it didn't author, without
|
|
1176
|
-
* that Block needing to have been written as a parameterized factory in
|
|
1177
|
-
* anticipation. Same move as `branch()`: decorate an existing Block, don't ask
|
|
1178
|
-
* every Block to pre-build its own override mechanism.
|
|
1179
|
-
*
|
|
1180
|
-
* Wrap the one Block you want to change, in place, wherever it already sits in
|
|
1181
|
-
* a `defineFlow([...])` array - every other Block stays untouched:
|
|
1182
|
-
* `defineFlow([start, LoginBlock, withVerify(AddToCartBlock, [...]), end])`.
|
|
1183
|
-
* There is no separate positional array to keep in sync and no `null`
|
|
1184
|
-
* placeholder for "skip this one" - `defineFlow` has no per-slot verify
|
|
1185
|
-
* argument at all, only whatever `verify` each Block's own `instruction` (or
|
|
1186
|
-
* a `withVerify(...)` wrapping it) carries with it.
|
|
1187
|
-
*/
|
|
1188
|
-
export declare function withVerify<B extends Block<any, any>>(block: B, verify: Trait[] | ((out: any) => Trait[])): B;
|
|
1189
|
-
type StubPhaseFn<Out extends Checkpoint<string>> = import("./highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
1190
|
-
/**
|
|
1191
|
-
* Attach / chain a stubBefore lifecycle on a Block. Prefer
|
|
1192
|
-
* `(ctx) => { ctx.ring(...); const x = ctx.mem?.get(Key); }`.
|
|
1193
|
-
* @example FillUsernameBlock.stubBefore((ctx) => { ctx.ring("username", { ... }) })
|
|
1194
|
-
*/
|
|
1195
|
-
export declare function withStubBefore<B extends Block<any, any>>(block: B, stub: StubPhaseFn<any>): B;
|
|
1196
|
-
/** @see {@link withStubBefore} */
|
|
1197
|
-
export declare function withStubAfter<B extends Block<any, any>>(block: B, stub: StubPhaseFn<any>): B;
|
|
1198
|
-
/** @see {@link withStubBefore} */
|
|
1199
|
-
export declare function withStubOnError<B extends Block<any, any>>(block: B, stub: StubPhaseFn<any>): B;
|
|
1200
|
-
/**
|
|
1201
|
-
* Replaces one Trait inside `block`'s verify list, leaving every other check
|
|
1202
|
-
* untouched - the v1/v2/legacy-variant case, where one check needs a different
|
|
1203
|
-
* selector or URL pattern but the rest of the Block is identical. Addressed by
|
|
1204
|
-
* the Trait's own `name` (recommended - inserting or reordering other checks
|
|
1205
|
-
* can't silently retarget it) or, if you genuinely know the position and don't
|
|
1206
|
-
* need that safety, a numeric index. Either way a bad address fails loud
|
|
1207
|
-
* immediately instead of quietly doing nothing. `newCheck` can be a bare
|
|
1208
|
-
* `check` function (keeps the existing name) or a full `Trait` (to rename too).
|
|
1209
|
-
* Only works on a flat `verify` array - a function-form `verify` (from
|
|
1210
|
-
* `verify: (out) => Trait[]`) has no fixed list to address into, so this
|
|
1211
|
-
* throws rather than guess; use `withVerify` to replace it wholesale instead.
|
|
1212
|
-
*/
|
|
1213
|
-
export declare function modVerify<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, nameOrIndex: string | number, newCheck: Trait["check"] | Trait): DefinedBlock<In, Out>;
|
|
1214
|
-
/**
|
|
1215
|
-
* `modVerify`, but for several named checks in one call - a v2 variant that
|
|
1216
|
-
* differs in five ways from v1 shouldn't need five nested `modVerify(modVerify(
|
|
1217
|
-
* modVerify(...)))` calls to track by eye. `patches` keys are plain strings (a
|
|
1218
|
-
* Trait's `name`, not a `MemKey` instance), so an ordinary object literal is
|
|
1219
|
-
* fine here - unlike `MemPage`, there's no identity-collision reason to need
|
|
1220
|
-
* `[name, check]` pairs. Applies each patch in turn via `modVerify`, so the
|
|
1221
|
-
* same fail-loud-on-unknown-name behavior holds for every entry.
|
|
1222
|
-
*/
|
|
1223
|
-
export declare function modVerifyAll<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, patches: Record<string, Trait["check"] | Trait>): DefinedBlock<In, Out>;
|
|
1224
|
-
export {};
|
|
1
|
+
export * from "./engine/config.js";
|
|
2
|
+
export * from "./engine/run-graph.js";
|
|
3
|
+
export * from "./engine/flow.js";
|
|
4
|
+
export * from "./engine/core.js";
|
|
5
|
+
export * from "./engine/compose.js";
|
|
6
|
+
export * from "./engine/engine-class.js";
|
|
7
|
+
export * from "./engine/blocks/nav.js";
|
|
8
|
+
export * from "./engine/blocks/method.js";
|
|
9
|
+
export * from "./engine/blocks/page.js";
|
|
10
|
+
export * from "./engine/blocks/effect.js";
|
|
11
|
+
export * from "./engine/locate.js";
|