Skip to content

Commit 31204e6

Browse files
committed
Normalize Workbenches
Normalize trigger scripts across workbenches fix: include hono in local build test test: include src dir for test test: add workflow dir config in test to fix sveltekit dev tests add temp 7_full in example wokrflow format fix(sveltekit): detecting workflow folders and customizable dir Remove 7_full and 1_simple error replace API symlink in webpack workbench Fix sveltekit and vite tests Fix sveltekit symlinks Test fixes Fix sveltekit workflows path Dont symlink routes in vite Include e2e tests for hono and vite fix error tests post normalization wip - attempted fixes
1 parent b97b6bf commit 31204e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+780
-131
lines changed

packages/core/e2e/dev.test.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export interface DevTestConfig {
1010
apiFileImportPath: string;
1111
/** The workflow file to modify for testing HMR. Defaults to '3_streams.ts' */
1212
testWorkflowFile?: string;
13+
/** The workflows directory relative to appPath. Defaults to 'workflows' */
14+
workflowsDir?: string;
1315
}
1416

1517
function getConfigFromEnv(): DevTestConfig | null {
@@ -39,6 +41,7 @@ export function createDevTests(config?: DevTestConfig) {
3941
finalConfig.generatedWorkflowPath
4042
);
4143
const testWorkflowFile = finalConfig.testWorkflowFile ?? '3_streams.ts';
44+
const workflowsDir = finalConfig.workflowsDir ?? 'workflows';
4245
const restoreFiles: Array<{ path: string; content: string }> = [];
4346

4447
afterEach(async () => {
@@ -55,7 +58,7 @@ export function createDevTests(config?: DevTestConfig) {
5558
});
5659

5760
test('should rebuild on workflow change', { timeout: 10_000 }, async () => {
58-
const workflowFile = path.join(appPath, 'workflows', testWorkflowFile);
61+
const workflowFile = path.join(appPath, workflowsDir, testWorkflowFile);
5962

6063
const content = await fs.readFile(workflowFile, 'utf8');
6164

@@ -83,7 +86,7 @@ export async function myNewWorkflow() {
8386
});
8487

8588
test('should rebuild on step change', { timeout: 10_000 }, async () => {
86-
const stepFile = path.join(appPath, 'workflows', testWorkflowFile);
89+
const stepFile = path.join(appPath, workflowsDir, testWorkflowFile);
8790

8891
const content = await fs.readFile(stepFile, 'utf8');
8992

@@ -114,7 +117,11 @@ export async function myNewStep() {
114117
'should rebuild on adding workflow file',
115118
{ timeout: 10_000 },
116119
async () => {
117-
const workflowFile = path.join(appPath, 'workflows', 'new-workflow.ts');
120+
const workflowFile = path.join(
121+
appPath,
122+
workflowsDir,
123+
'new-workflow.ts'
124+
);
118125

119126
await fs.writeFile(
120127
workflowFile,
@@ -132,7 +139,7 @@ export async function myNewStep() {
132139

133140
await fs.writeFile(
134141
apiFile,
135-
`import '${finalConfig.apiFileImportPath}/workflows/new-workflow';
142+
`import '${finalConfig.apiFileImportPath}/${workflowsDir}/new-workflow';
136143
${apiFileContent}`
137144
);
138145

packages/core/e2e/e2e.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ describe('e2e', () => {
9090
output: 133,
9191
});
9292
// In local vs. vercel backends, the workflow name is different, so we check for either,
93-
// since this test runs against both.
93+
// since this test runs against both. Also different workbenches have different directory structures.
9494
expect(json.workflowName).toBeOneOf([
9595
`workflow//example/${workflow.workflowFile}//${workflow.workflowFn}`,
9696
`workflow//${workflow.workflowFile}//${workflow.workflowFn}`,
97+
`workflow//src/${workflow.workflowFile}//${workflow.workflowFn}`,
9798
]);
9899
});
99100

packages/core/e2e/local-build.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe.each([
1212
'vite',
1313
'sveltekit',
1414
'nuxt',
15+
'hono',
1516
])('e2e', (project) => {
1617
test('builds without errors', { timeout: 180_000 }, async () => {
1718
// skip if we're targeting specific app to test

packages/nitro/src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,14 @@ function addVirtualHandler(nitro: Nitro, route: string, buildPath: string) {
9191
// Nitro v3+ (native web handlers)
9292
nitro.options.virtual[`#${buildPath}`] = /* js */ `
9393
import { POST } from "${join(nitro.options.buildDir, buildPath)}";
94-
export default ({ req }) => POST(req);
94+
export default async ({ req }) => {
95+
try {
96+
return await POST(req);
97+
} catch (error) {
98+
console.error('Handler error:', error);
99+
return new Response('Internal Server Error', { status: 500 });
100+
}
101+
};
95102
`;
96103
}
97104
}

packages/sveltekit/src/builder.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ async function convertSvelteKitRequest(request) {
1919

2020
export class SvelteKitBuilder extends BaseBuilder {
2121
constructor(config?: Partial<SvelteKitConfig>) {
22+
const workingDir = config?.workingDir || process.cwd();
23+
const dirs = getWorkflowDirs({ dirs: config?.dirs });
24+
2225
super({
2326
...config,
24-
dirs: ['workflows'],
27+
dirs,
2528
buildTarget: 'sveltekit' as const,
2629
stepsBundlePath: '', // unused in base
2730
workflowsBundlePath: '', // unused in base
2831
webhookBundlePath: '', // unused in base
29-
workingDir: config?.workingDir || process.cwd(),
32+
workingDir,
3033
});
3134
}
3235

@@ -229,3 +232,24 @@ export const OPTIONS = createSvelteKitHandler('OPTIONS');`
229232
}
230233
}
231234
}
235+
236+
/**
237+
* Gets the list of directories to scan for workflow files.
238+
*/
239+
export function getWorkflowDirs(options?: { dirs?: string[] }): string[] {
240+
return unique([
241+
// User-provided directories take precedence
242+
...(options?.dirs ?? []),
243+
// Scan routes directories (like Next.js does with app/pages directories)
244+
// This allows workflows to be placed anywhere in the routes tree
245+
'routes',
246+
'src/routes',
247+
// Also scan dedicated workflow directories for organization
248+
'workflows',
249+
'src/workflows',
250+
]).sort();
251+
}
252+
253+
function unique<T>(array: T[]): T[] {
254+
return Array.from(new Set(array));
255+
}

packages/sveltekit/src/plugin.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ import { resolveModulePath } from 'exsolve';
44
import type { HotUpdateOptions, Plugin } from 'vite';
55
import { SvelteKitBuilder } from './builder.js';
66

7-
export function workflowPlugin(): Plugin {
7+
export interface WorkflowPluginOptions {
8+
/**
9+
* Directories to scan for workflow files.
10+
* If not specified, defaults to ['workflows', 'src/workflows', 'routes', 'src/routes']
11+
*/
12+
dirs?: string[];
13+
}
14+
15+
export function workflowPlugin(options?: WorkflowPluginOptions): Plugin {
816
let builder: SvelteKitBuilder;
917

1018
return {
@@ -89,7 +97,9 @@ export function workflowPlugin(): Plugin {
8997
},
9098

9199
configResolved() {
92-
builder = new SvelteKitBuilder();
100+
builder = new SvelteKitBuilder({
101+
dirs: options?.dirs,
102+
});
93103
},
94104

95105
// TODO: Move this to @workflow/vite or something since this is vite specific

scripts/create-test-matrix.mjs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,19 @@ const DEV_TEST_CONFIGS = {
2929
generatedWorkflowPath: 'src/routes/.well-known/workflow/v1/flow/+server.js',
3030
apiFilePath: 'src/routes/api/chat/+server.ts',
3131
apiFileImportPath: '../../../..',
32+
workflowsDir: 'src/workflows',
3233
},
3334
vite: {
34-
generatedStepPath: 'dist/workflow/steps.mjs',
35-
generatedWorkflowPath: 'dist/workflow/workflows.mjs',
36-
apiFilePath: 'src/main.ts',
37-
apiFileImportPath: '..',
35+
generatedStepPath: '.nitro/workflow/steps.mjs',
36+
generatedWorkflowPath: '.nitro/workflow/workflows.mjs',
37+
apiFilePath: 'routes/api/trigger.post.ts',
38+
apiFileImportPath: '../..',
39+
},
40+
hono: {
41+
generatedStepPath: '.nitro/workflow/steps.mjs',
42+
generatedWorkflowPath: '.nitro/workflow/workflows.mjs',
43+
apiFilePath: 'server.ts',
44+
apiFileImportPath: '.',
3845
},
3946
};
4047

@@ -81,4 +88,16 @@ matrix.app.push({
8188
...DEV_TEST_CONFIGS.nuxt,
8289
});
8390

91+
matrix.app.push({
92+
name: 'hono',
93+
project: 'workbench-hono-workflow',
94+
...DEV_TEST_CONFIGS.hono,
95+
});
96+
97+
matrix.app.push({
98+
name: 'vite',
99+
project: 'workbench-vite-workflow',
100+
...DEV_TEST_CONFIGS.vite,
101+
});
102+
84103
console.log(JSON.stringify(matrix));
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { sleep, createWebhook } from 'workflow';
2+
3+
export async function handleUserSignup(email: string) {
4+
'use workflow';
5+
6+
const user = await createUser(email);
7+
await sendWelcomeEmail(user);
8+
9+
await sleep('5s');
10+
11+
const webhook = createWebhook();
12+
await sendOnboardingEmail(user, webhook.url);
13+
14+
await webhook;
15+
console.log('Webhook Resolved');
16+
17+
return { userId: user.id, status: 'onboarded' };
18+
}
19+
20+
async function createUser(email: string) {
21+
'use step';
22+
23+
console.log(`Creating a new user with email: ${email}`);
24+
25+
return { id: crypto.randomUUID(), email };
26+
}
27+
28+
async function sendWelcomeEmail(user: { id: string; email: string }) {
29+
'use step';
30+
31+
console.log(`Sending welcome email to user: ${user.id}`);
32+
}
33+
34+
async function sendOnboardingEmail(
35+
user: { id: string; email: string },
36+
callback: string
37+
) {
38+
'use step';
39+
40+
console.log(`Sending onboarding email to user: ${user.id}`);
41+
42+
console.log(`Click this link to resolve the webhook: ${callback}`);
43+
}

workbench/hono/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ manifest.js
44
.output
55
.data
66
.vercel
7+
_workflows.ts

workbench/hono/_workflows.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)