@browserflow-ai/core 0.0.6

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 (57) hide show
  1. package/dist/config-schema.d.ts +354 -0
  2. package/dist/config-schema.d.ts.map +1 -0
  3. package/dist/config-schema.js +83 -0
  4. package/dist/config-schema.js.map +1 -0
  5. package/dist/config.d.ts +107 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +5 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/duration.d.ts +39 -0
  10. package/dist/duration.d.ts.map +1 -0
  11. package/dist/duration.js +111 -0
  12. package/dist/duration.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +20 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/locator-object.d.ts +556 -0
  18. package/dist/locator-object.d.ts.map +1 -0
  19. package/dist/locator-object.js +114 -0
  20. package/dist/locator-object.js.map +1 -0
  21. package/dist/lockfile.d.ts +1501 -0
  22. package/dist/lockfile.d.ts.map +1 -0
  23. package/dist/lockfile.js +86 -0
  24. package/dist/lockfile.js.map +1 -0
  25. package/dist/run-store.d.ts +81 -0
  26. package/dist/run-store.d.ts.map +1 -0
  27. package/dist/run-store.js +181 -0
  28. package/dist/run-store.js.map +1 -0
  29. package/dist/spec-loader.d.ts +17 -0
  30. package/dist/spec-loader.d.ts.map +1 -0
  31. package/dist/spec-loader.js +37 -0
  32. package/dist/spec-loader.js.map +1 -0
  33. package/dist/spec-schema.d.ts +1411 -0
  34. package/dist/spec-schema.d.ts.map +1 -0
  35. package/dist/spec-schema.js +239 -0
  36. package/dist/spec-schema.js.map +1 -0
  37. package/package.json +45 -0
  38. package/schemas/browserflow.schema.json +220 -0
  39. package/schemas/lockfile.schema.json +568 -0
  40. package/schemas/spec-v2.schema.json +413 -0
  41. package/src/config-schema.test.ts +190 -0
  42. package/src/config-schema.ts +111 -0
  43. package/src/config.ts +112 -0
  44. package/src/duration.test.ts +175 -0
  45. package/src/duration.ts +128 -0
  46. package/src/index.ts +136 -0
  47. package/src/json-schemas.test.ts +374 -0
  48. package/src/locator-object.test.ts +323 -0
  49. package/src/locator-object.ts +250 -0
  50. package/src/lockfile.test.ts +345 -0
  51. package/src/lockfile.ts +209 -0
  52. package/src/run-store.test.ts +232 -0
  53. package/src/run-store.ts +240 -0
  54. package/src/spec-loader.test.ts +181 -0
  55. package/src/spec-loader.ts +47 -0
  56. package/src/spec-schema.test.ts +360 -0
  57. package/src/spec-schema.ts +347 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Lockfile types for exploration results
3
+ *
4
+ * @see bf-aak for implementation task
5
+ */
6
+ import { z } from 'zod';
7
+ import { join } from 'path';
8
+ import { createHash } from 'crypto';
9
+ import { readFile, writeFile } from 'fs/promises';
10
+ import { locatorObjectSchema } from './locator-object.js';
11
+ export const assertionTypeSchema = z.enum([
12
+ 'visible',
13
+ 'hidden',
14
+ 'text_contains',
15
+ 'text_equals',
16
+ 'url_contains',
17
+ 'url_matches',
18
+ 'count',
19
+ 'attribute',
20
+ 'checked',
21
+ 'screenshot',
22
+ ]);
23
+ export const maskSchema = z.object({
24
+ x: z.number(),
25
+ y: z.number(),
26
+ width: z.number(),
27
+ height: z.number(),
28
+ reason: z.string(),
29
+ locator: z.string().optional(),
30
+ });
31
+ export const assertionSchema = z.object({
32
+ id: z.string(),
33
+ type: assertionTypeSchema,
34
+ target: locatorObjectSchema.optional(),
35
+ expected: z.union([z.string(), z.number(), z.boolean()]).optional(),
36
+ step_id: z.string().optional(),
37
+ });
38
+ export const generationMetadataSchema = z.object({
39
+ format: z.literal('playwright-ts'),
40
+ output_path: z.string(),
41
+ generated_at: z.string().optional(),
42
+ });
43
+ export const lockfileSchema = z.object({
44
+ run_id: z.string(),
45
+ spec_name: z.string(),
46
+ spec_hash: z.string(),
47
+ created_at: z.string(),
48
+ locators: z.record(locatorObjectSchema),
49
+ masks: z.record(z.array(maskSchema)),
50
+ assertions: z.array(assertionSchema),
51
+ generation: generationMetadataSchema,
52
+ });
53
+ /**
54
+ * Validates if an object is a valid Lockfile
55
+ */
56
+ export function validateLockfile(lockfile) {
57
+ return lockfileSchema.safeParse(lockfile).success;
58
+ }
59
+ /**
60
+ * Computes SHA256 hash of spec file content
61
+ */
62
+ export function computeSpecHash(content) {
63
+ return createHash('sha256').update(content).digest('hex');
64
+ }
65
+ /**
66
+ * Reads a lockfile from a run directory
67
+ */
68
+ export async function readLockfile(runDir) {
69
+ const lockfilePath = join(runDir, 'lockfile.json');
70
+ const content = await readFile(lockfilePath, 'utf-8');
71
+ const parsed = JSON.parse(content);
72
+ const result = lockfileSchema.safeParse(parsed);
73
+ if (!result.success) {
74
+ throw new Error(`Invalid lockfile: ${result.error.message}`);
75
+ }
76
+ return result.data;
77
+ }
78
+ /**
79
+ * Writes a lockfile to a run directory
80
+ */
81
+ export async function writeLockfile(runDir, lockfile) {
82
+ const lockfilePath = join(runDir, 'lockfile.json');
83
+ const content = JSON.stringify(lockfile, null, 2);
84
+ await writeFile(lockfilePath, content, 'utf-8');
85
+ }
86
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Immutable run directory management
3
+ *
4
+ * Manages .browserflow/ directories for storing exploration runs,
5
+ * screenshots, and generated artifacts.
6
+ *
7
+ * @see bf-92j for implementation task
8
+ */
9
+ /**
10
+ * Run directory structure:
11
+ * .browserflow/
12
+ * runs/
13
+ * <spec-name>/
14
+ * run-20260115-031000-abc123/
15
+ * exploration.json
16
+ * review.json
17
+ * lockfile.json
18
+ * artifacts/
19
+ * screenshots/
20
+ * trace.zip
21
+ * logs/
22
+ * run-20260115-041500-def456/
23
+ * ...
24
+ * latest -> run-20260115-041500-def456
25
+ * cache/
26
+ * tmp/
27
+ */
28
+ export interface RunDirectoryPaths {
29
+ root: string;
30
+ runsDir: string;
31
+ runDir: string;
32
+ lockfile: string;
33
+ screenshotsDir: string;
34
+ reviewFile: string;
35
+ }
36
+ export interface RunStore {
37
+ createRun(specName: string): Promise<string>;
38
+ getLatestRun(specName: string): string | null;
39
+ listRuns(specName: string): string[];
40
+ getRunDir(specName: string, runId: string): string;
41
+ runExists(specName: string, runId: string): boolean;
42
+ }
43
+ /**
44
+ * Generates a unique run ID.
45
+ *
46
+ * Format: run-<YYYYMMDDHHMMSS>-<random>
47
+ * Example: run-20260115031000-a3f2dd
48
+ */
49
+ export declare function createRunId(): string;
50
+ /**
51
+ * Creates a RunStore instance for a project root.
52
+ */
53
+ export declare function createRunStore(projectRoot: string): RunStore;
54
+ /**
55
+ * Gets paths for a run directory.
56
+ *
57
+ * @param projectRoot - Root of the project (where .browserflow lives)
58
+ * @param explorationId - Unique exploration identifier
59
+ * @returns Paths object
60
+ */
61
+ export declare function getRunPaths(projectRoot: string, explorationId: string): RunDirectoryPaths;
62
+ /**
63
+ * Generates a unique exploration ID.
64
+ *
65
+ * Format: <spec-slug>-<timestamp>-<random>
66
+ * Example: login-flow-20240115-143022-abc123
67
+ *
68
+ * @param specName - Name of the spec
69
+ * @returns Unique exploration ID
70
+ */
71
+ export declare function generateExplorationId(specName: string): string;
72
+ /**
73
+ * Gets the screenshot path for a step.
74
+ *
75
+ * @param screenshotsDir - Screenshots directory path
76
+ * @param stepIndex - Step index (0-based)
77
+ * @param type - "before" or "after"
78
+ * @returns Screenshot file path
79
+ */
80
+ export declare function getScreenshotPath(screenshotsDir: string, stepIndex: number, type: 'before' | 'after'): string;
81
+ //# sourceMappingURL=run-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../src/run-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACrC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACnD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACrD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAQpC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAyG5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,iBAAiB,CAazF;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAe9D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GACvB,MAAM,CAER"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Immutable run directory management
3
+ *
4
+ * Manages .browserflow/ directories for storing exploration runs,
5
+ * screenshots, and generated artifacts.
6
+ *
7
+ * @see bf-92j for implementation task
8
+ */
9
+ import { join } from 'path';
10
+ import { randomBytes } from 'crypto';
11
+ import { mkdir, symlink, unlink } from 'fs/promises';
12
+ import { existsSync, statSync, readdirSync } from 'fs';
13
+ /**
14
+ * Generates a unique run ID.
15
+ *
16
+ * Format: run-<YYYYMMDDHHMMSS>-<random>
17
+ * Example: run-20260115031000-a3f2dd
18
+ */
19
+ export function createRunId() {
20
+ const now = new Date();
21
+ const ts = now
22
+ .toISOString()
23
+ .replace(/[-:T]/g, '')
24
+ .slice(0, 14); // YYYYMMDDHHMMSS
25
+ const rand = randomBytes(3).toString('hex');
26
+ return `run-${ts}-${rand}`;
27
+ }
28
+ /**
29
+ * Creates a RunStore instance for a project root.
30
+ */
31
+ export function createRunStore(projectRoot) {
32
+ const browserflowDir = join(projectRoot, '.browserflow');
33
+ const runsDir = join(browserflowDir, 'runs');
34
+ return {
35
+ async createRun(specName) {
36
+ const specDir = join(runsDir, specName);
37
+ const runId = createRunId();
38
+ const runDir = join(specDir, runId);
39
+ // Create directory structure
40
+ await mkdir(runDir, { recursive: true });
41
+ await mkdir(join(runDir, 'artifacts', 'screenshots'), { recursive: true });
42
+ await mkdir(join(runDir, 'artifacts', 'logs'), { recursive: true });
43
+ // Update "latest" symlink atomically
44
+ const latestPath = join(specDir, 'latest');
45
+ const tempLatestPath = join(specDir, `.latest-${Date.now()}`);
46
+ try {
47
+ // Create symlink to new location
48
+ await symlink(runId, tempLatestPath);
49
+ // Atomic rename (replaces old symlink)
50
+ try {
51
+ await unlink(latestPath);
52
+ }
53
+ catch {
54
+ // Ignore if doesn't exist
55
+ }
56
+ await symlink(runId, latestPath);
57
+ await unlink(tempLatestPath);
58
+ }
59
+ catch (error) {
60
+ // Cleanup temp symlink on error
61
+ try {
62
+ await unlink(tempLatestPath);
63
+ }
64
+ catch {
65
+ // Ignore
66
+ }
67
+ throw error;
68
+ }
69
+ return runDir;
70
+ },
71
+ getLatestRun(specName) {
72
+ const specDir = join(runsDir, specName);
73
+ const latestPath = join(specDir, 'latest');
74
+ try {
75
+ // Check if latest symlink exists
76
+ if (!existsSync(latestPath)) {
77
+ return null;
78
+ }
79
+ // Read symlink target synchronously
80
+ const target = readdirSync(specDir)
81
+ .filter((name) => name.startsWith('run-'))
82
+ .map((name) => ({
83
+ name,
84
+ path: join(specDir, name),
85
+ mtime: statSync(join(specDir, name)).mtime.getTime(),
86
+ }))
87
+ .sort((a, b) => b.mtime - a.mtime)[0];
88
+ return target ? target.path : null;
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ },
94
+ listRuns(specName) {
95
+ const specDir = join(runsDir, specName);
96
+ try {
97
+ if (!existsSync(specDir)) {
98
+ return [];
99
+ }
100
+ return readdirSync(specDir)
101
+ .filter((name) => name.startsWith('run-'))
102
+ .map((name) => ({
103
+ name,
104
+ path: join(specDir, name),
105
+ mtime: statSync(join(specDir, name)).mtime.getTime(),
106
+ }))
107
+ .sort((a, b) => b.mtime - a.mtime)
108
+ .map((item) => item.path);
109
+ }
110
+ catch {
111
+ return [];
112
+ }
113
+ },
114
+ getRunDir(specName, runId) {
115
+ return join(runsDir, specName, runId);
116
+ },
117
+ runExists(specName, runId) {
118
+ const runDir = join(runsDir, specName, runId);
119
+ try {
120
+ return existsSync(runDir) && statSync(runDir).isDirectory();
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ },
126
+ };
127
+ }
128
+ /**
129
+ * Gets paths for a run directory.
130
+ *
131
+ * @param projectRoot - Root of the project (where .browserflow lives)
132
+ * @param explorationId - Unique exploration identifier
133
+ * @returns Paths object
134
+ */
135
+ export function getRunPaths(projectRoot, explorationId) {
136
+ const root = join(projectRoot, '.browserflow');
137
+ const runsDir = join(root, 'runs');
138
+ const runDir = join(runsDir, explorationId);
139
+ return {
140
+ root,
141
+ runsDir,
142
+ runDir,
143
+ lockfile: join(runDir, 'lockfile.json'),
144
+ screenshotsDir: join(runDir, 'screenshots'),
145
+ reviewFile: join(runDir, 'review.json'),
146
+ };
147
+ }
148
+ /**
149
+ * Generates a unique exploration ID.
150
+ *
151
+ * Format: <spec-slug>-<timestamp>-<random>
152
+ * Example: login-flow-20240115-143022-abc123
153
+ *
154
+ * @param specName - Name of the spec
155
+ * @returns Unique exploration ID
156
+ */
157
+ export function generateExplorationId(specName) {
158
+ const slug = specName
159
+ .toLowerCase()
160
+ .replace(/[^a-z0-9]+/g, '-')
161
+ .replace(/^-|-$/g, '')
162
+ .slice(0, 30);
163
+ const timestamp = new Date()
164
+ .toISOString()
165
+ .replace(/[-:T]/g, '')
166
+ .slice(0, 14);
167
+ const random = Math.random().toString(36).slice(2, 8);
168
+ return `${slug}-${timestamp}-${random}`;
169
+ }
170
+ /**
171
+ * Gets the screenshot path for a step.
172
+ *
173
+ * @param screenshotsDir - Screenshots directory path
174
+ * @param stepIndex - Step index (0-based)
175
+ * @param type - "before" or "after"
176
+ * @returns Screenshot file path
177
+ */
178
+ export function getScreenshotPath(screenshotsDir, stepIndex, type) {
179
+ return join(screenshotsDir, `step-${stepIndex}-${type}.png`);
180
+ }
181
+ //# sourceMappingURL=run-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-store.js","sourceRoot":"","sources":["../src/run-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Spec loading and normalization utilities
3
+ * @see bf-7ne - preconditions.page string coercion
4
+ */
5
+ import type { Preconditions, BrowserFlowSpec } from './spec-schema.js';
6
+ import type { z } from 'zod';
7
+ /**
8
+ * Normalize preconditions to handle backward-compatible formats
9
+ * Coerces string page values to object format
10
+ */
11
+ export declare function normalizePreconditions(preconditions: unknown): Preconditions;
12
+ /**
13
+ * Load and validate a spec with normalization
14
+ * Returns a Zod SafeParseReturnType for detailed error handling
15
+ */
16
+ export declare function loadSpec(rawSpec: unknown): z.SafeParseReturnType<unknown, BrowserFlowSpec>;
17
+ //# sourceMappingURL=spec-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-loader.d.ts","sourceRoot":"","sources":["../src/spec-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,OAAO,GAAG,aAAa,CAa5E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC,CAc1F"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Spec loading and normalization utilities
3
+ * @see bf-7ne - preconditions.page string coercion
4
+ */
5
+ import { specSchema } from './spec-schema.js';
6
+ /**
7
+ * Normalize preconditions to handle backward-compatible formats
8
+ * Coerces string page values to object format
9
+ */
10
+ export function normalizePreconditions(preconditions) {
11
+ if (!preconditions || typeof preconditions !== 'object') {
12
+ return {};
13
+ }
14
+ const pre = { ...preconditions };
15
+ // Coerce string page to object format
16
+ if (typeof pre.page === 'string') {
17
+ pre.page = { url: pre.page };
18
+ }
19
+ return pre;
20
+ }
21
+ /**
22
+ * Load and validate a spec with normalization
23
+ * Returns a Zod SafeParseReturnType for detailed error handling
24
+ */
25
+ export function loadSpec(rawSpec) {
26
+ if (!rawSpec || typeof rawSpec !== 'object') {
27
+ return specSchema.safeParse(rawSpec);
28
+ }
29
+ const spec = { ...rawSpec };
30
+ // Normalize preconditions if present
31
+ if (spec.preconditions) {
32
+ spec.preconditions = normalizePreconditions(spec.preconditions);
33
+ }
34
+ // Validate with Zod schema
35
+ return specSchema.safeParse(spec);
36
+ }
37
+ //# sourceMappingURL=spec-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-loader.js","sourceRoot":"","sources":["../src/spec-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,aAAsB;IAC3D,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,GAAG,aAAa,EAA6B,CAAC;IAE5D,sCAAsC;IACtC,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,GAAoB,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAA6B,CAAC;IAEvD,qCAAqC;IACrC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAClE,CAAC;IAED,2BAA2B;IAC3B,OAAO,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC"}