Skip to content

Commit a4adba7

Browse files
pranaygpclaude
andcommitted
feat: create @workflow/builders package with shared builder infrastructure
This commit extracts builder infrastructure from @workflow/cli into a new shared @workflow/builders package. This improves code organization by: - Creating a dedicated package for builder functionality - Allowing @workflow/next and @workflow/nitro to depend on builders directly - Reducing coupling between framework integrations and the CLI - Preparing for moving NextBuilder to @workflow/next in the next PR Changes: - Created new @workflow/builders package - Moved BaseBuilder, BasicBuilder, and VercelBuildOutputAPIBuilder - Moved esbuild plugins (swc, discover-entries, node-module) - Moved WorkflowConfig and BuildTarget types - Updated @workflow/cli to import from @workflow/builders - Updated @workflow/nitro to import from @workflow/builders - Re-exported types from CLI for backwards compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent ef1417a commit a4adba7

23 files changed

+1744
-43
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@workflow/builders": patch
3+
"@workflow/cli": patch
4+
"@workflow/nitro": patch
5+
---
6+
7+
Create @workflow/builders package with shared builder infrastructure

packages/builders/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# @workflow/builders
2+
3+
Shared builder infrastructure for Workflow DevKit. This package provides the base builder class and utilities used by framework-specific integrations.
4+
5+
## Overview
6+
7+
This package contains the core build logic for transforming workflow source files into deployable bundles. It is used by:
8+
9+
- `@workflow/cli` - For standalone/basic builds
10+
- `@workflow/next` - For Next.js integration
11+
- `@workflow/nitro` - For Nitro/Nuxt integration
12+
13+
## Key Components
14+
15+
- **BaseBuilder**: Abstract base class providing common build logic
16+
- **Build plugins**: esbuild plugins for workflow transformations
17+
- **SWC integration**: Compiler plugin integration for workflow directives
18+
19+
## Usage
20+
21+
This package is typically not used directly. Instead, use one of the framework-specific packages that extend `BaseBuilder`:
22+
23+
```typescript
24+
import { BaseBuilder } from '@workflow/builders';
25+
26+
class MyBuilder extends BaseBuilder {
27+
async build(): Promise<void> {
28+
// Implement builder-specific logic
29+
}
30+
}
31+
```
32+
33+
## Architecture
34+
35+
The builder system uses:
36+
37+
1. **esbuild** for bundling and tree-shaking
38+
2. **SWC** for transforming workflow directives (`"use workflow"`, `"use step"`)
39+
3. **Enhanced resolve** for TypeScript path mapping
40+
41+
## License
42+
43+
MIT

packages/builders/package.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "@workflow/builders",
3+
"version": "4.0.1-beta.3",
4+
"description": "Shared builder infrastructure for Workflow DevKit",
5+
"type": "module",
6+
"main": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
".": {
10+
"types": "./dist/index.d.ts",
11+
"default": "./dist/index.js"
12+
},
13+
"./base-builder": {
14+
"types": "./dist/base-builder.d.ts",
15+
"default": "./dist/base-builder.js"
16+
}
17+
},
18+
"files": [
19+
"dist"
20+
],
21+
"publishConfig": {
22+
"access": "public"
23+
},
24+
"license": "MIT",
25+
"repository": {
26+
"type": "git",
27+
"url": "https://github.com/vercel/workflow.git",
28+
"directory": "packages/builders"
29+
},
30+
"scripts": {
31+
"build": "tsc",
32+
"clean": "tsc --build --clean && rm -r dist ||:",
33+
"dev": "tsc --watch",
34+
"test": "vitest run src",
35+
"typecheck": "tsc --noEmit"
36+
},
37+
"devDependencies": {
38+
"@types/node": "catalog:",
39+
"@workflow/tsconfig": "workspace:*"
40+
},
41+
"dependencies": {
42+
"@swc/core": "1.11.24",
43+
"@workflow/swc-plugin": "workspace:*",
44+
"@workflow/errors": "workspace:*",
45+
"@workflow/core": "workspace:*",
46+
"builtin-modules": "^5.0.0",
47+
"chalk": "^5.6.2",
48+
"comment-json": "4.2.5",
49+
"enhanced-resolve": "5.18.2",
50+
"esbuild": "catalog:",
51+
"find-up": "7.0.0",
52+
"tinyglobby": "^0.2.14"
53+
}
54+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { transform } from '@swc/core';
2+
import { createRequire } from 'module';
3+
4+
const require = createRequire(import.meta.filename);
5+
6+
export type WorkflowManifest = {
7+
steps?: {
8+
[relativeFileName: string]: {
9+
[functionName: string]: {
10+
stepId: string;
11+
};
12+
};
13+
};
14+
workflows?: {
15+
[relativeFileName: string]: {
16+
[functionName: string]: {
17+
workflowId: string;
18+
};
19+
};
20+
};
21+
};
22+
23+
export async function applySwcTransform(
24+
filename: string,
25+
source: string,
26+
mode: 'workflow' | 'step' | 'client' | false,
27+
jscConfig?: {
28+
paths?: Record<string, string[]>;
29+
// this must be absolute path
30+
baseUrl?: string;
31+
}
32+
): Promise<{
33+
code: string;
34+
workflowManifest: WorkflowManifest;
35+
}> {
36+
// Determine if this is a TypeScript file
37+
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
38+
const isTsx = filename.endsWith('.tsx');
39+
40+
// Transform with SWC to support syntax esbuild doesn't
41+
const result = await transform(source, {
42+
filename,
43+
swcrc: false,
44+
jsc: {
45+
parser: {
46+
syntax: isTypeScript ? 'typescript' : 'ecmascript',
47+
tsx: isTsx,
48+
},
49+
target: 'es2022',
50+
experimental: mode
51+
? {
52+
plugins: [[require.resolve('@workflow/swc-plugin'), { mode }]],
53+
}
54+
: undefined,
55+
...jscConfig,
56+
},
57+
// TODO: investigate proper source map support as they
58+
// won't even be used in Node.js by default unless we
59+
// intercept errors and apply them ourselves
60+
sourceMaps: false,
61+
minify: false,
62+
});
63+
64+
const workflowCommentMatch = result.code.match(
65+
/\/\*\*__internal_workflows({.*?})\*\//s
66+
);
67+
68+
const parsedWorkflows = JSON.parse(
69+
workflowCommentMatch?.[1] || '{}'
70+
) as WorkflowManifest;
71+
72+
return {
73+
code: result.code,
74+
workflowManifest: parsedWorkflows || {},
75+
};
76+
}

0 commit comments

Comments
 (0)