prowl-tools 0.1.3

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.
@@ -0,0 +1,546 @@
1
+ // src/config/loader.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import yaml from "yaml";
5
+ import dotenv from "dotenv";
6
+
7
+ // src/config/schema.ts
8
+ import { z } from "zod";
9
+
10
+ // src/config/hunt-name.ts
11
+ var HUNT_NAME_PATTERN = /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*$/;
12
+ function isValidHuntName(name) {
13
+ return HUNT_NAME_PATTERN.test(name);
14
+ }
15
+ function assertValidHuntName(name) {
16
+ if (!isValidHuntName(name)) {
17
+ throw new Error(
18
+ `Invalid hunt name: "${name}". Use only letters, numbers, hyphens, underscores, and forward slashes.`
19
+ );
20
+ }
21
+ }
22
+
23
+ // src/config/schema.ts
24
+ var configSchema = z.object({
25
+ target: z.object({
26
+ url: z.string().min(1)
27
+ }),
28
+ browser: z.object({
29
+ headless: z.boolean().optional(),
30
+ slowMo: z.number().optional(),
31
+ timeout: z.number().optional(),
32
+ engine: z.enum(["chromium", "firefox", "webkit"]).optional(),
33
+ channel: z.enum([
34
+ "chromium",
35
+ "chrome",
36
+ "chrome-beta",
37
+ "chrome-canary",
38
+ "chrome-dev",
39
+ "msedge",
40
+ "msedge-beta",
41
+ "msedge-canary",
42
+ "msedge-dev"
43
+ ]).optional(),
44
+ viewport: z.union([
45
+ z.enum(["mobile", "tablet", "desktop"]),
46
+ z.object({ width: z.number().int().positive(), height: z.number().int().positive() }).strict()
47
+ ]).optional()
48
+ }).optional(),
49
+ artifacts: z.object({
50
+ screenshots: z.enum(["on-failure", "all"]).optional(),
51
+ networkHar: z.boolean().optional(),
52
+ console: z.boolean().optional(),
53
+ junit: z.boolean().optional()
54
+ }).optional(),
55
+ assertions: z.object({
56
+ noConsoleErrors: z.boolean().optional(),
57
+ noNetworkErrors: z.boolean().optional(),
58
+ maxTotalTimeMs: z.number().optional(),
59
+ networkIgnorePatterns: z.array(z.string()).optional()
60
+ }).optional(),
61
+ guardrails: z.object({
62
+ maxSteps: z.number().optional(),
63
+ allowedDomains: z.array(z.string()).optional(),
64
+ forbiddenSelectors: z.array(z.string()).optional(),
65
+ selfHealing: z.boolean().optional()
66
+ }).optional(),
67
+ auth: z.object({
68
+ storageStatePath: z.string().optional()
69
+ }).optional(),
70
+ history: z.object({
71
+ maxRuns: z.number().int().positive().optional()
72
+ }).optional(),
73
+ bugLog: z.object({
74
+ enabled: z.boolean().optional(),
75
+ backlogPath: z.string().min(1).optional(),
76
+ resolvedPath: z.string().min(1).optional()
77
+ }).strict().optional(),
78
+ tracing: z.object({
79
+ header: z.string().min(1).optional()
80
+ }).strict().optional(),
81
+ reliability: z.object({
82
+ flakyThreshold: z.number().min(0).max(1).optional()
83
+ }).strict().optional()
84
+ }).strict();
85
+ var navigateStepSchema = z.object({ navigate: z.string().min(1) }).strict();
86
+ var clickStepSchema = z.object({
87
+ click: z.union([z.object({ selector: z.string().min(1) }).strict(), z.string().min(1)])
88
+ }).strict();
89
+ var singleKeyValueSchema = z.record(z.string().min(1), z.string()).refine((record) => Object.keys(record).length === 1, {
90
+ message: "Expected exactly one key-value pair"
91
+ });
92
+ var fillStepSchema = z.object({
93
+ fill: z.union([
94
+ z.object({ selector: z.string().min(1), value: z.string() }).strict(),
95
+ singleKeyValueSchema
96
+ ])
97
+ }).strict();
98
+ var typeStepSchema = z.object({ type: z.string() }).strict();
99
+ var pressStepSchema = z.object({
100
+ press: z.object({ selector: z.string().min(1), key: z.string().min(1) }).strict()
101
+ }).strict();
102
+ var waitForSelectorStepSchema = z.object({
103
+ waitForSelector: z.object({ selector: z.string().min(1), timeout: z.number().optional() }).strict()
104
+ }).strict();
105
+ var waitStepSchema = z.object({
106
+ wait: z.union([
107
+ z.string().min(1),
108
+ z.object({ for: z.string().min(1), timeout: z.number().optional() }).strict()
109
+ ])
110
+ }).strict();
111
+ var waitForUrlStepSchema = z.object({
112
+ waitForUrl: z.object({ value: z.string().min(1), timeout: z.number().optional() }).strict()
113
+ }).strict();
114
+ var waitForNetworkIdleStepSchema = z.object({
115
+ waitForNetworkIdle: z.object({ timeout: z.number().optional() }).strict()
116
+ }).strict();
117
+ var selectOptionStepSchema = z.object({
118
+ selectOption: z.object({ selector: z.string().min(1), value: z.string() }).strict()
119
+ }).strict();
120
+ var selectStepSchema = z.object({
121
+ select: singleKeyValueSchema
122
+ }).strict();
123
+ var onDialogStepSchema = z.object({
124
+ onDialog: z.object({ action: z.enum(["accept", "dismiss"]) }).strict()
125
+ }).strict();
126
+ var setInputFilesStepSchema = z.object({
127
+ setInputFiles: z.object({
128
+ selector: z.string().min(1),
129
+ files: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)])
130
+ }).strict()
131
+ }).strict();
132
+ var inlineAssertStepSchema = z.object({
133
+ assert: z.object({
134
+ visible: z.string().min(1).optional(),
135
+ notVisible: z.string().min(1).optional(),
136
+ urlIncludes: z.string().min(1).optional(),
137
+ urlEquals: z.string().min(1).optional()
138
+ }).strict().refine(
139
+ (value) => [value.visible, value.notVisible, value.urlIncludes, value.urlEquals].filter(
140
+ (entry) => entry !== void 0
141
+ ).length === 1,
142
+ {
143
+ message: "assert requires exactly one of visible, notVisible, urlIncludes, urlEquals"
144
+ }
145
+ )
146
+ }).strict();
147
+ var runHuntStepSchema = z.object({
148
+ runHunt: z.union([
149
+ z.string().min(1).refine(isValidHuntName, {
150
+ message: "Invalid hunt name. Use only letters, numbers, hyphens, underscores, and forward slashes."
151
+ }),
152
+ z.object({
153
+ name: z.string().min(1).refine(isValidHuntName, {
154
+ message: "Invalid hunt name. Use only letters, numbers, hyphens, underscores, and forward slashes."
155
+ }),
156
+ vars: z.record(z.string(), z.string()).optional()
157
+ }).strict()
158
+ ])
159
+ }).strict();
160
+ var hoverStepSchema = z.object({
161
+ hover: z.object({ selector: z.string().min(1) }).strict()
162
+ }).strict();
163
+ var scrollStepSchema = z.object({
164
+ scroll: z.object({
165
+ direction: z.enum(["up", "down", "left", "right"]),
166
+ amount: z.number().optional()
167
+ }).strict()
168
+ }).strict();
169
+ var scrollToStepSchema = z.object({
170
+ scrollTo: z.object({ selector: z.string().min(1) }).strict()
171
+ }).strict();
172
+ var screenshotStepSchema = z.object({
173
+ screenshot: z.object({ name: z.string().optional() }).strict()
174
+ }).strict();
175
+ var ifStepSchema = z.object({
176
+ if: z.object({
177
+ visible: z.string().min(1).optional(),
178
+ notVisible: z.string().min(1).optional(),
179
+ then: z.lazy(() => z.array(stepSchema).min(1)),
180
+ else: z.lazy(() => z.array(stepSchema).min(1)).optional()
181
+ }).strict().refine(
182
+ (value) => [value.visible, value.notVisible].filter((v) => v !== void 0).length === 1,
183
+ { message: "if requires exactly one of visible or notVisible" }
184
+ )
185
+ }).strict();
186
+ var repeatStepSchema = z.object({
187
+ repeat: z.object({
188
+ times: z.number().int().positive().optional(),
189
+ while: z.object({
190
+ visible: z.string().min(1).optional(),
191
+ notVisible: z.string().min(1).optional()
192
+ }).strict().refine(
193
+ (value) => [value.visible, value.notVisible].filter((v) => v !== void 0).length === 1,
194
+ { message: "while requires exactly one of visible or notVisible" }
195
+ ).optional(),
196
+ maxIterations: z.number().int().positive().optional(),
197
+ steps: z.lazy(() => z.array(stepSchema).min(1))
198
+ }).strict().refine((value) => !(value.times !== void 0 && value.while !== void 0), {
199
+ message: "repeat requires either times or while, not both"
200
+ }).refine((value) => value.times !== void 0 || value.while !== void 0, {
201
+ message: "repeat requires either times or while"
202
+ }).refine((value) => !(value.while !== void 0 && value.maxIterations === void 0), {
203
+ message: "while requires maxIterations"
204
+ })
205
+ }).strict();
206
+ var mockRouteStepSchema = z.object({
207
+ mockRoute: z.object({
208
+ url: z.string().min(1),
209
+ response: z.object({
210
+ status: z.number().int(),
211
+ contentType: z.string().min(1).optional(),
212
+ body: z.string().min(1).optional(),
213
+ file: z.string().min(1).optional()
214
+ }).strict().refine(
215
+ (value) => [value.body, value.file].filter((v) => v !== void 0).length === 1,
216
+ { message: "response requires exactly one of body or file" }
217
+ )
218
+ }).strict()
219
+ }).strict();
220
+ var unmockRouteStepSchema = z.object({
221
+ unmockRoute: z.union([
222
+ z.string().min(1),
223
+ z.object({ url: z.string().min(1) }).strict()
224
+ ])
225
+ }).strict();
226
+ var evalScriptStepSchema = z.object({
227
+ evalScript: z.union([
228
+ z.string().min(1),
229
+ z.object({
230
+ expression: z.string().min(1),
231
+ as: z.string().min(1).optional()
232
+ }).strict()
233
+ ])
234
+ }).strict();
235
+ var runScriptStepSchema = z.object({
236
+ runScript: z.object({ file: z.string().min(1) }).strict()
237
+ }).strict();
238
+ var assertScreenshotStepSchema = z.object({
239
+ assertScreenshot: z.object({
240
+ name: z.string().min(1),
241
+ threshold: z.number().min(0).max(1).optional()
242
+ }).strict()
243
+ }).strict();
244
+ var copyTextStepSchema = z.object({
245
+ copyText: z.object({
246
+ selector: z.string().min(1),
247
+ as: z.string().min(1)
248
+ }).strict()
249
+ }).strict();
250
+ var waitForDownloadStepSchema = z.object({
251
+ waitForDownload: z.union([
252
+ z.object({
253
+ filename: z.string().min(1).optional(),
254
+ timeout: z.number().int().positive().optional()
255
+ }).strict(),
256
+ z.null()
257
+ ])
258
+ }).strict();
259
+ var stepSchema = z.union([
260
+ navigateStepSchema,
261
+ clickStepSchema,
262
+ fillStepSchema,
263
+ typeStepSchema,
264
+ pressStepSchema,
265
+ waitStepSchema,
266
+ selectOptionStepSchema,
267
+ selectStepSchema,
268
+ onDialogStepSchema,
269
+ setInputFilesStepSchema,
270
+ inlineAssertStepSchema,
271
+ runHuntStepSchema,
272
+ waitForSelectorStepSchema,
273
+ waitForUrlStepSchema,
274
+ waitForNetworkIdleStepSchema,
275
+ hoverStepSchema,
276
+ scrollStepSchema,
277
+ scrollToStepSchema,
278
+ screenshotStepSchema,
279
+ ifStepSchema,
280
+ repeatStepSchema,
281
+ mockRouteStepSchema,
282
+ unmockRouteStepSchema,
283
+ evalScriptStepSchema,
284
+ runScriptStepSchema,
285
+ assertScreenshotStepSchema,
286
+ copyTextStepSchema,
287
+ waitForDownloadStepSchema
288
+ ]);
289
+ var assertionSchema = z.union([
290
+ z.object({ selectorExists: z.string().min(1) }).strict(),
291
+ z.object({ selectorNotExists: z.string().min(1) }).strict(),
292
+ z.object({ urlIncludes: z.string().min(1) }).strict(),
293
+ z.object({ urlEquals: z.string().min(1) }).strict(),
294
+ z.object({ noConsoleErrors: z.boolean() }).strict(),
295
+ z.object({ noNetworkErrors: z.boolean() }).strict()
296
+ ]);
297
+ var huntSchema = z.object({
298
+ name: z.string().optional(),
299
+ description: z.string().optional(),
300
+ tags: z.array(z.string().min(1)).optional(),
301
+ vars: z.record(z.string(), z.string()).optional(),
302
+ steps: z.array(stepSchema),
303
+ assertions: z.array(assertionSchema).optional(),
304
+ retry: z.object({
305
+ maxRetries: z.number().int().min(0),
306
+ delay: z.number().int().min(0).optional()
307
+ }).strict().optional()
308
+ }).strict();
309
+
310
+ // src/config/loader.ts
311
+ var DEFAULT_CONFIG = {
312
+ target: {
313
+ url: "http://localhost:3000"
314
+ },
315
+ browser: {
316
+ headless: true,
317
+ slowMo: 0,
318
+ timeout: 3e4,
319
+ engine: "chromium",
320
+ viewport: { width: 1280, height: 720 }
321
+ },
322
+ artifacts: {
323
+ screenshots: "on-failure",
324
+ networkHar: false,
325
+ console: true,
326
+ junit: false
327
+ },
328
+ assertions: {
329
+ noConsoleErrors: true,
330
+ noNetworkErrors: true,
331
+ maxTotalTimeMs: 3e4,
332
+ networkIgnorePatterns: []
333
+ },
334
+ guardrails: {
335
+ maxSteps: 50,
336
+ allowedDomains: ["localhost", "127.0.0.1", "0.0.0.0"],
337
+ forbiddenSelectors: ["[data-danger]", ".delete-btn"],
338
+ selfHealing: false
339
+ },
340
+ auth: {
341
+ storageStatePath: ".prowl/auth-state.json"
342
+ },
343
+ history: {
344
+ maxRuns: 100
345
+ }
346
+ };
347
+ var CONFIG_DIR = ".prowl";
348
+ var LEGACY_CONFIG_DIR = ".prowlqa";
349
+ var legacyDirWarned = false;
350
+ function warnLegacyConfigDir() {
351
+ if (legacyDirWarned) {
352
+ return;
353
+ }
354
+ legacyDirWarned = true;
355
+ console.warn(
356
+ 'Warning: the ".prowlqa/" config directory is deprecated; rename it to ".prowl/". Support for ".prowlqa/" will be removed in a future release.'
357
+ );
358
+ }
359
+ function findConfigPath(startDir) {
360
+ let current = startDir;
361
+ while (current) {
362
+ for (const dir of [CONFIG_DIR, LEGACY_CONFIG_DIR]) {
363
+ const candidate = path.join(current, dir, "config.yml");
364
+ if (fs.existsSync(candidate)) {
365
+ return candidate;
366
+ }
367
+ }
368
+ const parent = path.dirname(current);
369
+ if (parent === current) {
370
+ break;
371
+ }
372
+ current = parent;
373
+ }
374
+ return null;
375
+ }
376
+ var VIEWPORT_PRESETS = {
377
+ mobile: { width: 375, height: 812 },
378
+ tablet: { width: 768, height: 1024 },
379
+ desktop: { width: 1280, height: 720 }
380
+ };
381
+ function resolveViewport(value) {
382
+ if (value === void 0) {
383
+ return DEFAULT_CONFIG.browser.viewport;
384
+ }
385
+ if (typeof value === "string") {
386
+ const preset = VIEWPORT_PRESETS[value];
387
+ if (!preset) {
388
+ throw new Error(`Unknown viewport preset: "${value}". Use mobile, tablet, or desktop.`);
389
+ }
390
+ return preset;
391
+ }
392
+ return value;
393
+ }
394
+ function mergeConfig(partial) {
395
+ return {
396
+ target: {
397
+ url: partial.target?.url ?? DEFAULT_CONFIG.target.url
398
+ },
399
+ browser: {
400
+ headless: partial.browser?.headless ?? DEFAULT_CONFIG.browser.headless,
401
+ slowMo: partial.browser?.slowMo ?? DEFAULT_CONFIG.browser.slowMo,
402
+ timeout: partial.browser?.timeout ?? DEFAULT_CONFIG.browser.timeout,
403
+ engine: partial.browser?.engine ?? DEFAULT_CONFIG.browser.engine,
404
+ channel: partial.browser?.channel,
405
+ viewport: resolveViewport(partial.browser?.viewport)
406
+ },
407
+ artifacts: {
408
+ screenshots: partial.artifacts?.screenshots ?? DEFAULT_CONFIG.artifacts.screenshots,
409
+ networkHar: partial.artifacts?.networkHar ?? DEFAULT_CONFIG.artifacts.networkHar,
410
+ console: partial.artifacts?.console ?? DEFAULT_CONFIG.artifacts.console,
411
+ junit: partial.artifacts?.junit ?? DEFAULT_CONFIG.artifacts.junit
412
+ },
413
+ assertions: {
414
+ noConsoleErrors: partial.assertions?.noConsoleErrors ?? DEFAULT_CONFIG.assertions.noConsoleErrors,
415
+ noNetworkErrors: partial.assertions?.noNetworkErrors ?? DEFAULT_CONFIG.assertions.noNetworkErrors,
416
+ maxTotalTimeMs: partial.assertions?.maxTotalTimeMs ?? DEFAULT_CONFIG.assertions.maxTotalTimeMs,
417
+ networkIgnorePatterns: partial.assertions?.networkIgnorePatterns ?? DEFAULT_CONFIG.assertions.networkIgnorePatterns
418
+ },
419
+ guardrails: {
420
+ maxSteps: partial.guardrails?.maxSteps ?? DEFAULT_CONFIG.guardrails.maxSteps,
421
+ allowedDomains: partial.guardrails?.allowedDomains ?? DEFAULT_CONFIG.guardrails.allowedDomains,
422
+ forbiddenSelectors: partial.guardrails?.forbiddenSelectors ?? DEFAULT_CONFIG.guardrails.forbiddenSelectors,
423
+ selfHealing: partial.guardrails?.selfHealing ?? DEFAULT_CONFIG.guardrails.selfHealing
424
+ },
425
+ auth: {
426
+ storageStatePath: partial.auth?.storageStatePath ?? (partial.auth !== void 0 ? DEFAULT_CONFIG.auth.storageStatePath : void 0)
427
+ },
428
+ history: {
429
+ maxRuns: partial.history?.maxRuns ?? DEFAULT_CONFIG.history.maxRuns
430
+ },
431
+ bugLog: partial.bugLog,
432
+ tracing: partial.tracing,
433
+ reliability: partial.reliability
434
+ };
435
+ }
436
+ function ensureAllowedDomain(allowed, urlValue) {
437
+ try {
438
+ const host = new URL(urlValue).hostname;
439
+ if (!allowed.includes(host)) {
440
+ return [...allowed, host];
441
+ }
442
+ } catch {
443
+ return allowed;
444
+ }
445
+ return allowed;
446
+ }
447
+ function loadConfig(configPath) {
448
+ const resolvedPath = configPath ? path.resolve(configPath) : findConfigPath(process.cwd());
449
+ if (!resolvedPath) {
450
+ throw new Error("Could not find .prowl/config.yml. Run `prowl init` first.");
451
+ }
452
+ if (!fs.existsSync(resolvedPath)) {
453
+ throw new Error(`Config file not found at ${resolvedPath}`);
454
+ }
455
+ const configDir = path.dirname(resolvedPath);
456
+ if (path.basename(configDir) === LEGACY_CONFIG_DIR) {
457
+ warnLegacyConfigDir();
458
+ }
459
+ dotenv.config({ path: path.join(configDir, ".env"), override: false });
460
+ const raw = fs.readFileSync(resolvedPath, "utf-8");
461
+ const parsed = yaml.parse(raw) ?? {};
462
+ const validated = configSchema.parse(parsed);
463
+ const config = mergeConfig(validated);
464
+ config.guardrails.allowedDomains = ensureAllowedDomain(
465
+ config.guardrails.allowedDomains,
466
+ config.target.url
467
+ );
468
+ return { config, configPath: resolvedPath, configDir };
469
+ }
470
+ function loadHunt(huntName, configDir) {
471
+ assertValidHuntName(huntName);
472
+ const huntPath = path.join(configDir, "hunts", `${huntName}.yml`);
473
+ if (!fs.existsSync(huntPath)) {
474
+ throw new Error(`Hunt file not found: ${huntPath}`);
475
+ }
476
+ const raw = fs.readFileSync(huntPath, "utf-8");
477
+ const parsed = yaml.parse(raw) ?? {};
478
+ const validated = huntSchema.parse(parsed);
479
+ return validated;
480
+ }
481
+ function loadHuntTags(huntName, configDir) {
482
+ assertValidHuntName(huntName);
483
+ const huntPath = path.join(configDir, "hunts", `${huntName}.yml`);
484
+ if (!fs.existsSync(huntPath)) {
485
+ return [];
486
+ }
487
+ const raw = fs.readFileSync(huntPath, "utf-8");
488
+ const parsed = yaml.parse(raw) ?? {};
489
+ return Array.isArray(parsed.tags) ? parsed.tags : [];
490
+ }
491
+ function loadHuntMeta(huntName, configDir) {
492
+ assertValidHuntName(huntName);
493
+ const huntPath = path.join(configDir, "hunts", `${huntName}.yml`);
494
+ if (!fs.existsSync(huntPath)) {
495
+ return { tags: [] };
496
+ }
497
+ const raw = fs.readFileSync(huntPath, "utf-8");
498
+ const parsed = yaml.parse(raw) ?? {};
499
+ return {
500
+ description: typeof parsed.description === "string" ? parsed.description : void 0,
501
+ tags: Array.isArray(parsed.tags) ? parsed.tags : []
502
+ };
503
+ }
504
+ function listHunts(configDir) {
505
+ const huntsDir = path.join(configDir, "hunts");
506
+ if (!fs.existsSync(huntsDir)) {
507
+ return [];
508
+ }
509
+ const stats = fs.statSync(huntsDir);
510
+ if (!stats.isDirectory()) {
511
+ throw new Error(`Hunts path is not a directory: ${huntsDir}`);
512
+ }
513
+ const results = [];
514
+ function scanDir(dir) {
515
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
516
+ for (const entry of entries) {
517
+ if (entry.isFile() && entry.name.endsWith(".yml")) {
518
+ const fullPath = path.join(dir, entry.name);
519
+ const relative = path.relative(huntsDir, fullPath);
520
+ results.push(relative.replace(/\.yml$/, ""));
521
+ } else if (entry.isDirectory()) {
522
+ scanDir(path.join(dir, entry.name));
523
+ }
524
+ }
525
+ }
526
+ scanDir(huntsDir);
527
+ return results.sort((a, b) => a.localeCompare(b));
528
+ }
529
+
530
+ export {
531
+ configSchema,
532
+ stepSchema,
533
+ huntSchema,
534
+ CONFIG_DIR,
535
+ LEGACY_CONFIG_DIR,
536
+ warnLegacyConfigDir,
537
+ findConfigPath,
538
+ resolveViewport,
539
+ ensureAllowedDomain,
540
+ loadConfig,
541
+ loadHunt,
542
+ loadHuntTags,
543
+ loadHuntMeta,
544
+ listHunts
545
+ };
546
+ //# sourceMappingURL=chunk-NXXGJOBG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/loader.ts","../src/config/schema.ts","../src/config/hunt-name.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"yaml\";\nimport dotenv from \"dotenv\";\nimport type { BrowserChannel, BrowserEngine, Config, Hunt, Viewport } from \"../types/index.js\";\nimport { configSchema, huntSchema } from \"./schema.js\";\nimport { assertValidHuntName } from \"./hunt-name.js\";\n\nconst DEFAULT_CONFIG: Config = {\n target: {\n url: \"http://localhost:3000\"\n },\n browser: {\n headless: true,\n slowMo: 0,\n timeout: 30000,\n engine: \"chromium\",\n viewport: { width: 1280, height: 720 }\n },\n artifacts: {\n screenshots: \"on-failure\",\n networkHar: false,\n console: true,\n junit: false\n },\n assertions: {\n noConsoleErrors: true,\n noNetworkErrors: true,\n maxTotalTimeMs: 30000,\n networkIgnorePatterns: []\n },\n guardrails: {\n maxSteps: 50,\n allowedDomains: [\"localhost\", \"127.0.0.1\", \"0.0.0.0\"],\n forbiddenSelectors: [\"[data-danger]\", \".delete-btn\"],\n selfHealing: false\n },\n auth: {\n storageStatePath: \".prowl/auth-state.json\"\n },\n history: {\n maxRuns: 100\n }\n};\n\nexport const CONFIG_DIR = \".prowl\";\nexport const LEGACY_CONFIG_DIR = \".prowlqa\";\n\nlet legacyDirWarned = false;\n\n/** Warn (once per process) when a project still uses the legacy .prowlqa/ directory. */\nexport function warnLegacyConfigDir(): void {\n if (legacyDirWarned) {\n return;\n }\n legacyDirWarned = true;\n console.warn(\n 'Warning: the \".prowlqa/\" config directory is deprecated; rename it to \".prowl/\". ' +\n 'Support for \".prowlqa/\" will be removed in a future release.'\n );\n}\n\nexport function findConfigPath(startDir: string): string | null {\n let current = startDir;\n while (current) {\n // Prefer the new .prowl/ directory; fall back to the legacy .prowlqa/ at the same level.\n for (const dir of [CONFIG_DIR, LEGACY_CONFIG_DIR]) {\n const candidate = path.join(current, dir, \"config.yml\");\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return null;\n}\n\nconst VIEWPORT_PRESETS: Record<string, Viewport> = {\n mobile: { width: 375, height: 812 },\n tablet: { width: 768, height: 1024 },\n desktop: { width: 1280, height: 720 }\n};\n\nexport function resolveViewport(\n value: string | Viewport | undefined\n): Viewport {\n if (value === undefined) {\n return DEFAULT_CONFIG.browser.viewport;\n }\n if (typeof value === \"string\") {\n const preset = VIEWPORT_PRESETS[value];\n if (!preset) {\n throw new Error(`Unknown viewport preset: \"${value}\". Use mobile, tablet, or desktop.`);\n }\n return preset;\n }\n return value;\n}\n\nfunction mergeConfig(partial: Partial<Config>): Config {\n return {\n target: {\n url: partial.target?.url ?? DEFAULT_CONFIG.target.url\n },\n browser: {\n headless: partial.browser?.headless ?? DEFAULT_CONFIG.browser.headless,\n slowMo: partial.browser?.slowMo ?? DEFAULT_CONFIG.browser.slowMo,\n timeout: partial.browser?.timeout ?? DEFAULT_CONFIG.browser.timeout,\n engine: (partial.browser as { engine?: BrowserEngine } | undefined)?.engine ?? DEFAULT_CONFIG.browser.engine,\n channel: (partial.browser as { channel?: BrowserChannel } | undefined)?.channel,\n viewport: resolveViewport((partial.browser as { viewport?: string | Viewport } | undefined)?.viewport)\n },\n artifacts: {\n screenshots: partial.artifacts?.screenshots ?? DEFAULT_CONFIG.artifacts.screenshots,\n networkHar: partial.artifacts?.networkHar ?? DEFAULT_CONFIG.artifacts.networkHar,\n console: partial.artifacts?.console ?? DEFAULT_CONFIG.artifacts.console,\n junit: partial.artifacts?.junit ?? DEFAULT_CONFIG.artifacts.junit\n },\n assertions: {\n noConsoleErrors:\n partial.assertions?.noConsoleErrors ?? DEFAULT_CONFIG.assertions.noConsoleErrors,\n noNetworkErrors:\n partial.assertions?.noNetworkErrors ?? DEFAULT_CONFIG.assertions.noNetworkErrors,\n maxTotalTimeMs:\n partial.assertions?.maxTotalTimeMs ?? DEFAULT_CONFIG.assertions.maxTotalTimeMs,\n networkIgnorePatterns:\n partial.assertions?.networkIgnorePatterns ??\n DEFAULT_CONFIG.assertions.networkIgnorePatterns\n },\n guardrails: {\n maxSteps: partial.guardrails?.maxSteps ?? DEFAULT_CONFIG.guardrails.maxSteps,\n allowedDomains: partial.guardrails?.allowedDomains ?? DEFAULT_CONFIG.guardrails.allowedDomains,\n forbiddenSelectors:\n partial.guardrails?.forbiddenSelectors ?? DEFAULT_CONFIG.guardrails.forbiddenSelectors,\n selfHealing: partial.guardrails?.selfHealing ?? DEFAULT_CONFIG.guardrails.selfHealing\n },\n auth: {\n storageStatePath: partial.auth?.storageStatePath ?? (partial.auth !== undefined ? DEFAULT_CONFIG.auth.storageStatePath : undefined)\n },\n history: {\n maxRuns: partial.history?.maxRuns ?? DEFAULT_CONFIG.history.maxRuns\n },\n bugLog: partial.bugLog,\n tracing: partial.tracing,\n reliability: partial.reliability\n };\n}\n\nexport function ensureAllowedDomain(allowed: string[], urlValue: string): string[] {\n try {\n const host = new URL(urlValue).hostname;\n if (!allowed.includes(host)) {\n return [...allowed, host];\n }\n } catch {\n return allowed;\n }\n return allowed;\n}\n\nexport function loadConfig(configPath?: string): {\n config: Config;\n configPath: string;\n configDir: string;\n} {\n const resolvedPath = configPath\n ? path.resolve(configPath)\n : findConfigPath(process.cwd());\n\n if (!resolvedPath) {\n throw new Error(\"Could not find .prowl/config.yml. Run `prowl init` first.\");\n }\n\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`Config file not found at ${resolvedPath}`);\n }\n\n const configDir = path.dirname(resolvedPath);\n if (path.basename(configDir) === LEGACY_CONFIG_DIR) {\n warnLegacyConfigDir();\n }\n dotenv.config({ path: path.join(configDir, \".env\"), override: false });\n\n const raw = fs.readFileSync(resolvedPath, \"utf-8\");\n const parsed = yaml.parse(raw) ?? {};\n const validated = configSchema.parse(parsed);\n const config = mergeConfig(validated as Partial<Config>);\n\n config.guardrails.allowedDomains = ensureAllowedDomain(\n config.guardrails.allowedDomains,\n config.target.url\n );\n\n return { config, configPath: resolvedPath, configDir };\n}\n\nexport function loadHunt(huntName: string, configDir: string): Hunt {\n assertValidHuntName(huntName);\n const huntPath = path.join(configDir, \"hunts\", `${huntName}.yml`);\n if (!fs.existsSync(huntPath)) {\n throw new Error(`Hunt file not found: ${huntPath}`);\n }\n const raw = fs.readFileSync(huntPath, \"utf-8\");\n const parsed = yaml.parse(raw) ?? {};\n const validated = huntSchema.parse(parsed);\n return validated as Hunt;\n}\n\nexport function loadHuntTags(huntName: string, configDir: string): string[] {\n assertValidHuntName(huntName);\n const huntPath = path.join(configDir, \"hunts\", `${huntName}.yml`);\n if (!fs.existsSync(huntPath)) {\n return [];\n }\n const raw = fs.readFileSync(huntPath, \"utf-8\");\n const parsed = yaml.parse(raw) ?? {};\n return Array.isArray(parsed.tags) ? parsed.tags : [];\n}\n\nexport function loadHuntMeta(huntName: string, configDir: string): { description?: string; tags: string[] } {\n assertValidHuntName(huntName);\n const huntPath = path.join(configDir, \"hunts\", `${huntName}.yml`);\n if (!fs.existsSync(huntPath)) {\n return { tags: [] };\n }\n const raw = fs.readFileSync(huntPath, \"utf-8\");\n const parsed = yaml.parse(raw) ?? {};\n return {\n description: typeof parsed.description === \"string\" ? parsed.description : undefined,\n tags: Array.isArray(parsed.tags) ? parsed.tags : []\n };\n}\n\nexport function listHunts(configDir: string): string[] {\n const huntsDir = path.join(configDir, \"hunts\");\n if (!fs.existsSync(huntsDir)) {\n return [];\n }\n const stats = fs.statSync(huntsDir);\n if (!stats.isDirectory()) {\n throw new Error(`Hunts path is not a directory: ${huntsDir}`);\n }\n\n const results: string[] = [];\n\n function scanDir(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith(\".yml\")) {\n const fullPath = path.join(dir, entry.name);\n const relative = path.relative(huntsDir, fullPath);\n results.push(relative.replace(/\\.yml$/, \"\"));\n } else if (entry.isDirectory()) {\n scanDir(path.join(dir, entry.name));\n }\n }\n }\n\n scanDir(huntsDir);\n return results.sort((a, b) => a.localeCompare(b));\n}\n","import { z } from \"zod\";\nimport type { Step } from \"../types/index.js\";\nimport { isValidHuntName } from \"./hunt-name.js\";\n\nexport const configSchema = z\n .object({\n target: z.object({\n url: z.string().min(1)\n }),\n browser: z\n .object({\n headless: z.boolean().optional(),\n slowMo: z.number().optional(),\n timeout: z.number().optional(),\n engine: z.enum([\"chromium\", \"firefox\", \"webkit\"]).optional(),\n channel: z.enum([\n \"chromium\",\n \"chrome\", \"chrome-beta\", \"chrome-canary\", \"chrome-dev\",\n \"msedge\", \"msedge-beta\", \"msedge-canary\", \"msedge-dev\"\n ]).optional(),\n viewport: z\n .union([\n z.enum([\"mobile\", \"tablet\", \"desktop\"]),\n z.object({ width: z.number().int().positive(), height: z.number().int().positive() }).strict()\n ])\n .optional()\n })\n .optional(),\n artifacts: z\n .object({\n screenshots: z.enum([\"on-failure\", \"all\"]).optional(),\n networkHar: z.boolean().optional(),\n console: z.boolean().optional(),\n junit: z.boolean().optional()\n })\n .optional(),\n assertions: z\n .object({\n noConsoleErrors: z.boolean().optional(),\n noNetworkErrors: z.boolean().optional(),\n maxTotalTimeMs: z.number().optional(),\n networkIgnorePatterns: z.array(z.string()).optional()\n })\n .optional(),\n guardrails: z\n .object({\n maxSteps: z.number().optional(),\n allowedDomains: z.array(z.string()).optional(),\n forbiddenSelectors: z.array(z.string()).optional(),\n selfHealing: z.boolean().optional()\n })\n .optional(),\n auth: z\n .object({\n storageStatePath: z.string().optional()\n })\n .optional(),\n history: z\n .object({\n maxRuns: z.number().int().positive().optional()\n })\n .optional(),\n bugLog: z\n .object({\n enabled: z.boolean().optional(),\n backlogPath: z.string().min(1).optional(),\n resolvedPath: z.string().min(1).optional()\n })\n .strict()\n .optional(),\n tracing: z\n .object({\n header: z.string().min(1).optional()\n })\n .strict()\n .optional(),\n reliability: z\n .object({\n flakyThreshold: z.number().min(0).max(1).optional()\n })\n .strict()\n .optional()\n })\n .strict();\n\nexport const navigateStepSchema = z.object({ navigate: z.string().min(1) }).strict();\nexport const clickStepSchema = z\n .object({\n click: z.union([z.object({ selector: z.string().min(1) }).strict(), z.string().min(1)])\n })\n .strict();\n\nconst singleKeyValueSchema = z\n .record(z.string().min(1), z.string())\n .refine((record) => Object.keys(record).length === 1, {\n message: \"Expected exactly one key-value pair\"\n });\n\nexport const fillStepSchema = z\n .object({\n fill: z.union([\n z.object({ selector: z.string().min(1), value: z.string() }).strict(),\n singleKeyValueSchema\n ])\n })\n .strict();\nexport const typeStepSchema = z.object({ type: z.string() }).strict();\nexport const pressStepSchema = z\n .object({\n press: z.object({ selector: z.string().min(1), key: z.string().min(1) }).strict()\n })\n .strict();\nexport const waitForSelectorStepSchema = z\n .object({\n waitForSelector: z\n .object({ selector: z.string().min(1), timeout: z.number().optional() })\n .strict()\n })\n .strict();\nexport const waitStepSchema = z\n .object({\n wait: z.union([\n z.string().min(1),\n z.object({ for: z.string().min(1), timeout: z.number().optional() }).strict()\n ])\n })\n .strict();\nexport const waitForUrlStepSchema = z\n .object({\n waitForUrl: z.object({ value: z.string().min(1), timeout: z.number().optional() }).strict()\n })\n .strict();\nexport const waitForNetworkIdleStepSchema = z\n .object({\n waitForNetworkIdle: z.object({ timeout: z.number().optional() }).strict()\n })\n .strict();\nexport const selectOptionStepSchema = z\n .object({\n selectOption: z.object({ selector: z.string().min(1), value: z.string() }).strict()\n })\n .strict();\nexport const selectStepSchema = z\n .object({\n select: singleKeyValueSchema\n })\n .strict();\nexport const onDialogStepSchema = z\n .object({\n onDialog: z.object({ action: z.enum([\"accept\", \"dismiss\"]) }).strict()\n })\n .strict();\nexport const setInputFilesStepSchema = z\n .object({\n setInputFiles: z\n .object({\n selector: z.string().min(1),\n files: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)])\n })\n .strict()\n })\n .strict();\nexport const inlineAssertStepSchema = z\n .object({\n assert: z\n .object({\n visible: z.string().min(1).optional(),\n notVisible: z.string().min(1).optional(),\n urlIncludes: z.string().min(1).optional(),\n urlEquals: z.string().min(1).optional()\n })\n .strict()\n .refine(\n (value) =>\n [value.visible, value.notVisible, value.urlIncludes, value.urlEquals].filter(\n (entry) => entry !== undefined\n ).length === 1,\n {\n message: \"assert requires exactly one of visible, notVisible, urlIncludes, urlEquals\"\n }\n )\n })\n .strict();\nexport const runHuntStepSchema = z\n .object({\n runHunt: z.union([\n z\n .string()\n .min(1)\n .refine(isValidHuntName, {\n message:\n \"Invalid hunt name. Use only letters, numbers, hyphens, underscores, and forward slashes.\"\n }),\n z\n .object({\n name: z\n .string()\n .min(1)\n .refine(isValidHuntName, {\n message:\n \"Invalid hunt name. Use only letters, numbers, hyphens, underscores, and forward slashes.\"\n }),\n vars: z.record(z.string(), z.string()).optional()\n })\n .strict()\n ])\n })\n .strict();\nexport const hoverStepSchema = z\n .object({\n hover: z.object({ selector: z.string().min(1) }).strict()\n })\n .strict();\nexport const scrollStepSchema = z\n .object({\n scroll: z\n .object({\n direction: z.enum([\"up\", \"down\", \"left\", \"right\"]),\n amount: z.number().optional()\n })\n .strict()\n })\n .strict();\nexport const scrollToStepSchema = z\n .object({\n scrollTo: z.object({ selector: z.string().min(1) }).strict()\n })\n .strict();\nexport const screenshotStepSchema = z\n .object({\n screenshot: z.object({ name: z.string().optional() }).strict()\n })\n .strict();\n\n// Recursive step schemas use z.lazy() to reference stepSchema before it's defined\nexport const ifStepSchema = z\n .object({\n if: z\n .object({\n visible: z.string().min(1).optional(),\n notVisible: z.string().min(1).optional(),\n then: z.lazy(() => z.array(stepSchema).min(1)),\n else: z.lazy(() => z.array(stepSchema).min(1)).optional()\n })\n .strict()\n .refine(\n (value) =>\n [value.visible, value.notVisible].filter((v) => v !== undefined).length === 1,\n { message: \"if requires exactly one of visible or notVisible\" }\n )\n })\n .strict();\n\nexport const repeatStepSchema = z\n .object({\n repeat: z\n .object({\n times: z.number().int().positive().optional(),\n while: z\n .object({\n visible: z.string().min(1).optional(),\n notVisible: z.string().min(1).optional()\n })\n .strict()\n .refine(\n (value) =>\n [value.visible, value.notVisible].filter((v) => v !== undefined).length === 1,\n { message: \"while requires exactly one of visible or notVisible\" }\n )\n .optional(),\n maxIterations: z.number().int().positive().optional(),\n steps: z.lazy(() => z.array(stepSchema).min(1))\n })\n .strict()\n .refine((value) => !(value.times !== undefined && value.while !== undefined), {\n message: \"repeat requires either times or while, not both\"\n })\n .refine((value) => value.times !== undefined || value.while !== undefined, {\n message: \"repeat requires either times or while\"\n })\n .refine((value) => !(value.while !== undefined && value.maxIterations === undefined), {\n message: \"while requires maxIterations\"\n })\n })\n .strict();\n\nexport const mockRouteStepSchema = z\n .object({\n mockRoute: z\n .object({\n url: z.string().min(1),\n response: z\n .object({\n status: z.number().int(),\n contentType: z.string().min(1).optional(),\n body: z.string().min(1).optional(),\n file: z.string().min(1).optional()\n })\n .strict()\n .refine(\n (value) =>\n [value.body, value.file].filter((v) => v !== undefined).length === 1,\n { message: \"response requires exactly one of body or file\" }\n )\n })\n .strict()\n })\n .strict();\n\nexport const unmockRouteStepSchema = z\n .object({\n unmockRoute: z.union([\n z.string().min(1),\n z.object({ url: z.string().min(1) }).strict()\n ])\n })\n .strict();\n\nexport const evalScriptStepSchema = z\n .object({\n evalScript: z.union([\n z.string().min(1),\n z\n .object({\n expression: z.string().min(1),\n as: z.string().min(1).optional()\n })\n .strict()\n ])\n })\n .strict();\n\nexport const runScriptStepSchema = z\n .object({\n runScript: z.object({ file: z.string().min(1) }).strict()\n })\n .strict();\n\nexport const assertScreenshotStepSchema = z\n .object({\n assertScreenshot: z\n .object({\n name: z.string().min(1),\n threshold: z.number().min(0).max(1).optional()\n })\n .strict()\n })\n .strict();\n\nexport const copyTextStepSchema = z\n .object({\n copyText: z\n .object({\n selector: z.string().min(1),\n as: z.string().min(1)\n })\n .strict()\n })\n .strict();\n\nexport const waitForDownloadStepSchema = z\n .object({\n waitForDownload: z.union([\n z\n .object({\n filename: z.string().min(1).optional(),\n timeout: z.number().int().positive().optional()\n })\n .strict(),\n z.null()\n ])\n })\n .strict();\n\nexport const stepSchema: z.ZodType<Step> = z.union([\n navigateStepSchema,\n clickStepSchema,\n fillStepSchema,\n typeStepSchema,\n pressStepSchema,\n waitStepSchema,\n selectOptionStepSchema,\n selectStepSchema,\n onDialogStepSchema,\n setInputFilesStepSchema,\n inlineAssertStepSchema,\n runHuntStepSchema,\n waitForSelectorStepSchema,\n waitForUrlStepSchema,\n waitForNetworkIdleStepSchema,\n hoverStepSchema,\n scrollStepSchema,\n scrollToStepSchema,\n screenshotStepSchema,\n ifStepSchema,\n repeatStepSchema,\n mockRouteStepSchema,\n unmockRouteStepSchema,\n evalScriptStepSchema,\n runScriptStepSchema,\n assertScreenshotStepSchema,\n copyTextStepSchema,\n waitForDownloadStepSchema\n]);\n\nexport const assertionSchema = z.union([\n z.object({ selectorExists: z.string().min(1) }).strict(),\n z.object({ selectorNotExists: z.string().min(1) }).strict(),\n z.object({ urlIncludes: z.string().min(1) }).strict(),\n z.object({ urlEquals: z.string().min(1) }).strict(),\n z.object({ noConsoleErrors: z.boolean() }).strict(),\n z.object({ noNetworkErrors: z.boolean() }).strict()\n]);\n\nexport const huntSchema = z\n .object({\n name: z.string().optional(),\n description: z.string().optional(),\n tags: z.array(z.string().min(1)).optional(),\n vars: z.record(z.string(), z.string()).optional(),\n steps: z.array(stepSchema),\n assertions: z.array(assertionSchema).optional(),\n retry: z\n .object({\n maxRetries: z.number().int().min(0),\n delay: z.number().int().min(0).optional()\n })\n .strict()\n .optional()\n })\n .strict();\n","const HUNT_NAME_PATTERN = /^[A-Za-z0-9_-]+(?:\\/[A-Za-z0-9_-]+)*$/;\n\nexport function isValidHuntName(name: string): boolean {\n return HUNT_NAME_PATTERN.test(name);\n}\n\nexport function assertValidHuntName(name: string): void {\n if (!isValidHuntName(name)) {\n throw new Error(\n `Invalid hunt name: \"${name}\". Use only letters, numbers, hyphens, underscores, and forward slashes.`\n );\n }\n}\n"],"mappings":"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","names":[]}