waygraph 0.15.51 → 0.15.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/analysis/graph.d.ts +1 -1
- package/dist/analysis/graph.js +10 -15
- package/dist/analysis/map-check.d.ts +3 -2
- package/dist/analysis/practices-check.d.ts +0 -1
- package/dist/analysis/practices-check.js +0 -13
- package/dist/auto-session/session.d.ts +1 -1
- package/dist/auto-session/session.js +13 -8
- package/dist/blocks-select.d.ts +7 -4
- package/dist/blocks-select.js +0 -14
- package/dist/browser.d.ts +27 -0
- package/dist/browser.js +62 -0
- package/dist/cli/flags.js +3 -1
- package/dist/cli/run-chain.js +4 -0
- package/dist/cli/usage.js +17 -1
- package/dist/cli.js +13 -1
- package/dist/commands/agent-dive-scaffold.d.ts +5 -20
- package/dist/commands/agent-dive-scaffold.js +10 -3
- package/dist/commands/extensions.d.ts +1 -0
- package/dist/commands/extensions.js +22 -0
- package/dist/commands/init.js +43 -5
- package/dist/commands/test.js +16 -2
- package/dist/commands/try.js +2 -1
- package/dist/commands/upgrade.d.ts +6 -0
- package/dist/commands/upgrade.js +113 -0
- package/dist/config.d.ts +81 -3
- package/dist/config.js +91 -16
- package/dist/core/block.d.ts +19 -2
- package/dist/core/block.js +43 -3
- package/dist/core/blocks/nav.d.ts +11 -0
- package/dist/core/blocks/nav.js +8 -0
- package/dist/core/config.d.ts +5 -0
- package/dist/core/engine.d.ts +19 -16
- package/dist/core/engine.js +6 -4
- package/dist/core/flow.d.ts +27 -0
- package/dist/core/flow.js +75 -28
- package/dist/core/map-builder.d.ts +30 -4
- package/dist/core/map-builder.js +45 -7
- package/dist/env-file.d.ts +7 -7
- package/dist/env-file.js +29 -16
- package/dist/extensions.d.ts +21 -0
- package/dist/extensions.js +178 -0
- package/dist/highlights/demo-pace.d.ts +0 -1
- package/dist/highlights/demo-pace.js +24 -3
- package/dist/index.d.ts +7 -5
- package/dist/index.js +3 -2
- package/dist/pilot-overlay/action-ring.d.ts +0 -9
- package/dist/pilot-overlay/action-ring.js +1 -1
- package/dist/pilot-overlay/overlay-fixtures.d.ts +0 -7
- package/dist/pilot-overlay/overlay-fixtures.js +0 -45
- package/dist/pilot-overlay/panel.d.ts +2 -1
- package/dist/playwright-config.d.ts +4 -0
- package/dist/playwright-config.js +15 -0
- package/dist/playwright.config.d.ts +2 -0
- package/dist/playwright.config.js +6 -0
- package/dist/runner/demo-log.js +1 -7
- package/dist/runner/inpage/core.d.ts +1 -1
- package/dist/runner/inpage/core.js +8 -7
- package/dist/runner/interaction-patch.js +32 -1
- package/dist/runner/main.js +22 -11
- package/dist/runner/rings.js +0 -49
- package/dist/runner/step-mode.js +10 -4
- package/dist/session/auto-explore-run.js +9 -5
- package/dist/session/auto-explore.d.ts +2 -1
- package/dist/session/auto-explore.js +6 -4
- package/dist/session/auto-session-ipc.d.ts +1 -2
- package/dist/session/auto-session-ipc.js +1 -1
- package/dist/session/block-inject.d.ts +0 -13
- package/dist/session/block-inject.js +3 -3
- package/dist/session/pilot.d.ts +0 -2
- package/dist/session/pilot.js +1 -2
- package/dist/session/step-overlay.js +3 -1
- package/dist/traverse/coverage.d.ts +0 -4
- package/dist/traverse/coverage.js +1 -1
- package/dist/traverse/run.js +3 -1
- package/dist/types.d.ts +1 -1
- package/dist/ui/components/ring.js +1 -0
- package/dist/ui/overlay.css +1 -0
- package/dist/ui/shadow.d.ts +1 -3
- package/dist/ui/shadow.js +0 -4
- package/dist/ui/tokens.d.ts +0 -11
- package/dist/ui/tokens.js +0 -5
- package/dist/video-dir.d.ts +8 -0
- package/dist/video-dir.js +60 -0
- package/dist/webserver.js +5 -1
- package/package.json +11 -5
- package/templates/scaffold/README.md +5 -3
- package/templates/scaffold/STRUCTURE.md +10 -4
- package/templates/scaffold/config/waygraph.config.ts +45 -0
- package/templates/scaffold/package.json +7 -7
- package/templates/scaffold/src/flows/(external)/hoppscotch/auth.flow.ts +36 -0
- package/templates/scaffold/src/flows/(external)/hoppscotch/get.flow.ts +24 -0
- package/templates/scaffold/src/flows/(external)/hoppscotch/post.flow.ts +34 -0
- package/templates/scaffold/src/flows/(user-stories)/email-verification.flow.ts +47 -0
- package/templates/scaffold/src/flows/README.md +35 -14
- package/templates/scaffold/src/flows/home/cart.flow.ts +51 -0
- package/templates/scaffold/src/flows/home/hello.flow.ts +42 -0
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +0 -9
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +0 -5
- package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +1 -1
- package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +3 -19
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +2 -25
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +2 -19
- package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +1 -17
- package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +1 -10
- package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +1 -12
- package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +0 -9
- package/templates/scaffold/src/map/(app_base)/home/_sel.ts +3 -1
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +1 -23
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +19 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +18 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +15 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +23 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +36 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +17 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +22 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +18 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +11 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +36 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_sel.ts +27 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +10 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +2 -27
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +2 -21
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +1 -19
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +1 -11
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +1 -9
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +0 -11
- package/templates/scaffold/src/states/demo.mem-keys.ts +20 -19
- package/templates/scaffold/src/states/demo.mem-stubs.ts +4 -0
- package/templates/scaffold/src/states/demo.states.ts +5 -1
- package/templates/scaffold/tests/example.spec.ts +6 -7
- package/templates/scaffold/tests/hoppscotch.spec.ts +97 -0
- package/templates/scaffold/tests/mail-verify.spec.ts +8 -17
- package/templates/scaffold/tsconfig.json +1 -1
- package/templates/skills/waygraph-convention.skill.md +40 -3
- package/templates/skills/waygraph-pilot.skill.md +4 -5
- package/dist/browser-path.d.ts +0 -5
- package/dist/browser-path.js +0 -18
- package/dist/runner/overlay-present.d.ts +0 -8
- package/dist/runner/overlay-present.js +0 -57
- package/dist/ui/components/banner.d.ts +0 -2
- package/dist/ui/components/banner.js +0 -10
- package/dist/ui/components/cursor.d.ts +0 -2
- package/dist/ui/components/cursor.js +0 -19
- package/templates/scaffold/playwright.config.ts +0 -12
- package/templates/scaffold/src/flows/example.flow.ts +0 -29
- package/templates/scaffold/src/flows/mail-verify.flow.ts +0 -85
- package/templates/scaffold/src/flows/shop.flow.ts +0 -74
package/dist/core/engine.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Block, Checkpoint } from "../types.js";
|
|
2
2
|
import type { EngineConfig } from "./config.js";
|
|
3
3
|
import type { EndMarker, StartMarker } from "./run-graph.js";
|
|
4
|
-
import type { Flow } from "./flow.js";
|
|
4
|
+
import type { Flow, FlowOptions } from "./flow.js";
|
|
5
5
|
import { MapBuilder } from "./map-builder.js";
|
|
6
6
|
import type { MapBuilderOptions } from "./map-builder.js";
|
|
7
7
|
type S = Checkpoint<"__start__">;
|
|
@@ -16,18 +16,21 @@ export declare class Engine {
|
|
|
16
16
|
private readonly config;
|
|
17
17
|
constructor(config?: EngineConfig);
|
|
18
18
|
/**
|
|
19
|
+
* @deprecated Build flows with `engine.map()`, which checks each step's Block kind and nests flows with `.flow()`.
|
|
20
|
+
*
|
|
19
21
|
* Builds a runnable {@link Flow} from `[start, ...Blocks, end]`, typechecked
|
|
20
22
|
* so each Block's `In` must match the previous Block's `Out` - the same
|
|
21
23
|
* check `connect()` does, just declared as a flat array instead of hand-nested
|
|
22
24
|
* calls. Overloaded for 2-9 array slots (1-8 real Blocks between `start`/`end`)
|
|
23
25
|
* rather than one fully-generic recursive tuple type, so each arity is as
|
|
24
26
|
* reliably checked as `connect<A,B,C>` itself.
|
|
25
|
-
*
|
|
27
|
+
* Options go in the second argument instead of wrapping the result in `withTitle(withMemStub(...))`.
|
|
28
|
+
* @example engine.defineFlow([start, LoginBlock, AddToCartBlock, end], { title: "Login", memStub: true })
|
|
26
29
|
*/
|
|
27
|
-
defineFlow<B extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, EndMarker]): Flow<B>;
|
|
28
|
-
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, Block<B, C>, EndMarker]): Flow<C>;
|
|
29
|
-
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>;
|
|
30
|
-
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>;
|
|
30
|
+
defineFlow<B extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, EndMarker], options?: FlowOptions): Flow<B>;
|
|
31
|
+
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>>(blocks: readonly [StartMarker, Block<S, B>, Block<B, C>, EndMarker], options?: FlowOptions): Flow<C>;
|
|
32
|
+
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], options?: FlowOptions): Flow<D>;
|
|
33
|
+
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], options?: FlowOptions): Flow<E>;
|
|
31
34
|
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>>(blocks: readonly [
|
|
32
35
|
StartMarker,
|
|
33
36
|
Block<S, B>,
|
|
@@ -36,7 +39,7 @@ export declare class Engine {
|
|
|
36
39
|
Block<D, E>,
|
|
37
40
|
Block<E, F>,
|
|
38
41
|
EndMarker
|
|
39
|
-
]): Flow<F>;
|
|
42
|
+
], options?: FlowOptions): Flow<F>;
|
|
40
43
|
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 [
|
|
41
44
|
StartMarker,
|
|
42
45
|
Block<S, B>,
|
|
@@ -46,7 +49,7 @@ export declare class Engine {
|
|
|
46
49
|
Block<E, F>,
|
|
47
50
|
Block<F, G>,
|
|
48
51
|
EndMarker
|
|
49
|
-
]): Flow<G>;
|
|
52
|
+
], options?: FlowOptions): Flow<G>;
|
|
50
53
|
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 [
|
|
51
54
|
StartMarker,
|
|
52
55
|
Block<S, B>,
|
|
@@ -57,7 +60,7 @@ export declare class Engine {
|
|
|
57
60
|
Block<F, G>,
|
|
58
61
|
Block<G, H>,
|
|
59
62
|
EndMarker
|
|
60
|
-
]): Flow<H>;
|
|
63
|
+
], options?: FlowOptions): Flow<H>;
|
|
61
64
|
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 [
|
|
62
65
|
StartMarker,
|
|
63
66
|
Block<S, B>,
|
|
@@ -69,7 +72,7 @@ export declare class Engine {
|
|
|
69
72
|
Block<G, H>,
|
|
70
73
|
Block<H, I>,
|
|
71
74
|
EndMarker
|
|
72
|
-
]): Flow<I>;
|
|
75
|
+
], options?: FlowOptions): Flow<I>;
|
|
73
76
|
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 [
|
|
74
77
|
StartMarker,
|
|
75
78
|
Block<S, B>,
|
|
@@ -82,7 +85,7 @@ export declare class Engine {
|
|
|
82
85
|
Block<H, I>,
|
|
83
86
|
Block<I, J>,
|
|
84
87
|
EndMarker
|
|
85
|
-
]): Flow<J>;
|
|
88
|
+
], options?: FlowOptions): Flow<J>;
|
|
86
89
|
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 [
|
|
87
90
|
StartMarker,
|
|
88
91
|
Block<S, B>,
|
|
@@ -96,7 +99,7 @@ export declare class Engine {
|
|
|
96
99
|
Block<I, J>,
|
|
97
100
|
Block<J, K>,
|
|
98
101
|
EndMarker
|
|
99
|
-
]): Flow<K>;
|
|
102
|
+
], options?: FlowOptions): Flow<K>;
|
|
100
103
|
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 [
|
|
101
104
|
StartMarker,
|
|
102
105
|
Block<S, B>,
|
|
@@ -111,7 +114,7 @@ export declare class Engine {
|
|
|
111
114
|
Block<J, K>,
|
|
112
115
|
Block<K, L>,
|
|
113
116
|
EndMarker
|
|
114
|
-
]): Flow<L>;
|
|
117
|
+
], options?: FlowOptions): Flow<L>;
|
|
115
118
|
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 [
|
|
116
119
|
StartMarker,
|
|
117
120
|
Block<S, B>,
|
|
@@ -127,7 +130,7 @@ export declare class Engine {
|
|
|
127
130
|
Block<K, L>,
|
|
128
131
|
Block<L, M>,
|
|
129
132
|
EndMarker
|
|
130
|
-
]): Flow<M>;
|
|
133
|
+
], options?: FlowOptions): Flow<M>;
|
|
131
134
|
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 [
|
|
132
135
|
StartMarker,
|
|
133
136
|
Block<S, B>,
|
|
@@ -144,7 +147,7 @@ export declare class Engine {
|
|
|
144
147
|
Block<L, M>,
|
|
145
148
|
Block<M, N>,
|
|
146
149
|
EndMarker
|
|
147
|
-
]): Flow<N>;
|
|
150
|
+
], options?: FlowOptions): Flow<N>;
|
|
148
151
|
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 [
|
|
149
152
|
StartMarker,
|
|
150
153
|
Block<S, B>,
|
|
@@ -162,7 +165,7 @@ export declare class Engine {
|
|
|
162
165
|
Block<M, N>,
|
|
163
166
|
Block<N, O>,
|
|
164
167
|
EndMarker
|
|
165
|
-
]): Flow<O>;
|
|
168
|
+
], options?: FlowOptions): Flow<O>;
|
|
166
169
|
/**
|
|
167
170
|
* Fluent, kind-checked alternative to `defineFlow([start, ...blocks, end])` -
|
|
168
171
|
* see {@link MapBuilder}. Real, direct request this responds to: pia/zsign's
|
package/dist/core/engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildFlow } from "./flow.js";
|
|
1
|
+
import { applyFlowOptions, buildFlow } from "./flow.js";
|
|
2
2
|
import { MapBuilder } from "./map-builder.js";
|
|
3
3
|
/**
|
|
4
4
|
* Holds engine-level configuration shared across every flow defined from it -
|
|
@@ -12,8 +12,8 @@ export class Engine {
|
|
|
12
12
|
constructor(config = {}) {
|
|
13
13
|
this.config = config;
|
|
14
14
|
}
|
|
15
|
-
defineFlow(blocks) {
|
|
16
|
-
return buildFlow(blocks.slice(1, -1), this.config);
|
|
15
|
+
defineFlow(blocks, options) {
|
|
16
|
+
return applyFlowOptions(buildFlow(blocks.slice(1, -1), this.config), options);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Fluent, kind-checked alternative to `defineFlow([start, ...blocks, end])` -
|
|
@@ -36,7 +36,9 @@ export class Engine {
|
|
|
36
36
|
* .end();
|
|
37
37
|
*/
|
|
38
38
|
map(options) {
|
|
39
|
-
|
|
39
|
+
const { homeOrigin, ...flowOptions } = options ?? {};
|
|
40
|
+
const define = this.defineFlow.bind(this);
|
|
41
|
+
return MapBuilder.begin((blocks, extra) => define(blocks, { ...flowOptions, ...extra }), homeOrigin);
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
/**
|
package/dist/core/flow.d.ts
CHANGED
|
@@ -176,6 +176,7 @@ export declare function buildFlow<Out extends Checkpoint<string>>(middle: readon
|
|
|
176
176
|
* exactly as if a human had opened the app fresh, not wherever the
|
|
177
177
|
* previous Flow in the chain happened to leave the page.
|
|
178
178
|
* @example const loginFlow = withSessionReset(engine.defineFlow([start, LoginBlock, end]));
|
|
179
|
+
* @deprecated Use `map().flow(sub, { reset: true })`; the reset belongs to where flows are joined.
|
|
179
180
|
*/
|
|
180
181
|
export declare function withSessionReset<Out extends Checkpoint<string>>(flow: Flow<Out>): Flow<Out>;
|
|
181
182
|
/**
|
|
@@ -184,6 +185,7 @@ export declare function withSessionReset<Out extends Checkpoint<string>>(flow: F
|
|
|
184
185
|
* Blocks are executing, instead of one fixed title for the whole run.
|
|
185
186
|
* Non-destructive, same pattern as {@link withSessionReset}.
|
|
186
187
|
* @example const ticket123 = withTitle(loginFlow, "Ticket #123 - Sales rep signs in");
|
|
188
|
+
* @deprecated Name a flow with `ctx.title(...)` in a stub on its first step.
|
|
187
189
|
*/
|
|
188
190
|
export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out>, title: string): Flow<Out>;
|
|
189
191
|
/**
|
|
@@ -195,6 +197,7 @@ export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out
|
|
|
195
197
|
* this itself - the CLI's `--data`/`--mem-stub` seeding, or a bare-library
|
|
196
198
|
* caller's own explicit `seedMemStub(mem, flow)` call, does the filling.
|
|
197
199
|
* @example const demoLogin = withMemStub(loginFlow);
|
|
200
|
+
* @deprecated Use `engine.map({ memStub: true })`.
|
|
198
201
|
*/
|
|
199
202
|
export declare function withMemStub<Out extends Checkpoint<string>>(flow: Flow<Out>): Flow<Out>;
|
|
200
203
|
/**
|
|
@@ -205,17 +208,20 @@ export declare function withMemStub<Out extends Checkpoint<string>>(flow: Flow<O
|
|
|
205
208
|
* @example withDemoPace(happyFlow, 0.5) // 2x faster than normal
|
|
206
209
|
* @example withDemoPace(gapFlow, 2.5) // 2.5x slower
|
|
207
210
|
* @example withDemoPace(gapFlow, 4500) // absolute ~4.5s gates/dwells
|
|
211
|
+
* @deprecated Use `engine.map({ demoPace })`, a step `{ pace }`, or `demo.pace` in the config.
|
|
208
212
|
*/
|
|
209
213
|
export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: DemoPace): Flow<Out>;
|
|
210
214
|
/**
|
|
211
215
|
* Default highlight look for a Flow episode (size / weight / optional tone).
|
|
212
216
|
* Per-slot stub or {@link withHighlightFixtures} values win when set.
|
|
213
217
|
* @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
|
|
218
|
+
* @deprecated Use `engine.map({ highlightStyle })`.
|
|
214
219
|
*/
|
|
215
220
|
export declare function withHighlightStyle<Out extends Checkpoint<string>>(flow: Flow<Out>, style: HighlightStyleDefaults): Flow<Out>;
|
|
216
221
|
/**
|
|
217
222
|
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
218
223
|
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
224
|
+
* @deprecated Use a step option: `.method(Block, { pace })`.
|
|
219
225
|
*/
|
|
220
226
|
export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace: DemoPace): Block<In, Out>;
|
|
221
227
|
/**
|
|
@@ -235,6 +241,7 @@ export declare function withBlockPace<In extends Checkpoint<string>, Out extends
|
|
|
235
241
|
* engine.defineFlow([start, NavLoginBlock, SubmitLoginActionBlock, end]),
|
|
236
242
|
* "locked_out_user stays on LoginPage with the error banner - working as intended.",
|
|
237
243
|
* );
|
|
244
|
+
* @deprecated Use `engine.map({ expectedFailure: reason })`.
|
|
238
245
|
*/
|
|
239
246
|
export declare function withExpectedFailure<Out extends Checkpoint<string>>(flow: Flow<Out>, reason: string): Flow<Out>;
|
|
240
247
|
/**
|
|
@@ -243,8 +250,27 @@ export declare function withExpectedFailure<Out extends Checkpoint<string>>(flow
|
|
|
243
250
|
* stubOnError slots. Non-destructive, same pattern as {@link withTitle}.
|
|
244
251
|
* Demo/`chain --step` reads `flow.highlightFixtures`; `run()` ignores it.
|
|
245
252
|
* @example withHighlightFixtures(issueFlow, { "submit-login": { stubBefore: { email: { label: "AC-1" } } } })
|
|
253
|
+
* @deprecated Chain ctx stubs on the Block: `Block.stubAfter((ctx) => …)`.
|
|
246
254
|
*/
|
|
247
255
|
export declare function withHighlightFixtures<Out extends Checkpoint<string>>(flow: Flow<Out>, fixtures: import("../highlights.js").HighlightFixtureMap): Flow<Out>;
|
|
256
|
+
/** Everything a `with*` wrapper can set, given up front: `engine.defineFlow([...], { title, memStub, ... })`. */
|
|
257
|
+
export interface FlowOptions {
|
|
258
|
+
/** Shown as the banner while the Flow runs (`withTitle`). */
|
|
259
|
+
title?: string;
|
|
260
|
+
/** Fill missing `requires` keys from `registerMemStub` (`withMemStub`). */
|
|
261
|
+
memStub?: boolean;
|
|
262
|
+
/** Clear cookies and storage before this Flow's first Block when chained after another (`withSessionReset`). */
|
|
263
|
+
sessionReset?: boolean;
|
|
264
|
+
/** `withDemoPace`. */
|
|
265
|
+
demoPace?: DemoPace;
|
|
266
|
+
/** `withHighlightStyle`. */
|
|
267
|
+
highlightStyle?: HighlightStyleDefaults;
|
|
268
|
+
/** Marks a Flow that is supposed to throw, with the reason (`withExpectedFailure`). */
|
|
269
|
+
expectedFailure?: string;
|
|
270
|
+
}
|
|
271
|
+
/** Applies each set option through its `with*` wrapper, so both spellings produce the same Flow. */
|
|
272
|
+
export declare function applyFlowOptions<Out extends Checkpoint<string>>(flow: Flow<Out>, options: FlowOptions | undefined): Flow<Out>;
|
|
273
|
+
export declare function clearSessionState(context: BrowserContext, page: Page): Promise<void>;
|
|
248
274
|
/**
|
|
249
275
|
* Runs several complete, independent Flows one after another, reusing the
|
|
250
276
|
* same page/context/mem in order - each remains its own validated
|
|
@@ -262,5 +288,6 @@ export declare function withHighlightFixtures<Out extends Checkpoint<string>>(fl
|
|
|
262
288
|
* chain - nothing to reset yet). The combined result is whatever the LAST
|
|
263
289
|
* flow resolved to.
|
|
264
290
|
* @example chainFlow(ticket123Flow, ticket456Flow).run(context, mem)
|
|
291
|
+
* @deprecated Nest flows with `map().flow(a).flow(b, { reset: true })`.
|
|
265
292
|
*/
|
|
266
293
|
export declare function chainFlow(...flows: readonly Flow<any>[]): Flow<any>;
|
package/dist/core/flow.js
CHANGED
|
@@ -1,12 +1,43 @@
|
|
|
1
1
|
// Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
2
|
import { connect } from "../types.js";
|
|
3
|
-
import { chromiumExecutablePath } from "../browser
|
|
3
|
+
import { chromiumExecutablePath, extensionPathsFromEnv, launchContext } from "../browser.js";
|
|
4
|
+
import { resolveExtensions } from "../extensions.js";
|
|
5
|
+
import { loadWaygraphConfig } from "../config.js";
|
|
4
6
|
import { WaygraphError, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_INDEX, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_NAME, MSG_CHAINFLOW_EMPTY, } from "../errors.js";
|
|
5
7
|
import { preflight, runGraph } from "./run-graph.js";
|
|
6
8
|
import { resolveLauncher } from "./config.js";
|
|
7
9
|
import { MemPage } from "../mem-page.js";
|
|
8
|
-
import { findBlockIndex, modVerify, withVerify } from "./block.js";
|
|
10
|
+
import { copyWaygraphRuntime, findBlockIndex, modVerify, withVerify } from "./block.js";
|
|
9
11
|
import { normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight } from "../highlights.js";
|
|
12
|
+
/** Launches the browser and context an Engine uses when the caller gave none, from its config. */
|
|
13
|
+
async function openOwnContext(engineConfig) {
|
|
14
|
+
// A config chosen with `--config` / WAYGRAPH_CONFIG wins over the one the Engine was built with, so a flow that imports
|
|
15
|
+
// an engine from one config file still follows the config the run selected.
|
|
16
|
+
const chosen = process.env.WAYGRAPH_CONFIG ? await loadWaygraphConfig(process.cwd()) : undefined;
|
|
17
|
+
const config = chosen
|
|
18
|
+
? {
|
|
19
|
+
...engineConfig,
|
|
20
|
+
...(chosen.baseUrl !== undefined ? { baseUrl: chosen.baseUrl } : {}),
|
|
21
|
+
...(chosen.extensions !== undefined ? { extensions: chosen.extensions } : {}),
|
|
22
|
+
}
|
|
23
|
+
: engineConfig;
|
|
24
|
+
const browserName = config?.browserName ?? "chromium";
|
|
25
|
+
const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
|
|
26
|
+
const baseURL = config?.baseUrl ?? process.env.WAYGRAPH_BASE_URL;
|
|
27
|
+
return launchContext({
|
|
28
|
+
launcher: resolveLauncher(browserName, config),
|
|
29
|
+
launch: {
|
|
30
|
+
headless: config?.headless ?? true,
|
|
31
|
+
...(config?.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
|
|
32
|
+
...(executablePath ? { executablePath } : {}),
|
|
33
|
+
},
|
|
34
|
+
context: {
|
|
35
|
+
...(baseURL ? { baseURL } : {}),
|
|
36
|
+
...(config?.recordVideo ? { recordVideo: config.recordVideo } : {}),
|
|
37
|
+
},
|
|
38
|
+
extensions: await resolveExtensions(config?.extensions ?? extensionPathsFromEnv(), process.cwd()),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
10
41
|
export function buildFlow(middle, engineConfig) {
|
|
11
42
|
// resetSession/title start false/unset here - defineFlow itself carries
|
|
12
43
|
// no such options anymore. They're set by wrapping the result in
|
|
@@ -32,16 +63,8 @@ export function buildFlow(middle, engineConfig) {
|
|
|
32
63
|
// before a page opens - the same "fail loud, cheaply" guarantee
|
|
33
64
|
// run(context, mem) already has via an existing context.
|
|
34
65
|
preflight(mem, chain);
|
|
35
|
-
const
|
|
36
|
-
const launch = resolveLauncher(browserName, config);
|
|
37
|
-
const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
|
|
38
|
-
const browser = await launch.launch({
|
|
39
|
-
headless: config.headless ?? true,
|
|
40
|
-
...(config.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
|
|
41
|
-
...(executablePath ? { executablePath } : {}),
|
|
42
|
-
});
|
|
66
|
+
const { context, close } = await openOwnContext(config);
|
|
43
67
|
try {
|
|
44
|
-
const context = await browser.newContext(config.recordVideo ? { recordVideo: config.recordVideo } : {});
|
|
45
68
|
try {
|
|
46
69
|
return await runGraph(chain, undefined, context, mem, 5000, {
|
|
47
70
|
...(config.layouts !== undefined ? { layouts: config.layouts } : {}),
|
|
@@ -56,7 +79,7 @@ export function buildFlow(middle, engineConfig) {
|
|
|
56
79
|
}
|
|
57
80
|
}
|
|
58
81
|
finally {
|
|
59
|
-
await
|
|
82
|
+
await close();
|
|
60
83
|
}
|
|
61
84
|
}
|
|
62
85
|
const context = contextOrMem;
|
|
@@ -97,7 +120,12 @@ export function buildFlow(middle, engineConfig) {
|
|
|
97
120
|
};
|
|
98
121
|
return {
|
|
99
122
|
resetSession: false,
|
|
100
|
-
blocks: () => middle.map((b) => ({
|
|
123
|
+
blocks: () => middle.map((b) => ({
|
|
124
|
+
name: b.name,
|
|
125
|
+
block: b,
|
|
126
|
+
...(b.routes ? { routes: b.routes } : {}),
|
|
127
|
+
...(b.__waygraphResetBefore ? { resetSessionBefore: true } : {}),
|
|
128
|
+
})),
|
|
101
129
|
run: run,
|
|
102
130
|
withBlockVerify(block, verify) {
|
|
103
131
|
const index = findBlockIndex(middle, block);
|
|
@@ -127,6 +155,7 @@ export function buildFlow(middle, engineConfig) {
|
|
|
127
155
|
* exactly as if a human had opened the app fresh, not wherever the
|
|
128
156
|
* previous Flow in the chain happened to leave the page.
|
|
129
157
|
* @example const loginFlow = withSessionReset(engine.defineFlow([start, LoginBlock, end]));
|
|
158
|
+
* @deprecated Use `map().flow(sub, { reset: true })`; the reset belongs to where flows are joined.
|
|
130
159
|
*/
|
|
131
160
|
export function withSessionReset(flow) {
|
|
132
161
|
return {
|
|
@@ -142,6 +171,7 @@ export function withSessionReset(flow) {
|
|
|
142
171
|
* Blocks are executing, instead of one fixed title for the whole run.
|
|
143
172
|
* Non-destructive, same pattern as {@link withSessionReset}.
|
|
144
173
|
* @example const ticket123 = withTitle(loginFlow, "Ticket #123 - Sales rep signs in");
|
|
174
|
+
* @deprecated Name a flow with `ctx.title(...)` in a stub on its first step.
|
|
145
175
|
*/
|
|
146
176
|
export function withTitle(flow, title) {
|
|
147
177
|
return {
|
|
@@ -160,6 +190,7 @@ export function withTitle(flow, title) {
|
|
|
160
190
|
* this itself - the CLI's `--data`/`--mem-stub` seeding, or a bare-library
|
|
161
191
|
* caller's own explicit `seedMemStub(mem, flow)` call, does the filling.
|
|
162
192
|
* @example const demoLogin = withMemStub(loginFlow);
|
|
193
|
+
* @deprecated Use `engine.map({ memStub: true })`.
|
|
163
194
|
*/
|
|
164
195
|
export function withMemStub(flow) {
|
|
165
196
|
return {
|
|
@@ -177,6 +208,7 @@ export function withMemStub(flow) {
|
|
|
177
208
|
* @example withDemoPace(happyFlow, 0.5) // 2x faster than normal
|
|
178
209
|
* @example withDemoPace(gapFlow, 2.5) // 2.5x slower
|
|
179
210
|
* @example withDemoPace(gapFlow, 4500) // absolute ~4.5s gates/dwells
|
|
211
|
+
* @deprecated Use `engine.map({ demoPace })`, a step `{ pace }`, or `demo.pace` in the config.
|
|
180
212
|
*/
|
|
181
213
|
export function withDemoPace(flow, pace) {
|
|
182
214
|
const demoPace = pace;
|
|
@@ -191,6 +223,7 @@ export function withDemoPace(flow, pace) {
|
|
|
191
223
|
* Default highlight look for a Flow episode (size / weight / optional tone).
|
|
192
224
|
* Per-slot stub or {@link withHighlightFixtures} values win when set.
|
|
193
225
|
* @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
|
|
226
|
+
* @deprecated Use `engine.map({ highlightStyle })`.
|
|
194
227
|
*/
|
|
195
228
|
export function withHighlightStyle(flow, style) {
|
|
196
229
|
const highlightStyle = {
|
|
@@ -208,12 +241,12 @@ export function withHighlightStyle(flow, style) {
|
|
|
208
241
|
/**
|
|
209
242
|
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
210
243
|
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
244
|
+
* @deprecated Use a step option: `.method(Block, { pace })`.
|
|
211
245
|
*/
|
|
212
246
|
export function withBlockPace(block, pace) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
};
|
|
247
|
+
const next = { ...block, demoPace: pace };
|
|
248
|
+
copyWaygraphRuntime(block, next);
|
|
249
|
+
return next;
|
|
217
250
|
}
|
|
218
251
|
/**
|
|
219
252
|
* Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
|
|
@@ -232,6 +265,7 @@ export function withBlockPace(block, pace) {
|
|
|
232
265
|
* engine.defineFlow([start, NavLoginBlock, SubmitLoginActionBlock, end]),
|
|
233
266
|
* "locked_out_user stays on LoginPage with the error banner - working as intended.",
|
|
234
267
|
* );
|
|
268
|
+
* @deprecated Use `engine.map({ expectedFailure: reason })`.
|
|
235
269
|
*/
|
|
236
270
|
export function withExpectedFailure(flow, reason) {
|
|
237
271
|
return {
|
|
@@ -247,6 +281,7 @@ export function withExpectedFailure(flow, reason) {
|
|
|
247
281
|
* stubOnError slots. Non-destructive, same pattern as {@link withTitle}.
|
|
248
282
|
* Demo/`chain --step` reads `flow.highlightFixtures`; `run()` ignores it.
|
|
249
283
|
* @example withHighlightFixtures(issueFlow, { "submit-login": { stubBefore: { email: { label: "AC-1" } } } })
|
|
284
|
+
* @deprecated Chain ctx stubs on the Block: `Block.stubAfter((ctx) => …)`.
|
|
250
285
|
*/
|
|
251
286
|
export function withHighlightFixtures(flow, fixtures) {
|
|
252
287
|
return {
|
|
@@ -256,6 +291,25 @@ export function withHighlightFixtures(flow, fixtures) {
|
|
|
256
291
|
modBlockVerify: (block, nameOrIndex, newCheck) => withHighlightFixtures(flow.modBlockVerify(block, nameOrIndex, newCheck), fixtures),
|
|
257
292
|
};
|
|
258
293
|
}
|
|
294
|
+
/** Applies each set option through its `with*` wrapper, so both spellings produce the same Flow. */
|
|
295
|
+
export function applyFlowOptions(flow, options) {
|
|
296
|
+
if (!options)
|
|
297
|
+
return flow;
|
|
298
|
+
let f = flow;
|
|
299
|
+
if (options.sessionReset)
|
|
300
|
+
f = withSessionReset(f);
|
|
301
|
+
if (options.title !== undefined)
|
|
302
|
+
f = withTitle(f, options.title);
|
|
303
|
+
if (options.demoPace)
|
|
304
|
+
f = withDemoPace(f, options.demoPace);
|
|
305
|
+
if (options.highlightStyle)
|
|
306
|
+
f = withHighlightStyle(f, options.highlightStyle);
|
|
307
|
+
if (options.expectedFailure !== undefined)
|
|
308
|
+
f = withExpectedFailure(f, options.expectedFailure);
|
|
309
|
+
if (options.memStub)
|
|
310
|
+
f = withMemStub(f);
|
|
311
|
+
return f;
|
|
312
|
+
}
|
|
259
313
|
function locateInChain(flows, block) {
|
|
260
314
|
if (typeof block === "number") {
|
|
261
315
|
let remaining = block;
|
|
@@ -275,7 +329,7 @@ function locateInChain(flows, block) {
|
|
|
275
329
|
}
|
|
276
330
|
throw new WaygraphError("WG_FLOW_BLOCK_NOT_FOUND", MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_NAME(blockName));
|
|
277
331
|
}
|
|
278
|
-
async function clearSessionState(context, page) {
|
|
332
|
+
export async function clearSessionState(context, page) {
|
|
279
333
|
await context.clearCookies().catch(() => { });
|
|
280
334
|
await page
|
|
281
335
|
.evaluate(() => {
|
|
@@ -306,6 +360,7 @@ async function clearSessionState(context, page) {
|
|
|
306
360
|
* chain - nothing to reset yet). The combined result is whatever the LAST
|
|
307
361
|
* flow resolved to.
|
|
308
362
|
* @example chainFlow(ticket123Flow, ticket456Flow).run(context, mem)
|
|
363
|
+
* @deprecated Nest flows with `map().flow(a).flow(b, { reset: true })`.
|
|
309
364
|
*/
|
|
310
365
|
export function chainFlow(...flows) {
|
|
311
366
|
if (flows.length === 0) {
|
|
@@ -319,16 +374,8 @@ export function chainFlow(...flows) {
|
|
|
319
374
|
// config) would otherwise each launch a separate browser, defeating
|
|
320
375
|
// the point of sequencing them (a fresh browser is itself a full
|
|
321
376
|
// session reset, silently making withSessionReset a no-op).
|
|
322
|
-
const
|
|
323
|
-
const launch = resolveLauncher(browserName, config);
|
|
324
|
-
const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
|
|
325
|
-
const browser = await launch.launch({
|
|
326
|
-
headless: config?.headless ?? true,
|
|
327
|
-
...(config?.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
|
|
328
|
-
...(executablePath ? { executablePath } : {}),
|
|
329
|
-
});
|
|
377
|
+
const { context, close } = await openOwnContext(config);
|
|
330
378
|
try {
|
|
331
|
-
const context = await browser.newContext(config?.recordVideo ? { recordVideo: config.recordVideo } : {});
|
|
332
379
|
try {
|
|
333
380
|
return await run(context, mem, { closeOnFinish: true });
|
|
334
381
|
}
|
|
@@ -337,7 +384,7 @@ export function chainFlow(...flows) {
|
|
|
337
384
|
}
|
|
338
385
|
}
|
|
339
386
|
finally {
|
|
340
|
-
await
|
|
387
|
+
await close();
|
|
341
388
|
}
|
|
342
389
|
}
|
|
343
390
|
const context = contextOrMem;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Block, Checkpoint } from "../types.js";
|
|
2
2
|
import type { EndMarker, StartMarker } from "./run-graph.js";
|
|
3
|
-
import type { Flow } from "./flow.js";
|
|
3
|
+
import type { Flow, FlowOptions } from "./flow.js";
|
|
4
|
+
import type { DemoPace, HighlightStyleDefaults } from "../highlights.js";
|
|
4
5
|
import type { NavBlock } from "./blocks/nav.js";
|
|
5
6
|
import type { PageBlock } from "./blocks/page.js";
|
|
6
7
|
import type { AssertBlock, MethodBlock } from "./blocks/method.js";
|
|
@@ -12,8 +13,7 @@ type S = Checkpoint<"__start__">;
|
|
|
12
13
|
* import each other (Engine.map() builds a MapBuilder; MapBuilder.end() calls back into
|
|
13
14
|
* defineFlow) - a real cycle check:structure forbids. This type is how that's avoided.
|
|
14
15
|
*/
|
|
15
|
-
export type DefineFlowFn = (blocks: readonly [StartMarker, ...Block<any, any>[], EndMarker]) => Flow<any>;
|
|
16
|
-
/** Per-step options every `MapBuilder` step method (`.gotoPage()`/`.method()`/`.assert()`) takes. */
|
|
16
|
+
export type DefineFlowFn = (blocks: readonly [StartMarker, ...Block<any, any>[], EndMarker], options?: FlowOptions) => Flow<any>;
|
|
17
17
|
export interface MapStepOpts {
|
|
18
18
|
/**
|
|
19
19
|
* Fast-forward just this step, inline - no `.ffStart()/.ffEnd()` bracket needed. Consecutive
|
|
@@ -22,6 +22,12 @@ export interface MapStepOpts {
|
|
|
22
22
|
* @example map().gotoPage(NavLoginBlock, { ff: true }).method(FillUsernameBlock, { ff: true })
|
|
23
23
|
*/
|
|
24
24
|
ff?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Demo pace for just this step (`"blitz"` skips the typing animation and the pause after the action; `"fast"`, `"slow"`,
|
|
27
|
+
* or a number scale the narration gates). The map equivalent of `withBlockPace`, with no wrapper.
|
|
28
|
+
* @example map().method(SetBearerTokenBlock, { pace: "blitz" })
|
|
29
|
+
*/
|
|
30
|
+
pace?: DemoPace;
|
|
25
31
|
}
|
|
26
32
|
export interface MapBuilderOptions {
|
|
27
33
|
/**
|
|
@@ -31,6 +37,19 @@ export interface MapBuilderOptions {
|
|
|
31
37
|
* way; only the internal/external origin distinction is opt-in).
|
|
32
38
|
*/
|
|
33
39
|
homeOrigin?: string;
|
|
40
|
+
/** Fill missing `requires` keys from `registerMemStub` when the flow runs (what `withMemStub` did). */
|
|
41
|
+
memStub?: boolean;
|
|
42
|
+
/** Marks a flow that is supposed to throw, with the reason shown in the demo (what `withExpectedFailure` did). */
|
|
43
|
+
expectedFailure?: string;
|
|
44
|
+
/** Default demo pace for the whole flow (what `withDemoPace` did). */
|
|
45
|
+
demoPace?: DemoPace;
|
|
46
|
+
/** Default ring tone, size and weight for the whole flow (what `withHighlightStyle` did). */
|
|
47
|
+
highlightStyle?: HighlightStyleDefaults;
|
|
48
|
+
}
|
|
49
|
+
/** What `.flow()` takes for the sub-flow it runs inline. */
|
|
50
|
+
export interface MapFlowOpts {
|
|
51
|
+
/** Clear cookies and storage right before the sub-flow, e.g. to start a second user fresh (what `withSessionReset` + `chainFlow` did). */
|
|
52
|
+
reset?: boolean;
|
|
34
53
|
}
|
|
35
54
|
/**
|
|
36
55
|
* Fluent builder over {@link Engine.defineFlow} - see `map()`'s own doc
|
|
@@ -119,6 +138,12 @@ export declare class MapBuilder<Out extends Checkpoint<string>> {
|
|
|
119
138
|
method<NextOut extends Checkpoint<string>>(block: (MethodBlock<Out, NextOut> | EffectBlock<Out, NextOut>) & {
|
|
120
139
|
name: string;
|
|
121
140
|
}, opts?: MapStepOpts): MapBuilder<NextOut>;
|
|
141
|
+
/**
|
|
142
|
+
* Runs another flow's steps inline here, in the same page, browser and `mem`. This is how flows nest:
|
|
143
|
+
* `map().flow(loginFlow).flow(viewerFlow, { reset: true })`. With `{ reset: true }` cookies and storage are cleared
|
|
144
|
+
* right before the sub-flow's first step. Replaces `chainFlow` and `withSessionReset`.
|
|
145
|
+
*/
|
|
146
|
+
flow<NextOut extends Checkpoint<string>>(sub: Flow<NextOut>, opts?: MapFlowOpts): MapBuilder<NextOut>;
|
|
122
147
|
/**
|
|
123
148
|
* Branch: run everything added so far, then continue into whichever `routes[tag]` matches the
|
|
124
149
|
* resolved Checkpoint's tag - same page, same context, same mem. `routes` must cover every tag
|
|
@@ -166,6 +191,7 @@ export declare class MapBuilder<Out extends Checkpoint<string>> {
|
|
|
166
191
|
* left open at `.end()` closes silently; an EXPLICIT `.ffStart()` left open
|
|
167
192
|
* still throws - the author opened that one and needs to close it themselves.
|
|
168
193
|
*/
|
|
169
|
-
|
|
194
|
+
/** @param options @deprecated Pass flow settings to `map({ … })` instead. */
|
|
195
|
+
end(options?: FlowOptions): Flow<Out>;
|
|
170
196
|
}
|
|
171
197
|
export {};
|
package/dist/core/map-builder.js
CHANGED
|
@@ -2,6 +2,30 @@ import { WaygraphError, MSG_MAP_WRONG_KIND, MSG_MAP_WRONG_SALT, MSG_MAP_WRONG_OR
|
|
|
2
2
|
import { end, start } from "./run-graph.js";
|
|
3
3
|
import { MemPage } from "../mem-page.js";
|
|
4
4
|
import { fastForwardComposeBlock } from "./compose.js";
|
|
5
|
+
import { clearSessionState, withBlockPace } from "./flow.js";
|
|
6
|
+
import { copyWaygraphRuntime } from "./block.js";
|
|
7
|
+
/** Per-step options every `MapBuilder` step method (`.gotoPage()`/`.method()`/`.assert()`) takes. */
|
|
8
|
+
/** The same Block, but it clears cookies and storage before it acts. Keeps the runtime markers. */
|
|
9
|
+
function resetBefore(block) {
|
|
10
|
+
const act = block.instruction.act.bind(block.instruction);
|
|
11
|
+
const next = {
|
|
12
|
+
...block,
|
|
13
|
+
instruction: {
|
|
14
|
+
...block.instruction,
|
|
15
|
+
async act(page, input, mem) {
|
|
16
|
+
await clearSessionState(page.context(), page);
|
|
17
|
+
return act(page, input, mem);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
copyWaygraphRuntime(block, next);
|
|
22
|
+
Object.defineProperty(next, "__waygraphResetBefore", { value: true, enumerable: false, configurable: true });
|
|
23
|
+
return next;
|
|
24
|
+
}
|
|
25
|
+
/** Applies a step's `pace` option, keeping the Block's runtime markers. */
|
|
26
|
+
function paced(block, opts) {
|
|
27
|
+
return (opts?.pace === undefined ? block : withBlockPace(block, opts.pace));
|
|
28
|
+
}
|
|
5
29
|
function mapKindOf(block) {
|
|
6
30
|
return block?.__waygraphKind;
|
|
7
31
|
}
|
|
@@ -237,7 +261,7 @@ export class MapBuilder {
|
|
|
237
261
|
gotoPage(block, opts) {
|
|
238
262
|
assertMapKind(block, ["nav", "page"], "gotoPage");
|
|
239
263
|
assertMapOrigin(block, this.homeOrigin, "internal", "gotoPage");
|
|
240
|
-
return this.appendStep(block, opts?.ff);
|
|
264
|
+
return this.appendStep(paced(block, opts), opts?.ff);
|
|
241
265
|
}
|
|
242
266
|
/**
|
|
243
267
|
* Appends a genuinely cross-origin navigation step (e.g. `(external)/`
|
|
@@ -249,7 +273,7 @@ export class MapBuilder {
|
|
|
249
273
|
gotoExternal(block, opts) {
|
|
250
274
|
assertMapKind(block, ["nav", "page"], "gotoExternal");
|
|
251
275
|
assertMapOrigin(block, this.homeOrigin, "external", "gotoExternal");
|
|
252
|
-
return this.appendStep(block, opts?.ff);
|
|
276
|
+
return this.appendStep(paced(block, opts), opts?.ff);
|
|
253
277
|
}
|
|
254
278
|
/**
|
|
255
279
|
* Appends a self-loop verification step - requires a Block from
|
|
@@ -258,7 +282,7 @@ export class MapBuilder {
|
|
|
258
282
|
*/
|
|
259
283
|
assert(block, opts) {
|
|
260
284
|
assertMapKind(block, ["assert"], "assert");
|
|
261
|
-
return this.appendStep(block, opts?.ff);
|
|
285
|
+
return this.appendStep(paced(block, opts), opts?.ff);
|
|
262
286
|
}
|
|
263
287
|
/**
|
|
264
288
|
* Appends a non-navigating page action (submit, upload, add/remove an
|
|
@@ -274,7 +298,20 @@ export class MapBuilder {
|
|
|
274
298
|
throw new WaygraphError("WG_MAP_WRONG_KIND", MSG_MAP_METHOD_GOT_ASSERT(block.name));
|
|
275
299
|
}
|
|
276
300
|
assertMapSalt(block, ["method", "effect"], "method");
|
|
277
|
-
return this.appendStep(block, opts?.ff);
|
|
301
|
+
return this.appendStep(paced(block, opts), opts?.ff);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Runs another flow's steps inline here, in the same page, browser and `mem`. This is how flows nest:
|
|
305
|
+
* `map().flow(loginFlow).flow(viewerFlow, { reset: true })`. With `{ reset: true }` cookies and storage are cleared
|
|
306
|
+
* right before the sub-flow's first step. Replaces `chainFlow` and `withSessionReset`.
|
|
307
|
+
*/
|
|
308
|
+
flow(sub, opts) {
|
|
309
|
+
let next = this;
|
|
310
|
+
sub.blocks().forEach((info, i) => {
|
|
311
|
+
const block = i === 0 && opts?.reset ? resetBefore(info.block) : info.block;
|
|
312
|
+
next = next.appendStep(block);
|
|
313
|
+
});
|
|
314
|
+
return next;
|
|
278
315
|
}
|
|
279
316
|
/**
|
|
280
317
|
* Branch: run everything added so far, then continue into whichever `routes[tag]` matches the
|
|
@@ -329,17 +366,18 @@ export class MapBuilder {
|
|
|
329
366
|
* left open at `.end()` closes silently; an EXPLICIT `.ffStart()` left open
|
|
330
367
|
* still throws - the author opened that one and needs to close it themselves.
|
|
331
368
|
*/
|
|
332
|
-
|
|
369
|
+
/** @param options @deprecated Pass flow settings to `map({ … })` instead. */
|
|
370
|
+
end(options) {
|
|
333
371
|
if (this.ff && !this.ff.auto) {
|
|
334
372
|
throw new WaygraphError("WG_MAP_FF_NOT_CLOSED", MSG_MAP_FF_NOT_CLOSED(this.ff.name));
|
|
335
373
|
}
|
|
336
374
|
if (this.ff && this.ff.auto) {
|
|
337
|
-
return this.closeFf().end();
|
|
375
|
+
return this.closeFf().end(options);
|
|
338
376
|
}
|
|
339
377
|
if (this.steps.length === 0) {
|
|
340
378
|
throw new WaygraphError("WG_MAP_EMPTY", MSG_MAP_EMPTY);
|
|
341
379
|
}
|
|
342
380
|
const chain = [start, ...this.steps, end];
|
|
343
|
-
return this.defineFlow(chain);
|
|
381
|
+
return this.defineFlow(chain, options);
|
|
344
382
|
}
|
|
345
383
|
}
|
package/dist/env-file.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
/** The env mode: `--env <mode>` / `WAYGRAPH_ENV`, else `NODE_ENV`, else "development". */
|
|
2
|
+
export declare function envMode(): string;
|
|
3
|
+
/** Removes `--env <mode>` / `--env=<mode>` from argv and records it as `WAYGRAPH_ENV`, so it never reaches a forwarded command. */
|
|
4
|
+
export declare function takeEnvFlag(argv: string[]): string[];
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* whatever the shell actually exported - always wins over every file; a `.env` file only fills
|
|
6
|
-
* a gap, it never silently overrides something the caller explicitly set. Safe to call more
|
|
7
|
-
* than once (e.g. once eagerly at `cwd`, again once the real project dir is known) - loading
|
|
8
|
-
* twice is a no-op the second time for any key already filled.
|
|
6
|
+
* Loads `.env` / `.env.local` / `.env.<mode>` / `.env.<mode>.local` from a project's root, the layering
|
|
7
|
+
* Vite and Next use: each later file overrides the earlier ones (`.env.<mode>.local` wins). A value the
|
|
8
|
+
* shell already exported always beats every file, so a file only fills gaps. Calling it twice is harmless.
|
|
9
9
|
*/
|
|
10
10
|
export declare function loadEnvFiles(projectDir: string, mode?: string): void;
|