@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.
- package/dist/config-schema.d.ts +354 -0
- package/dist/config-schema.d.ts.map +1 -0
- package/dist/config-schema.js +83 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/config.d.ts +107 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -0
- package/dist/duration.d.ts +39 -0
- package/dist/duration.d.ts.map +1 -0
- package/dist/duration.js +111 -0
- package/dist/duration.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/locator-object.d.ts +556 -0
- package/dist/locator-object.d.ts.map +1 -0
- package/dist/locator-object.js +114 -0
- package/dist/locator-object.js.map +1 -0
- package/dist/lockfile.d.ts +1501 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +86 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/run-store.d.ts +81 -0
- package/dist/run-store.d.ts.map +1 -0
- package/dist/run-store.js +181 -0
- package/dist/run-store.js.map +1 -0
- package/dist/spec-loader.d.ts +17 -0
- package/dist/spec-loader.d.ts.map +1 -0
- package/dist/spec-loader.js +37 -0
- package/dist/spec-loader.js.map +1 -0
- package/dist/spec-schema.d.ts +1411 -0
- package/dist/spec-schema.d.ts.map +1 -0
- package/dist/spec-schema.js +239 -0
- package/dist/spec-schema.js.map +1 -0
- package/package.json +45 -0
- package/schemas/browserflow.schema.json +220 -0
- package/schemas/lockfile.schema.json +568 -0
- package/schemas/spec-v2.schema.json +413 -0
- package/src/config-schema.test.ts +190 -0
- package/src/config-schema.ts +111 -0
- package/src/config.ts +112 -0
- package/src/duration.test.ts +175 -0
- package/src/duration.ts +128 -0
- package/src/index.ts +136 -0
- package/src/json-schemas.test.ts +374 -0
- package/src/locator-object.test.ts +323 -0
- package/src/locator-object.ts +250 -0
- package/src/lockfile.test.ts +345 -0
- package/src/lockfile.ts +209 -0
- package/src/run-store.test.ts +232 -0
- package/src/run-store.ts +240 -0
- package/src/spec-loader.test.ts +181 -0
- package/src/spec-loader.ts +47 -0
- package/src/spec-schema.test.ts +360 -0
- 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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"}
|
package/dist/lockfile.js
ADDED
|
@@ -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"}
|