flowspec 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.
package/dist/init.js ADDED
@@ -0,0 +1,173 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ /**
4
+ * Default content for flowspec.config.yaml
5
+ */
6
+ export const DEFAULT_CONFIG_CONTENT = `baseUrl: http://localhost:3000
7
+ timeout: 10000
8
+ specsDir: specs/
9
+ `;
10
+ /**
11
+ * Default content for example flow file
12
+ */
13
+ export const DEFAULT_EXAMPLE_FLOW_CONTENT = `name: example-flow
14
+ description: Example flow - customize this for your app
15
+ steps:
16
+ - visit: /
17
+ expect:
18
+ - visible: Welcome
19
+ `;
20
+ /**
21
+ * Default content for Claude settings to protect specs
22
+ */
23
+ export const DEFAULT_CLAUDE_SETTINGS_CONTENT = `{
24
+ "hooks": {
25
+ "PreToolUse": [{
26
+ "matcher": { "tool": ["Edit", "Write"], "path": "specs/**/*.flow.yaml" },
27
+ "command": "echo '❌ Flow specs are immutable. Fix the implementation, not the spec.' && exit 1"
28
+ }]
29
+ }
30
+ }
31
+ `;
32
+ /**
33
+ * Safely create a directory if it doesn't exist
34
+ */
35
+ function ensureDirectory(dirPath) {
36
+ if (!existsSync(dirPath)) {
37
+ mkdirSync(dirPath, { recursive: true });
38
+ }
39
+ }
40
+ /**
41
+ * Create a file if it doesn't exist
42
+ * @returns Result indicating whether file was created or skipped
43
+ */
44
+ function createFileIfNotExists(filePath, content) {
45
+ const result = {
46
+ path: filePath,
47
+ created: false,
48
+ skipped: false,
49
+ };
50
+ try {
51
+ if (existsSync(filePath)) {
52
+ result.skipped = true;
53
+ return result;
54
+ }
55
+ // Ensure parent directory exists
56
+ const parentDir = dirname(filePath);
57
+ ensureDirectory(parentDir);
58
+ writeFileSync(filePath, content, "utf-8");
59
+ result.created = true;
60
+ }
61
+ catch (error) {
62
+ result.error =
63
+ error instanceof Error ? error.message : "Unknown error occurred";
64
+ }
65
+ return result;
66
+ }
67
+ /**
68
+ * Update package.json with test:e2e script if it exists
69
+ * @returns Result indicating whether package.json was updated
70
+ */
71
+ function updatePackageJson(projectDir) {
72
+ const packageJsonPath = join(projectDir, "package.json");
73
+ const result = {
74
+ path: packageJsonPath,
75
+ created: false,
76
+ skipped: false,
77
+ };
78
+ try {
79
+ if (!existsSync(packageJsonPath)) {
80
+ result.skipped = true;
81
+ return result;
82
+ }
83
+ const content = readFileSync(packageJsonPath, "utf-8");
84
+ const pkg = JSON.parse(content);
85
+ // Ensure scripts object exists
86
+ if (!pkg.scripts || typeof pkg.scripts !== "object") {
87
+ pkg.scripts = {};
88
+ }
89
+ const scripts = pkg.scripts;
90
+ // Check if test:e2e already exists
91
+ if (scripts["test:e2e"]) {
92
+ result.skipped = true;
93
+ return result;
94
+ }
95
+ // Add the test:e2e script
96
+ scripts["test:e2e"] = "flowspec run";
97
+ // Write back with proper formatting
98
+ writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf-8");
99
+ result.created = true;
100
+ }
101
+ catch (error) {
102
+ result.error =
103
+ error instanceof Error ? error.message : "Unknown error occurred";
104
+ }
105
+ return result;
106
+ }
107
+ /**
108
+ * Initialize FlowSpec in a project directory
109
+ * Creates configuration files and example flow
110
+ *
111
+ * @param projectDir - Directory to initialize (defaults to cwd)
112
+ * @returns Result with details about each file created
113
+ */
114
+ export function initProject(projectDir = process.cwd()) {
115
+ const files = [];
116
+ // 1. Create flowspec.config.yaml
117
+ const configResult = createFileIfNotExists(join(projectDir, "flowspec.config.yaml"), DEFAULT_CONFIG_CONTENT);
118
+ files.push(configResult);
119
+ // 2. Create specs/example.flow.yaml
120
+ const exampleFlowResult = createFileIfNotExists(join(projectDir, "specs", "example.flow.yaml"), DEFAULT_EXAMPLE_FLOW_CONTENT);
121
+ files.push(exampleFlowResult);
122
+ // 3. Create .claude/settings.local.json
123
+ const claudeSettingsResult = createFileIfNotExists(join(projectDir, ".claude", "settings.local.json"), DEFAULT_CLAUDE_SETTINGS_CONTENT);
124
+ files.push(claudeSettingsResult);
125
+ // 4. Update package.json if it exists
126
+ const packageJsonResult = updatePackageJson(projectDir);
127
+ files.push(packageJsonResult);
128
+ // Determine overall success
129
+ const success = files.every((f) => !f.error);
130
+ return { files, success };
131
+ }
132
+ /**
133
+ * Format the init result for console output
134
+ */
135
+ export function formatInitResult(result) {
136
+ const lines = [];
137
+ for (const file of result.files) {
138
+ const relativePath = file.path.includes("/")
139
+ ? file.path.split("/").slice(-2).join("/")
140
+ : file.path;
141
+ // Get just the filename or last path component
142
+ const displayPath = file.path.endsWith("package.json")
143
+ ? "Added test:e2e script to package.json"
144
+ : relativePath;
145
+ if (file.error) {
146
+ lines.push(`✗ Failed to create ${displayPath}: ${file.error}`);
147
+ }
148
+ else if (file.skipped) {
149
+ if (file.path.endsWith("package.json")) {
150
+ // Don't show anything for skipped package.json (either doesn't exist or already has script)
151
+ continue;
152
+ }
153
+ lines.push(`· Skipped ${displayPath} (already exists)`);
154
+ }
155
+ else if (file.created) {
156
+ if (file.path.endsWith("package.json")) {
157
+ lines.push(`✓ ${displayPath}`);
158
+ }
159
+ else {
160
+ lines.push(`✓ Created ${displayPath}`);
161
+ }
162
+ }
163
+ }
164
+ if (result.success) {
165
+ lines.push("");
166
+ lines.push("FlowSpec initialized! Next steps:");
167
+ lines.push(" 1. Edit specs/example.flow.yaml for your app");
168
+ lines.push(" 2. Start your app on http://localhost:3000");
169
+ lines.push(" 3. Run: flowspec run");
170
+ }
171
+ return lines.join("\n");
172
+ }
173
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type FlowSpec } from "./types";
2
+ /**
3
+ * Parse a YAML string into a FlowSpec object
4
+ * @param yamlContent - The YAML string to parse
5
+ * @returns The parsed FlowSpec
6
+ * @throws Error if YAML is invalid or doesn't match FlowSpec schema
7
+ */
8
+ export declare function parseFlowSpec(yamlContent: string): FlowSpec;
9
+ /**
10
+ * Read and parse a YAML flow file
11
+ * @param filePath - Path to the YAML file
12
+ * @returns The parsed FlowSpec
13
+ * @throws Error if file not found, YAML is invalid, or doesn't match FlowSpec schema
14
+ */
15
+ export declare function parseFlowFile(filePath: string): FlowSpec;
16
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,SAAS,CAAC;AAaxD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAqB3D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAaxD"}
package/dist/parser.js ADDED
@@ -0,0 +1,56 @@
1
+ import { readFileSync } from "node:fs";
2
+ import yaml from "js-yaml";
3
+ import { FlowSpecSchema } from "./types";
4
+ /**
5
+ * Format a Zod validation error into a human-readable message
6
+ */
7
+ function formatZodError(error) {
8
+ const issues = error.issues.map((issue) => {
9
+ const path = issue.path.length > 0 ? issue.path.join(".") : "root";
10
+ return `${path}: ${issue.message}`;
11
+ });
12
+ return `Schema validation failed: ${issues.join("; ")}`;
13
+ }
14
+ /**
15
+ * Parse a YAML string into a FlowSpec object
16
+ * @param yamlContent - The YAML string to parse
17
+ * @returns The parsed FlowSpec
18
+ * @throws Error if YAML is invalid or doesn't match FlowSpec schema
19
+ */
20
+ export function parseFlowSpec(yamlContent) {
21
+ let parsed;
22
+ try {
23
+ parsed = yaml.load(yamlContent);
24
+ }
25
+ catch (error) {
26
+ if (error instanceof yaml.YAMLException) {
27
+ throw new Error(`Invalid YAML syntax at line ${error.mark?.line ?? "unknown"}, column ${error.mark?.column ?? "unknown"}: ${error.reason}`);
28
+ }
29
+ throw error;
30
+ }
31
+ const result = FlowSpecSchema.safeParse(parsed);
32
+ if (!result.success) {
33
+ throw new Error(formatZodError(result.error));
34
+ }
35
+ return result.data;
36
+ }
37
+ /**
38
+ * Read and parse a YAML flow file
39
+ * @param filePath - Path to the YAML file
40
+ * @returns The parsed FlowSpec
41
+ * @throws Error if file not found, YAML is invalid, or doesn't match FlowSpec schema
42
+ */
43
+ export function parseFlowFile(filePath) {
44
+ let content;
45
+ try {
46
+ content = readFileSync(filePath, "utf-8");
47
+ }
48
+ catch (error) {
49
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
50
+ throw new Error(`File not found: ${filePath}`);
51
+ }
52
+ throw error;
53
+ }
54
+ return parseFlowSpec(content);
55
+ }
56
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,OAAO,EAAiB,cAAc,EAAE,MAAM,SAAS,CAAC;AAExD;;GAEG;AACH,SAAS,cAAc,CAAC,KAAe;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACnE,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,OAAO,6BAA6B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,MAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,IAAI,CAAC,aAAa,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CACb,+BAA+B,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,SAAS,YAAY,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,CAC3H,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEhD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,IAAI,OAAe,CAAC;IAEpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { FlowError, FlowResult } from "./types";
2
+ /**
3
+ * Format a FlowError into a human-readable string
4
+ * @param error - The FlowError to format
5
+ * @returns Formatted error message
6
+ */
7
+ export declare function formatError(error: FlowError): string;
8
+ /**
9
+ * Format a single FlowResult for terminal output
10
+ * Shows checkmark and duration for success, X with error details for failure
11
+ * @param result - The FlowResult to format
12
+ * @returns Formatted result string with ANSI colors
13
+ */
14
+ export declare function formatResult(result: FlowResult): string;
15
+ /**
16
+ * Format multiple FlowResults into a summary line
17
+ * Shows total, passed, and failed counts
18
+ * @param results - Array of FlowResults to summarize
19
+ * @returns Formatted summary string
20
+ */
21
+ export declare function formatSummary(results: FlowResult[]): string;
22
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAc,MAAM,SAAS,CAAC;AAqCjE;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAUpD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAoBvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAQ3D"}
@@ -0,0 +1,80 @@
1
+ // ANSI color codes
2
+ const GREEN = "\x1b[32m";
3
+ const RED = "\x1b[31m";
4
+ const RESET = "\x1b[0m";
5
+ /**
6
+ * Format duration for display
7
+ * Uses seconds for durations >= 1000ms, otherwise milliseconds
8
+ */
9
+ function formatDuration(ms) {
10
+ if (ms >= 1000) {
11
+ return `${ms / 1000}s`;
12
+ }
13
+ return `${ms}ms`;
14
+ }
15
+ /**
16
+ * Format a StepAction into a human-readable string
17
+ */
18
+ function formatAction(action) {
19
+ if ("visit" in action) {
20
+ return `visit "${action.visit}"`;
21
+ }
22
+ if ("click" in action) {
23
+ return `click "${action.click}"`;
24
+ }
25
+ if ("fill" in action) {
26
+ return "fill";
27
+ }
28
+ if ("select" in action) {
29
+ return "select";
30
+ }
31
+ return "unknown action";
32
+ }
33
+ /**
34
+ * Format a FlowError into a human-readable string
35
+ * @param error - The FlowError to format
36
+ * @returns Formatted error message
37
+ */
38
+ export function formatError(error) {
39
+ const parts = [];
40
+ if (error.step !== undefined && error.action) {
41
+ parts.push(`Step ${error.step}: ${formatAction(error.action)}`);
42
+ }
43
+ parts.push(`Error: ${error.message}`);
44
+ return parts.join("\n ");
45
+ }
46
+ /**
47
+ * Format a single FlowResult for terminal output
48
+ * Shows checkmark and duration for success, X with error details for failure
49
+ * @param result - The FlowResult to format
50
+ * @returns Formatted result string with ANSI colors
51
+ */
52
+ export function formatResult(result) {
53
+ const duration = formatDuration(result.duration);
54
+ if (result.success) {
55
+ return `${GREEN}✓ ${result.flowName} (${duration})${RESET}`;
56
+ }
57
+ const lines = [];
58
+ lines.push(`${RED}✗ ${result.flowName} (${duration})${RESET}`);
59
+ if (result.error) {
60
+ if (result.error.step !== undefined && result.error.action) {
61
+ lines.push(` Step ${result.error.step}: ${formatAction(result.error.action)}`);
62
+ }
63
+ lines.push(` Error: ${result.error.message}`);
64
+ }
65
+ return lines.join("\n");
66
+ }
67
+ /**
68
+ * Format multiple FlowResults into a summary line
69
+ * Shows total, passed, and failed counts
70
+ * @param results - Array of FlowResults to summarize
71
+ * @returns Formatted summary string
72
+ */
73
+ export function formatSummary(results) {
74
+ const total = results.length;
75
+ const passed = results.filter((r) => r.success).length;
76
+ const failed = total - passed;
77
+ const flowWord = total === 1 ? "flow" : "flows";
78
+ return `${total} ${flowWord}: ${passed} passed, ${failed} failed`;
79
+ }
80
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { FlowResult, FlowSpec } from "./types";
2
+ /**
3
+ * Options for flow execution
4
+ */
5
+ export interface RunnerOptions {
6
+ baseUrl?: string;
7
+ timeout?: number;
8
+ }
9
+ /**
10
+ * Default timeout for assertion retries (in milliseconds)
11
+ */
12
+ export declare const DEFAULT_TIMEOUT = 5000;
13
+ /**
14
+ * Interval between retry attempts (in milliseconds)
15
+ */
16
+ export declare const POLL_INTERVAL = 250;
17
+ /**
18
+ * Execute a flow specification and return the result
19
+ * @param flow - The FlowSpec to execute
20
+ * @param options - Optional runner configuration
21
+ * @returns Promise resolving to the FlowResult
22
+ */
23
+ export declare function runFlow(flow: FlowSpec, options?: RunnerOptions): Promise<FlowResult>;
24
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACV,QAAQ,EAGT,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,aAAa,MAAM,CAAC;AA4bjC;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,QAAQ,EACd,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,UAAU,CAAC,CAuDrB"}