screencast-axi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +555 -0
  3. package/dist/bin/screencast-axi.d.ts +2 -0
  4. package/dist/bin/screencast-axi.js +16 -0
  5. package/dist/bin/screencast-axi.js.map +1 -0
  6. package/dist/src/auth/strategies.d.ts +54 -0
  7. package/dist/src/auth/strategies.js +137 -0
  8. package/dist/src/auth/strategies.js.map +1 -0
  9. package/dist/src/auth/types.d.ts +65 -0
  10. package/dist/src/auth/types.js +2 -0
  11. package/dist/src/auth/types.js.map +1 -0
  12. package/dist/src/browser.d.ts +100 -0
  13. package/dist/src/browser.js +168 -0
  14. package/dist/src/browser.js.map +1 -0
  15. package/dist/src/cli.d.ts +2 -0
  16. package/dist/src/cli.js +160 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/commands/auth.d.ts +4 -0
  19. package/dist/src/commands/auth.js +207 -0
  20. package/dist/src/commands/auth.js.map +1 -0
  21. package/dist/src/commands/check.d.ts +12 -0
  22. package/dist/src/commands/check.js +103 -0
  23. package/dist/src/commands/check.js.map +1 -0
  24. package/dist/src/commands/doctor.d.ts +15 -0
  25. package/dist/src/commands/doctor.js +131 -0
  26. package/dist/src/commands/doctor.js.map +1 -0
  27. package/dist/src/commands/guide.d.ts +6 -0
  28. package/dist/src/commands/guide.js +257 -0
  29. package/dist/src/commands/guide.js.map +1 -0
  30. package/dist/src/commands/home.d.ts +12 -0
  31. package/dist/src/commands/home.js +78 -0
  32. package/dist/src/commands/home.js.map +1 -0
  33. package/dist/src/commands/list.d.ts +6 -0
  34. package/dist/src/commands/list.js +128 -0
  35. package/dist/src/commands/list.js.map +1 -0
  36. package/dist/src/commands/record.d.ts +7 -0
  37. package/dist/src/commands/record.js +266 -0
  38. package/dist/src/commands/record.js.map +1 -0
  39. package/dist/src/commands/scaffold.d.ts +4 -0
  40. package/dist/src/commands/scaffold.js +122 -0
  41. package/dist/src/commands/scaffold.js.map +1 -0
  42. package/dist/src/commands/setup.d.ts +14 -0
  43. package/dist/src/commands/setup.js +137 -0
  44. package/dist/src/commands/setup.js.map +1 -0
  45. package/dist/src/config.d.ts +126 -0
  46. package/dist/src/config.js +275 -0
  47. package/dist/src/config.js.map +1 -0
  48. package/dist/src/director.d.ts +217 -0
  49. package/dist/src/director.js +415 -0
  50. package/dist/src/director.js.map +1 -0
  51. package/dist/src/duration.d.ts +33 -0
  52. package/dist/src/duration.js +68 -0
  53. package/dist/src/duration.js.map +1 -0
  54. package/dist/src/encode.d.ts +67 -0
  55. package/dist/src/encode.js +225 -0
  56. package/dist/src/encode.js.map +1 -0
  57. package/dist/src/errors.d.ts +19 -0
  58. package/dist/src/errors.js +27 -0
  59. package/dist/src/errors.js.map +1 -0
  60. package/dist/src/flags.d.ts +39 -0
  61. package/dist/src/flags.js +130 -0
  62. package/dist/src/flags.js.map +1 -0
  63. package/dist/src/forensics.d.ts +51 -0
  64. package/dist/src/forensics.js +107 -0
  65. package/dist/src/forensics.js.map +1 -0
  66. package/dist/src/hooks.d.ts +9 -0
  67. package/dist/src/hooks.js +20 -0
  68. package/dist/src/hooks.js.map +1 -0
  69. package/dist/src/index.d.ts +18 -0
  70. package/dist/src/index.js +18 -0
  71. package/dist/src/index.js.map +1 -0
  72. package/dist/src/inventory.d.ts +45 -0
  73. package/dist/src/inventory.js +89 -0
  74. package/dist/src/inventory.js.map +1 -0
  75. package/dist/src/manifest.d.ts +89 -0
  76. package/dist/src/manifest.js +137 -0
  77. package/dist/src/manifest.js.map +1 -0
  78. package/dist/src/output.d.ts +8 -0
  79. package/dist/src/output.js +2 -0
  80. package/dist/src/output.js.map +1 -0
  81. package/dist/src/overlay.d.ts +105 -0
  82. package/dist/src/overlay.js +302 -0
  83. package/dist/src/overlay.js.map +1 -0
  84. package/dist/src/reference.d.ts +1 -0
  85. package/dist/src/reference.js +108 -0
  86. package/dist/src/reference.js.map +1 -0
  87. package/dist/src/run.d.ts +82 -0
  88. package/dist/src/run.js +321 -0
  89. package/dist/src/run.js.map +1 -0
  90. package/dist/src/skill.d.ts +12 -0
  91. package/dist/src/skill.js +69 -0
  92. package/dist/src/skill.js.map +1 -0
  93. package/dist/src/toolchain.d.ts +62 -0
  94. package/dist/src/toolchain.js +127 -0
  95. package/dist/src/toolchain.js.map +1 -0
  96. package/dist/src/types.d.ts +88 -0
  97. package/dist/src/types.js +18 -0
  98. package/dist/src/types.js.map +1 -0
  99. package/dist/src/version.d.ts +10 -0
  100. package/dist/src/version.js +11 -0
  101. package/dist/src/version.js.map +1 -0
  102. package/package.json +93 -0
  103. package/skills/screencast-axi/SKILL.md +49 -0
@@ -0,0 +1,126 @@
1
+ import { type EncodeSettings } from "./encode.js";
2
+ import { type DeepPartial, type OverlayTheme } from "./overlay.js";
3
+ import { type DefinedScenario, type Viewport } from "./types.js";
4
+ import type { AuthConfig, AuthStrategy } from "./auth/types.js";
5
+ /**
6
+ * Configuration, and finding the scenarios.
7
+ *
8
+ * A config file is the scale-up path, not the entry fee: `record ./clip.ts`
9
+ * works with no config at all, on defaults rooted at the current directory.
10
+ * Someone recording one page of a site they do not own should not have to
11
+ * learn a config format first.
12
+ */
13
+ export interface BrowserConfig {
14
+ readonly headless: boolean;
15
+ /**
16
+ * Persistent Chrome profile directory.
17
+ *
18
+ * Present means a warm profile, so a session a human signed into by hand
19
+ * survives between takes. Absent means an isolated context per take.
20
+ */
21
+ readonly profileDir?: string;
22
+ /** Overrides a device preset's own scale factor. Rarely wanted. */
23
+ readonly deviceScaleFactor?: number;
24
+ readonly args: readonly string[];
25
+ readonly colorScheme?: "light" | "dark";
26
+ readonly locale?: string;
27
+ readonly timezoneId?: string;
28
+ }
29
+ export interface ScreencastConfig {
30
+ readonly outDir?: string;
31
+ readonly rawDir?: string;
32
+ /** File paths, directories, or `dir/*.ts` patterns. */
33
+ readonly scenarios?: readonly string[];
34
+ readonly baseUrl?: string;
35
+ readonly viewport?: Viewport;
36
+ readonly device?: string;
37
+ readonly pace?: number;
38
+ readonly deliverables?: Partial<EncodeSettings>;
39
+ readonly browser?: Partial<BrowserConfig>;
40
+ readonly overlay?: DeepPartial<OverlayTheme>;
41
+ /** One strategy, or several by name for `--auth <name>`. */
42
+ readonly auth?: AuthConfig;
43
+ readonly timeouts?: {
44
+ readonly setupMs?: number;
45
+ readonly runMs?: number;
46
+ /** Per-action timeout during a rehearsal. Deliberately short. */
47
+ readonly rehearseMs?: number;
48
+ /** Ceiling on how long `goto` waits for the network to go quiet. */
49
+ readonly settleMs?: number;
50
+ };
51
+ }
52
+ export interface ResolvedConfig {
53
+ /** Directory every relative path in the config resolves against. */
54
+ readonly rootDir: string;
55
+ /** Absolute path of the config file, or null when running without one. */
56
+ readonly configPath: string | null;
57
+ readonly outDir: string;
58
+ readonly rawDir: string;
59
+ readonly scenarios: readonly string[];
60
+ readonly baseUrl: string;
61
+ readonly viewport: Viewport;
62
+ readonly device?: string;
63
+ readonly pace: number;
64
+ readonly deliverables: EncodeSettings;
65
+ readonly browser: BrowserConfig;
66
+ readonly overlay: DeepPartial<OverlayTheme>;
67
+ readonly auth: Readonly<Record<string, AuthStrategy>>;
68
+ readonly timeouts: {
69
+ readonly setupMs: number;
70
+ readonly runMs: number;
71
+ readonly rehearseMs: number;
72
+ readonly settleMs: number;
73
+ };
74
+ }
75
+ export declare const CONFIG_BASENAMES: readonly ["screencast.config.ts", "screencast.config.mts", "screencast.config.js", "screencast.config.mjs"];
76
+ /**
77
+ * Chromium flags that make a capture look deliberate rather than incidental:
78
+ * no scrollbars in frame, sRGB so colours match the design, and no font
79
+ * hinting so text renders the same on every machine that reshoots.
80
+ */
81
+ export declare const DEFAULT_BROWSER_ARGS: readonly ["--hide-scrollbars", "--force-color-profile=srgb", "--font-render-hinting=none"];
82
+ /** Identity function, for the types and the editor completion. */
83
+ export declare function defineConfig(config: ScreencastConfig): ScreencastConfig;
84
+ /** Walks up from `startDir` looking for a config file. */
85
+ export declare function findConfigPath(startDir: string): string | null;
86
+ export declare function resolveConfigPath(explicit?: string, cwd?: string): string | null;
87
+ export declare function loadConfig(explicit?: string, cwd?: string): Promise<ResolvedConfig>;
88
+ export declare function resolveConfig(raw: ScreencastConfig, configPath: string | null, cwd?: string): ResolvedConfig;
89
+ /**
90
+ * Expands one `scenarios` entry to concrete files.
91
+ *
92
+ * Supports a file path, a directory, `dir/*.ts` and `dir/**` - which is the
93
+ * whole realistic range. A full glob library would be a dependency bought for
94
+ * patterns nobody writes here.
95
+ */
96
+ export declare function expandScenarioPattern(pattern: string, rootDir: string): string[];
97
+ export interface LoadedScenario {
98
+ readonly scenario: DefinedScenario;
99
+ /** Absolute path of the module it came from, for error messages. */
100
+ readonly file: string;
101
+ }
102
+ /**
103
+ * Loads every scenario the config points at, in declaration order.
104
+ *
105
+ * A module may export its scenario as `default`, as a named export, or several
106
+ * at once: the `defineScenario` stamp is what makes it findable, so nobody has
107
+ * to remember a naming convention.
108
+ */
109
+ export declare function loadScenarios(config: ResolvedConfig): Promise<LoadedScenario[]>;
110
+ export declare function loadScenarioFiles(files: readonly string[]): Promise<LoadedScenario[]>;
111
+ /**
112
+ * Normalises the config's `auth` into a name -> strategy map.
113
+ *
114
+ * A single strategy becomes `{ default: it }`, so a scenario saying
115
+ * `auth: true` or nothing at all resolves without the config author having to
116
+ * name anything.
117
+ */
118
+ export declare function normaliseAuth(auth: AuthConfig | undefined): Record<string, AuthStrategy>;
119
+ /**
120
+ * Picks the strategy for a take.
121
+ *
122
+ * `false` on a scenario, or `--no-auth`, means signed out - a deliberate
123
+ * choice worth being able to make per scenario, since a landing page and a
124
+ * dashboard often live in the same config.
125
+ */
126
+ export declare function selectStrategy(config: ResolvedConfig, scenarioAuth: string | false | undefined, override?: string | false): AuthStrategy | null;
@@ -0,0 +1,275 @@
1
+ import { ScreencastError } from "./errors.js";
2
+ import { existsSync, readdirSync, statSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { DEFAULT_ENCODE_SETTINGS } from "./encode.js";
6
+ import { DEFAULT_SETTLE_MS } from "./director.js";
7
+ import { DEFAULT_OVERLAY_THEME } from "./overlay.js";
8
+ import { isScenario } from "./types.js";
9
+ import { noAuth } from "./auth/strategies.js";
10
+ export const CONFIG_BASENAMES = [
11
+ "screencast.config.ts",
12
+ "screencast.config.mts",
13
+ "screencast.config.js",
14
+ "screencast.config.mjs",
15
+ ];
16
+ const DEFAULT_VIEWPORT = { width: 1600, height: 1000 };
17
+ /**
18
+ * Chromium flags that make a capture look deliberate rather than incidental:
19
+ * no scrollbars in frame, sRGB so colours match the design, and no font
20
+ * hinting so text renders the same on every machine that reshoots.
21
+ */
22
+ export const DEFAULT_BROWSER_ARGS = [
23
+ "--hide-scrollbars",
24
+ "--force-color-profile=srgb",
25
+ "--font-render-hinting=none",
26
+ ];
27
+ /** Identity function, for the types and the editor completion. */
28
+ export function defineConfig(config) {
29
+ return config;
30
+ }
31
+ /** Walks up from `startDir` looking for a config file. */
32
+ export function findConfigPath(startDir) {
33
+ let dir = resolve(startDir);
34
+ for (;;) {
35
+ for (const name of CONFIG_BASENAMES) {
36
+ const candidate = join(dir, name);
37
+ if (existsSync(candidate))
38
+ return candidate;
39
+ }
40
+ const parent = dirname(dir);
41
+ if (parent === dir)
42
+ return null;
43
+ dir = parent;
44
+ }
45
+ }
46
+ export function resolveConfigPath(explicit, cwd = process.cwd()) {
47
+ const chosen = explicit ?? process.env["SCREENCAST_CONFIG"];
48
+ if (chosen) {
49
+ const absolute = isAbsolute(chosen) ? chosen : resolve(cwd, chosen);
50
+ if (!existsSync(absolute)) {
51
+ throw new ScreencastError(`Config not found: ${absolute}`, "CONFIG_NOT_FOUND", [
52
+ "Pass `--config <path>` pointing at an existing file",
53
+ "Or drop the flag to search upwards from the current directory",
54
+ ]);
55
+ }
56
+ return absolute;
57
+ }
58
+ return findConfigPath(cwd);
59
+ }
60
+ /**
61
+ * Imports a module, registering `tsx` first if Node cannot load TypeScript.
62
+ *
63
+ * The package does not own transpilation. Node's own type stripping does not
64
+ * resolve tsconfig path aliases, which real scenarios use to reach a project's
65
+ * own code, so `tsx` is the documented way and an optional peer.
66
+ */
67
+ let tsxRegistered = false;
68
+ async function importModule(file) {
69
+ const url = pathToFileURL(file).href;
70
+ try {
71
+ return (await import(url));
72
+ }
73
+ catch (error) {
74
+ const code = error.code;
75
+ const needsLoader = code === "ERR_UNKNOWN_FILE_EXTENSION" ||
76
+ (error instanceof SyntaxError && /\.m?ts$/.test(file));
77
+ if (!needsLoader || tsxRegistered)
78
+ throw error;
79
+ try {
80
+ const specifier = "tsx/esm/api";
81
+ const tsx = (await import(specifier));
82
+ tsx.register?.();
83
+ tsxRegistered = true;
84
+ }
85
+ catch {
86
+ throw new ScreencastError(`Cannot load ${file}: this Node cannot run TypeScript directly`, "TS_LOADER_MISSING", ["Install the loader: `pnpm add -D tsx`", "Or write the file as .mjs instead of .ts"]);
87
+ }
88
+ // Cache-bust so the retry does not get the failed module record back.
89
+ return (await import(`${url}?tsx=1`));
90
+ }
91
+ }
92
+ export async function loadConfig(explicit, cwd = process.cwd()) {
93
+ const configPath = resolveConfigPath(explicit, cwd);
94
+ const raw = configPath
95
+ ? ((await importModule(configPath))["default"] ?? {})
96
+ : {};
97
+ return resolveConfig(raw, configPath, cwd);
98
+ }
99
+ export function resolveConfig(raw, configPath, cwd = process.cwd()) {
100
+ // Relative paths anchor to the config file, never to the shell's cwd -
101
+ // otherwise the same command means different things from different
102
+ // directories in the same repo.
103
+ const rootDir = configPath ? dirname(configPath) : resolve(cwd);
104
+ const at = (p) => (isAbsolute(p) ? p : resolve(rootDir, p));
105
+ const browser = {
106
+ headless: raw.browser?.headless ?? true,
107
+ ...(raw.browser?.profileDir ? { profileDir: at(raw.browser.profileDir) } : {}),
108
+ // No default: a device preset carries its own (2-3 on phones), and a
109
+ // config-level default of 1 would silently override it and throw away the
110
+ // detail that makes a phone clip readable.
111
+ ...(raw.browser?.deviceScaleFactor !== undefined
112
+ ? { deviceScaleFactor: raw.browser.deviceScaleFactor }
113
+ : {}),
114
+ args: raw.browser?.args ?? DEFAULT_BROWSER_ARGS,
115
+ ...(raw.browser?.colorScheme ? { colorScheme: raw.browser.colorScheme } : {}),
116
+ ...(raw.browser?.locale ? { locale: raw.browser.locale } : {}),
117
+ ...(raw.browser?.timezoneId ? { timezoneId: raw.browser.timezoneId } : {}),
118
+ };
119
+ return {
120
+ rootDir,
121
+ configPath,
122
+ outDir: at(raw.outDir ?? "screencasts"),
123
+ rawDir: at(raw.rawDir ?? ".screencast/raw"),
124
+ scenarios: raw.scenarios ?? [],
125
+ baseUrl: raw.baseUrl ?? "http://localhost:3000",
126
+ viewport: raw.viewport ?? DEFAULT_VIEWPORT,
127
+ ...(raw.device ? { device: raw.device } : {}),
128
+ pace: raw.pace ?? 1,
129
+ deliverables: { ...DEFAULT_ENCODE_SETTINGS, ...raw.deliverables },
130
+ browser,
131
+ overlay: { ...DEFAULT_OVERLAY_THEME, ...raw.overlay },
132
+ auth: normaliseAuth(raw.auth),
133
+ timeouts: {
134
+ setupMs: raw.timeouts?.setupMs ?? 120_000,
135
+ runMs: raw.timeouts?.runMs ?? 300_000,
136
+ rehearseMs: raw.timeouts?.rehearseMs ?? 8_000,
137
+ settleMs: raw.timeouts?.settleMs ?? DEFAULT_SETTLE_MS,
138
+ },
139
+ };
140
+ }
141
+ const SCENARIO_EXTENSIONS = [".ts", ".mts", ".js", ".mjs"];
142
+ function isScenarioFile(file) {
143
+ return SCENARIO_EXTENSIONS.some((ext) => file.endsWith(ext)) && !file.endsWith(".d.ts");
144
+ }
145
+ function walk(dir, recursive) {
146
+ const found = [];
147
+ for (const name of readdirSync(dir).sort()) {
148
+ const full = join(dir, name);
149
+ const stats = statSync(full);
150
+ if (stats.isDirectory()) {
151
+ if (recursive)
152
+ found.push(...walk(full, true));
153
+ }
154
+ else if (isScenarioFile(name)) {
155
+ found.push(full);
156
+ }
157
+ }
158
+ return found;
159
+ }
160
+ /**
161
+ * Expands one `scenarios` entry to concrete files.
162
+ *
163
+ * Supports a file path, a directory, `dir/*.ts` and `dir/**` - which is the
164
+ * whole realistic range. A full glob library would be a dependency bought for
165
+ * patterns nobody writes here.
166
+ */
167
+ export function expandScenarioPattern(pattern, rootDir) {
168
+ const absolute = isAbsolute(pattern) ? pattern : join(rootDir, pattern);
169
+ if (!absolute.includes("*")) {
170
+ if (!existsSync(absolute))
171
+ return [];
172
+ return statSync(absolute).isDirectory() ? walk(absolute, false) : [absolute];
173
+ }
174
+ const star = absolute.indexOf("*");
175
+ const base = absolute.slice(0, star);
176
+ const dir = base.endsWith(sep) ? base.slice(0, -1) : dirname(base);
177
+ if (!existsSync(dir))
178
+ return [];
179
+ const recursive = absolute.includes("**");
180
+ const suffix = absolute.slice(absolute.lastIndexOf("*") + 1);
181
+ return walk(dir, recursive).filter((f) => (suffix ? f.endsWith(suffix) : true));
182
+ }
183
+ /**
184
+ * Loads every scenario the config points at, in declaration order.
185
+ *
186
+ * A module may export its scenario as `default`, as a named export, or several
187
+ * at once: the `defineScenario` stamp is what makes it findable, so nobody has
188
+ * to remember a naming convention.
189
+ */
190
+ export async function loadScenarios(config) {
191
+ const files = [];
192
+ for (const pattern of config.scenarios) {
193
+ for (const file of expandScenarioPattern(pattern, config.rootDir)) {
194
+ if (!files.includes(file))
195
+ files.push(file);
196
+ }
197
+ }
198
+ return loadScenarioFiles(files);
199
+ }
200
+ export async function loadScenarioFiles(files) {
201
+ const loaded = [];
202
+ const seen = new Map();
203
+ for (const file of files) {
204
+ const module = await importModule(file);
205
+ const found = Object.values(module).filter(isScenario);
206
+ if (found.length === 0) {
207
+ throw new ScreencastError(`No scenario exported by ${file}`, "NO_SCENARIO", [
208
+ "Wrap the object: `export default defineScenario({ ... })`",
209
+ "`defineScenario` is imported from `screencast-axi`",
210
+ ]);
211
+ }
212
+ for (const scenario of found) {
213
+ const previous = seen.get(scenario.id);
214
+ if (previous) {
215
+ // Two clips writing the same file stem would silently overwrite each
216
+ // other, and whichever ran last would win.
217
+ throw new ScreencastError(`Duplicate scenario id \`${scenario.id}\``, "DUPLICATE_SCENARIO", [
218
+ `Defined in ${relative(process.cwd(), previous)} and ${relative(process.cwd(), file)}`,
219
+ "Ids are the output file stem, so they have to be unique",
220
+ ]);
221
+ }
222
+ seen.set(scenario.id, file);
223
+ loaded.push({ scenario, file });
224
+ }
225
+ }
226
+ return loaded;
227
+ }
228
+ /**
229
+ * Normalises the config's `auth` into a name -> strategy map.
230
+ *
231
+ * A single strategy becomes `{ default: it }`, so a scenario saying
232
+ * `auth: true` or nothing at all resolves without the config author having to
233
+ * name anything.
234
+ */
235
+ export function normaliseAuth(auth) {
236
+ if (!auth)
237
+ return { none: noAuth() };
238
+ if (typeof auth.name === "string") {
239
+ return { default: auth };
240
+ }
241
+ return auth;
242
+ }
243
+ /**
244
+ * Picks the strategy for a take.
245
+ *
246
+ * `false` on a scenario, or `--no-auth`, means signed out - a deliberate
247
+ * choice worth being able to make per scenario, since a landing page and a
248
+ * dashboard often live in the same config.
249
+ */
250
+ export function selectStrategy(config, scenarioAuth, override) {
251
+ const chosen = override !== undefined ? override : scenarioAuth;
252
+ if (chosen === false)
253
+ return null;
254
+ const names = Object.keys(config.auth);
255
+ if (chosen === undefined) {
256
+ // Only a strategy the config supplied on its own - `auth: profileAuth()`,
257
+ // normalised to `default` - applies without being asked for. A named map
258
+ // never does, even when it holds exactly one entry: otherwise adding a
259
+ // second name would silently change what every unmarked scenario does, and
260
+ // a config with one login would quietly sign every take into it.
261
+ const strategy = config.auth["default"];
262
+ return !strategy || strategy.name === "none" ? null : strategy;
263
+ }
264
+ const strategy = config.auth[chosen];
265
+ if (!strategy) {
266
+ throw new ScreencastError(`Unknown auth strategy: ${chosen}`, "UNKNOWN_AUTH", [
267
+ names.length > 0
268
+ ? `This config defines: ${names.join(", ")}`
269
+ : "No auth strategies are configured. Add one under `auth` in screencast.config.ts",
270
+ "Use `--no-auth` to record signed out",
271
+ ]);
272
+ }
273
+ return strategy.name === "none" ? null : strategy;
274
+ }
275
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAuB,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAuC,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAuC,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AA6E9C,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,sBAAsB;IACtB,uBAAuB;IACvB,sBAAsB;IACtB,uBAAuB;CACf,CAAC;AAEX,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAEjE;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,mBAAmB;IACnB,4BAA4B;IAC5B,4BAA4B;CACpB,CAAC;AAEX,kEAAkE;AAClE,MAAM,UAAU,YAAY,CAAC,MAAwB;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,IAAI,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,SAAS,CAAC;QACR,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAClC,IAAI,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;QAC9C,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACtE,MAAM,MAAM,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC5D,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACpE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,qBAAqB,QAAQ,EAAE,EAAE,kBAAkB,EAAE;gBAC7E,qDAAqD;gBACrD,+DAA+D;aAChE,CAAC,CAAC;QACL,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,IAAI,aAAa,GAAG,KAAK,CAAC;AAC1B,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAA4B,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI,CAAC;QAC/C,MAAM,WAAW,GACf,IAAI,KAAK,4BAA4B;YACrC,CAAC,KAAK,YAAY,WAAW,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,WAAW,IAAI,aAAa;YAAE,MAAM,KAAK,CAAC;QAE/C,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,aAAa,CAAC;YAChC,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAA8B,CAAC;YACnE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;YACjB,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,eAAe,CACvB,eAAe,IAAI,4CAA4C,EAC/D,mBAAmB,EACnB,CAAC,uCAAuC,EAAE,0CAA0C,CAAC,CACtF,CAAC;QACJ,CAAC;QACD,sEAAsE;QACtE,OAAO,CAAC,MAAM,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,CAA4B,CAAC;IACnE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACrE,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAqB,UAAU;QACtC,CAAC,CAAC,CAAE,CAAC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAsB,IAAI,EAAE,CAAC;QAC3E,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAqB,EACrB,UAAyB,EACzB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,uEAAuE;IACvE,mEAAmE;IACnE,gCAAgC;IAChC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAEpE,MAAM,OAAO,GAAkB;QAC7B,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,IAAI,IAAI;QACvC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,qEAAqE;QACrE,0EAA0E;QAC1E,2CAA2C;QAC3C,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,SAAS;YAC9C,CAAC,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,oBAAoB;QAC/C,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;IAEF,OAAO;QACL,OAAO;QACP,UAAU;QACV,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,aAAa,CAAC;QACvC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,iBAAiB,CAAC;QAC3C,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;QAC9B,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,uBAAuB;QAC/C,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,gBAAgB;QAC1C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;QACnB,YAAY,EAAE,EAAE,GAAG,uBAAuB,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE;QACjE,OAAO;QACP,OAAO,EAAE,EAAE,GAAG,qBAAqB,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;QACrD,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,QAAQ,EAAE;YACR,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,IAAI,OAAO;YACzC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,IAAI,OAAO;YACrC,UAAU,EAAE,GAAG,CAAC,QAAQ,EAAE,UAAU,IAAI,KAAK;YAC7C,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,QAAQ,IAAI,iBAAiB;SACtD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAE3D,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,SAAkB;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACjD,CAAC;aAAM,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe,EAAE,OAAe;IACpE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAExE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEhC,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClF,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAsB;IACxD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAClE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAwB;IAC9D,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAEvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,eAAe,CAAC,2BAA2B,IAAI,EAAE,EAAE,aAAa,EAAE;gBAC1E,2DAA2D;gBAC3D,oDAAoD;aACrD,CAAC,CAAC;QACL,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACvC,IAAI,QAAQ,EAAE,CAAC;gBACb,qEAAqE;gBACrE,2CAA2C;gBAC3C,MAAM,IAAI,eAAe,CACvB,2BAA2B,QAAQ,CAAC,EAAE,IAAI,EAC1C,oBAAoB,EACpB;oBACE,cAAc,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,QAAQ,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE;oBACtF,yDAAyD;iBAC1D,CACF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAA4B;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACrC,IAAI,OAAQ,IAAqB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,EAAE,OAAO,EAAE,IAAoB,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,IAAoC,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAsB,EACtB,YAAwC,EACxC,QAAyB;IAEzB,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;IAChE,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,0EAA0E;QAC1E,yEAAyE;QACzE,uEAAuE;QACvE,2EAA2E;QAC3E,iEAAiE;QACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IACjE,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,eAAe,CAAC,0BAA0B,MAAM,EAAE,EAAE,cAAc,EAAE;YAC5E,KAAK,CAAC,MAAM,GAAG,CAAC;gBACd,CAAC,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC5C,CAAC,CAAC,iFAAiF;YACrF,sCAAsC;SACvC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpD,CAAC"}
@@ -0,0 +1,217 @@
1
+ import type { Locator, Page } from "playwright";
2
+ import type { Target } from "./types.js";
3
+ export interface DirectorOptions {
4
+ /** Base URL used to resolve relative paths passed to `goto`. */
5
+ readonly baseUrl: string;
6
+ /**
7
+ * Playback speed multiplier applied to every pause and tween. 1 = natural
8
+ * demo pace, 0.5 = twice as fast. Kept as a knob because the right pace
9
+ * differs between a 6-second GIF and a 30-second explainer.
10
+ */
11
+ readonly pace: number;
12
+ /** The scenario's narration script, addressed by index from `step()`. */
13
+ readonly steps?: readonly string[];
14
+ /**
15
+ * How long {@link Director.goto} will wait for the network to go quiet.
16
+ *
17
+ * Settling is an optimisation - start acting once the page has stopped
18
+ * moving - not a requirement, and it has to be bounded because plenty of
19
+ * real sites never go quiet at all. GitHub does not: analytics, websockets
20
+ * and polling keep at least one request in flight forever. Waiting on the
21
+ * default timeout there put up to 30 seconds of dead air *inside the clip*,
22
+ * silently, because the failure is caught and ignored.
23
+ */
24
+ readonly settleMs?: number;
25
+ }
26
+ /** One thing the scenario did, for the run to report afterwards. */
27
+ export interface DirectorAction {
28
+ /** Milliseconds since the Director was created. */
29
+ readonly atMs: number;
30
+ readonly kind: "goto" | "click" | "doubleClick" | "type" | "press" | "drag" | "scroll" | "waitFor" | "step";
31
+ /** What it acted on, as written in the scenario. */
32
+ readonly target?: string;
33
+ /** Typed text, a key, a distance - whatever makes the line readable. */
34
+ readonly detail?: string;
35
+ }
36
+ /** Default ceiling on the post-navigation settle wait. */
37
+ export declare const DEFAULT_SETTLE_MS = 2500;
38
+ /** One stop on a {@link Director.tour}. */
39
+ export interface TourStop {
40
+ /** Path or absolute URL to open. */
41
+ readonly path: string;
42
+ /** Index into the scenario's `steps`. Preferred over `caption`. */
43
+ readonly step?: number;
44
+ /** Ad-hoc caption, for a tour whose narration is not in `steps`. */
45
+ readonly caption?: string;
46
+ /** Scroll after the caption lands: a fraction of the viewport, or pixels. */
47
+ readonly scroll?: number;
48
+ /** Override the shared dwell for this stop. */
49
+ readonly dwellMs?: number;
50
+ /** Wait for this before narrating, so a slow page does not get a jump cut. */
51
+ readonly waitFor?: Target;
52
+ }
53
+ /**
54
+ * The scenario-facing API. Every method is written so the resulting video is
55
+ * *watchable*: the pointer travels rather than teleports, clicks are preceded
56
+ * by a beat, and typing is per-character.
57
+ *
58
+ * Raw Playwright is still available via `director.page` for anything the
59
+ * helpers do not cover - but prefer adding a helper here over reaching past it,
60
+ * so all clips share one visual language.
61
+ */
62
+ export declare class Director {
63
+ readonly page: Page;
64
+ private readonly opts;
65
+ private readonly contextCreatedAt;
66
+ private pointer;
67
+ /** ms since the context was created, at the moment the clip proper began. */
68
+ private clipStartedAt;
69
+ /** Indices passed to {@link step}, in the order the take showed them. */
70
+ private readonly shown;
71
+ /**
72
+ * Milliseconds spent in pauses this class controls.
73
+ *
74
+ * A take is `fixed + pace x scalable`: the app's own waits - navigation, a
75
+ * network round trip, an animation - do not get slower because the recorder
76
+ * does. Tracking the scalable half is what lets `--duration` solve for a
77
+ * pace exactly rather than assuming the whole clip scales.
78
+ */
79
+ private pausedMs;
80
+ /**
81
+ * Everything the scenario did, in order.
82
+ *
83
+ * A scenario is arbitrary code driving a real browser, often a signed-in
84
+ * one, so "what will this actually do" is a fair question to want answered
85
+ * before trusting it. Watching a headed run answers it once; this answers it
86
+ * in a form that can be read, diffed and kept.
87
+ */
88
+ private readonly actions;
89
+ constructor(page: Page, opts: DirectorOptions, contextCreatedAt: number);
90
+ /** Seconds of dead air at the head of the raw video, for the encoder to trim. */
91
+ get trimStartSeconds(): number;
92
+ /** Marks the end of setup. Everything before this is trimmed off the clip. */
93
+ markClipStart(): void;
94
+ private scaled;
95
+ /** Pace-scaled pause. Every wait this class owns goes through here. */
96
+ private pause;
97
+ /** How much of the take so far was pause this class controls, in ms. */
98
+ get scaledPauseMs(): number;
99
+ /** Everything the scenario did, in order. */
100
+ get performed(): readonly DirectorAction[];
101
+ private record;
102
+ /** A deliberate pause so the viewer can read what just happened. */
103
+ beat(ms?: number): Promise<void>;
104
+ goto(path: string): Promise<void>;
105
+ /** Which script lines this take put on screen, in order. */
106
+ get shownSteps(): readonly number[];
107
+ /**
108
+ * Puts line `index` of the scenario's `steps` on screen.
109
+ *
110
+ * Scenarios narrate through this rather than through {@link caption} so the
111
+ * text has one home: the same array becomes the burnt-in caption, the
112
+ * manifest's step list and the text the landing page renders beside the clip.
113
+ * `record.ts` checks afterwards that the take used every line exactly once,
114
+ * in order, which is what stops the written workflow from drifting away from
115
+ * the recorded one.
116
+ */
117
+ step(index: number, holdMs?: number): Promise<void>;
118
+ /** Shows a caption at the bottom of the frame. Pass `null` to clear it. */
119
+ caption(text: string | null, holdMs?: number): Promise<void>;
120
+ locator(target: Target): Locator;
121
+ /** Whether this target is a field whose value should never be logged. */
122
+ private isSecret;
123
+ private pointOf;
124
+ /** Glides the pointer to `target` along an eased path. */
125
+ moveTo(target: Target, { steps }?: {
126
+ steps?: number;
127
+ }): Promise<void>;
128
+ private glide;
129
+ /** Move, settle, then click - the pause is what makes the click legible. */
130
+ click(target: Target, { settleMs }?: {
131
+ settleMs?: number;
132
+ }): Promise<void>;
133
+ /**
134
+ * The click itself, without logging it.
135
+ *
136
+ * `type` focuses its field by clicking it, which is one action from the
137
+ * scenario's point of view. Logging the inner click too would put a
138
+ * phantom step in the record of what the take did.
139
+ */
140
+ private performClick;
141
+ doubleClick(target: Target): Promise<void>;
142
+ /**
143
+ * Clicks the field, then types character by character. `clear` selects the
144
+ * existing value first, so typing replaces it instead of appending - what a
145
+ * person does to a field that already holds a default.
146
+ */
147
+ type(target: Target, text: string, { delay, clear }?: {
148
+ delay?: number;
149
+ clear?: boolean;
150
+ }): Promise<void>;
151
+ press(key: string): Promise<void>;
152
+ /**
153
+ * Press-move-release drag. Deliberately slow and eased: this is the shot the
154
+ * whole harness exists for (reordering a tree row, moving a kanban card), and
155
+ * a fast drag reads as a teleport once it is re-encoded at 30fps.
156
+ */
157
+ drag(from: Target, to: Target, { steps, liftMs, dropMs, }?: {
158
+ steps?: number;
159
+ liftMs?: number;
160
+ dropMs?: number;
161
+ }): Promise<void>;
162
+ /**
163
+ * Drag for the parts of the product that move things with the HTML5
164
+ * drag-and-drop API (`draggable` + `dragstart`/`dragover`/`drop`) rather than
165
+ * with raw pointer events: the process-mapper components palette, the kanban
166
+ * board.
167
+ *
168
+ * Chromium does not synthesise those events from `mouse.down`/`move`/`up`, so
169
+ * {@link drag} silently does nothing there. This dispatches the protocol
170
+ * itself - one `DataTransfer` shared by every event of the gesture, which is
171
+ * what carries the payload the source sets in `dragstart` to the drop
172
+ * handler - while still moving the real pointer, so the overlay cursor shows
173
+ * a hand carrying the thing across the screen.
174
+ *
175
+ * The mouse button is deliberately *not* pressed. A real `mouse.down` on a
176
+ * `draggable` element makes Chromium open its own native drag session, which
177
+ * then swallows every following `mousemove` - the overlay pointer freezes at
178
+ * the source and the clip shows a thing teleporting. Without the press the
179
+ * pointer travels normally, and `setDragging` puts a ghost chip under it so
180
+ * the gesture still reads as carrying something.
181
+ */
182
+ dragHtml5(from: Target, to: Target, { steps, liftMs, dropMs, }?: {
183
+ steps?: number;
184
+ liftMs?: number;
185
+ dropMs?: number;
186
+ }): Promise<void>;
187
+ private setDragging;
188
+ /**
189
+ * Dispatches one drag event at `at`, on whatever is under that point.
190
+ *
191
+ * `dragenter`/`dragleave` are kept in step with the element under the pointer
192
+ * because a drop zone that only arms itself on `dragenter` would otherwise
193
+ * never accept the drop. `drop` also ends the gesture with `dragend` on the
194
+ * source, which is where a well-behaved source cleans up its drag state.
195
+ */
196
+ private dndEvent;
197
+ /** Smooth wheel scroll, in the page or in whatever is under the pointer. */
198
+ scrollBy(deltaY: number, { steps }?: {
199
+ steps?: number;
200
+ }): Promise<void>;
201
+ waitFor(target: Target): Promise<void>;
202
+ /**
203
+ * A multi-page walkthrough: go somewhere, narrate it, let it breathe, move on.
204
+ *
205
+ * This is the shape most requests actually have ("a walkthrough of the five
206
+ * main pages"), and writing it by hand is fifty lines of goto/caption/scroll
207
+ * whose only real content is the paths. Going through one helper also keeps
208
+ * the rhythm identical between stops, which is most of what makes a tour
209
+ * watchable rather than a run of jump cuts.
210
+ *
211
+ * Every pause here is pace-scaled like any other, so `--duration` re-cuts a
212
+ * tour without the scenario changing.
213
+ */
214
+ tour(stops: readonly TourStop[], { dwellMs }?: {
215
+ dwellMs?: number;
216
+ }): Promise<void>;
217
+ }