diff --git a/.changeset/expose-public-manifest.md b/.changeset/expose-public-manifest.md new file mode 100644 index 0000000000..34904e4ae1 --- /dev/null +++ b/.changeset/expose-public-manifest.md @@ -0,0 +1,5 @@ +--- +"@workflow/nitro": patch +--- + +Fix Nitro prod builds: use a physical handler file with inlined manifest content instead of a virtual module with `readFileSync` that referenced an absolute build-machine path diff --git a/packages/core/e2e/bench.bench.ts b/packages/core/e2e/bench.bench.ts index 26463c065b..b31ead016f 100644 --- a/packages/core/e2e/bench.bench.ts +++ b/packages/core/e2e/bench.bench.ts @@ -14,15 +14,6 @@ if (!deploymentUrl) { throw new Error('`DEPLOYMENT_URL` environment variable is not set'); } -console.log('[bench] deploymentUrl:', deploymentUrl); -console.log('[bench] isLocalDeployment:', isLocalDeployment()); -console.log('[bench] WORKFLOW_VERCEL_ENV:', process.env.WORKFLOW_VERCEL_ENV); -console.log('[bench] VERCEL_DEPLOYMENT_ID:', process.env.VERCEL_DEPLOYMENT_ID); -console.log( - '[bench] WORKFLOW_TARGET_WORLD:', - process.env.WORKFLOW_TARGET_WORLD -); - // Configure the World for the bench runner process (same as e2e tests) if (isLocalDeployment()) { process.env.WORKFLOW_LOCAL_BASE_URL = deploymentUrl; @@ -31,19 +22,12 @@ if (isLocalDeployment()) { const isNextJs = appName.includes('nextjs') || appName.includes('next-'); const dataDirName = isNextJs ? '.next/workflow-data' : '.workflow-data'; process.env.WORKFLOW_LOCAL_DATA_DIR = path.join(appPath, dataDirName); - console.log( - '[bench] configured local world, dataDir:', - process.env.WORKFLOW_LOCAL_DATA_DIR - ); } else if (process.env.WORKFLOW_VERCEL_ENV) { if (!process.env.VERCEL_DEPLOYMENT_ID) { throw new Error( 'VERCEL_DEPLOYMENT_ID is required for Vercel benchmarks but is not set' ); } - console.log('[bench] configured for Vercel world'); -} else { - console.log('[bench] no special world configuration'); } // Manifest type and helpers (same as e2e tests) @@ -61,22 +45,15 @@ let cachedManifest: WorkflowManifest | null = null; async function fetchManifest(): Promise { if (cachedManifest) return cachedManifest; const url = new URL('/.well-known/workflow/v1/manifest.json', deploymentUrl); - console.log('[bench] fetching manifest from:', url.toString()); const res = await fetch(url, { headers: getProtectionBypassHeaders(), signal: AbortSignal.timeout(30_000), - redirect: 'follow', }); - console.log('[bench] manifest response status:', res.status, 'url:', res.url); if (!res.ok) { const text = await res.text(); throw new Error(`Failed to fetch manifest: ${res.status} ${text}`); } cachedManifest = (await res.json()) as WorkflowManifest; - console.log( - '[bench] manifest loaded, workflows:', - Object.keys(cachedManifest.workflows).join(', ') - ); return cachedManifest; } @@ -133,27 +110,6 @@ const bufferedTimings: Map< { run: any; extra?: { firstByteTimeMs?: number; slurpTimeMs?: number } }[] > = new Map(); -/** - * Await run.returnValue with a timeout to prevent benchmarks from hanging. - */ -async function awaitReturnValue( - run: Run, - timeoutMs = 120_000 -): Promise { - const timeout = new Promise((_, reject) => - setTimeout( - () => - reject( - new Error( - `run.returnValue timed out after ${timeoutMs}ms for run ${run.runId}` - ) - ), - timeoutMs - ) - ); - return Promise.race([run.returnValue, timeout]); -} - /** * Collect run timing metadata from a completed run. */ @@ -328,14 +284,8 @@ describe('Workflow Performance Benchmarks', () => { bench( 'workflow with no steps', async () => { - console.log('[bench] resolving workflow metadata...'); - const wf = await benchWf('noStepsWorkflow'); - console.log('[bench] calling start() with workflowId:', wf.workflowId); - const run = await start(wf, [42]); - console.log('[bench] start() returned, runId:', run.runId); - console.log('[bench] awaiting returnValue...'); - await awaitReturnValue(run); - console.log('[bench] returnValue resolved'); + const run = await start(await benchWf('noStepsWorkflow'), [42]); + await run.returnValue; const timings = await getRunTimings(run); stageTiming('workflow with no steps', timings); }, @@ -346,7 +296,7 @@ describe('Workflow Performance Benchmarks', () => { 'workflow with 1 step', async () => { const run = await start(await benchWf('oneStepWorkflow'), [100]); - await awaitReturnValue(run); + await run.returnValue; const timings = await getRunTimings(run); stageTiming('workflow with 1 step', timings); }, @@ -374,7 +324,7 @@ describe('Workflow Performance Benchmarks', () => { const run = await start(await benchWf('sequentialStepsWorkflow'), [ count, ]); - await awaitReturnValue(run); + await run.returnValue; const timings = await getRunTimings(run); stageTiming(name, timings); }, @@ -386,7 +336,7 @@ describe('Workflow Performance Benchmarks', () => { 'workflow with stream', async () => { const run = await start(await benchWf('streamWorkflow'), []); - const value = await awaitReturnValue(run); + const value = await run.returnValue; const timings = await getRunTimings(run); // Consume the entire stream and track: // - firstByteTimeMs: time from workflow start to first byte @@ -446,7 +396,7 @@ describe('Workflow Performance Benchmarks', () => { name, async () => { const run = await start(await benchWf(workflow), [count]); - await awaitReturnValue(run); + await run.returnValue; const timings = await getRunTimings(run); stageTiming(name, timings); }, diff --git a/packages/core/e2e/e2e.test.ts b/packages/core/e2e/e2e.test.ts index 1a1cda759d..e6889123fc 100644 --- a/packages/core/e2e/e2e.test.ts +++ b/packages/core/e2e/e2e.test.ts @@ -3,7 +3,14 @@ import fs from 'fs'; import path from 'path'; import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'; import type { Run } from '../src/runtime'; -import { getRun, start } from '../src/runtime'; +import { + getHookByToken, + getRun, + getWorld, + healthCheck, + resumeHook, + start, +} from '../src/runtime'; import { cliHealthJson, cliInspectJson, @@ -323,51 +330,37 @@ describe('e2e', () => { const run = await start(await e2e('hookWorkflow'), [token, customData]); - // Wait a few seconds so that the webhook is registered. + // Wait a few seconds so that the hook is registered. // TODO: make this more efficient when we add subscription support. await new Promise((resolve) => setTimeout(resolve, 5_000)); - const hookUrl = new URL('/api/hook', deploymentUrl); - - let res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ token, data: { message: 'one' } }), + // Look up the hook and resume it with the first payload + let hook = await getHookByToken(token); + expect(hook.runId).toBe(run.runId); + await resumeHook(hook, { + message: 'one', + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); - let body = await res.json(); - expect(body.runId).toBe(run.runId); // Invalid token test - res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ token: 'invalid' }), - }); - // NOTE: For Nitro apps (Vite, Hono, etc.) in dev mode, status 404 does some - // unexpected stuff and could return a Vite SPA fallback or can cause a Hono route to hang. - // This is because Nitro passes the 404 requests to the dev server to handle. - expect(res.status).toBeOneOf([404, 422]); - body = await res.json(); - expect(body).toBeNull(); - - res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ token, data: { message: 'two' } }), + await expect(getHookByToken('invalid')).rejects.toThrow(/not found/i); + + // Resume with second payload + hook = await getHookByToken(token); + expect(hook.runId).toBe(run.runId); + await resumeHook(hook, { + message: 'two', + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); - body = await res.json(); - expect(body.runId).toBe(run.runId); - res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ token, data: { message: 'three', done: true } }), + // Resume with third (final) payload + hook = await getHookByToken(token); + expect(hook.runId).toBe(run.runId); + await resumeHook(hook, { + message: 'three', + done: true, + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); - body = await res.json(); - expect(body.runId).toBe(run.runId); const returnValue = await run.returnValue; expect(returnValue).toBeInstanceOf(Array); @@ -961,20 +954,13 @@ describe('e2e', () => { await new Promise((resolve) => setTimeout(resolve, 5_000)); // Send payload to first workflow - const hookUrl = new URL('/api/hook', deploymentUrl); - let res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ - token, - data: { message: 'test-message-1', customData }, - }), + let hook = await getHookByToken(token); + expect(hook.runId).toBe(run1.runId); + await resumeHook(hook, { + message: 'test-message-1', + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); - let body = await res.json(); - expect(body.runId).toBe(run1.runId); - // Get first workflow result const run1Result = await run1.returnValue; expect(run1Result).toMatchObject({ @@ -993,19 +979,13 @@ describe('e2e', () => { await new Promise((resolve) => setTimeout(resolve, 5_000)); // Send payload to second workflow using same token - res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ - token, - data: { message: 'test-message-2', customData }, - }), + hook = await getHookByToken(token); + expect(hook.runId).toBe(run2.runId); + await resumeHook(hook, { + message: 'test-message-2', + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); - body = await res.json(); - expect(body.runId).toBe(run2.runId); - // Get second workflow result const run2Result = await run2.returnValue; expect(run2Result).toMatchObject({ @@ -1059,16 +1039,11 @@ describe('e2e', () => { expect(run2Data.status).toBe('failed'); // Now send a payload to complete workflow 1 - const hookUrl = new URL('/api/hook', deploymentUrl); - const res = await fetch(hookUrl, { - method: 'POST', - headers: getProtectionBypassHeaders(), - body: JSON.stringify({ - token, - data: { message: 'test-concurrent', customData }, - }), + const hook = await getHookByToken(token); + await resumeHook(hook, { + message: 'test-concurrent', + customData: (hook.metadata as any)?.customData, }); - expect(res.status).toBe(200); // Verify workflow 1 completed successfully const run1Result = await run1.returnValue; @@ -1250,35 +1225,19 @@ describe('e2e', () => { 'health check (queue-based) - workflow and step endpoints respond to health check messages', { timeout: 60_000 }, async () => { - // NOTE: This tests the queue-based health check using healthCheck() function. - // This approach bypasses Vercel Deployment Protection by sending messages + // Tests the queue-based health check using healthCheck() directly. + // This bypasses Vercel Deployment Protection by sending messages // through the Queue infrastructure rather than direct HTTP. - const url = new URL('/api/test-health-check', deploymentUrl); + const world = getWorld(); // Test workflow endpoint health check - const workflowRes = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...getProtectionBypassHeaders(), - }, - body: JSON.stringify({ endpoint: 'workflow', timeout: 30000 }), + const workflowResult = await healthCheck(world, 'workflow', { + timeout: 30000, }); - expect(workflowRes.status).toBe(200); - const workflowResult = await workflowRes.json(); expect(workflowResult.healthy).toBe(true); // Test step endpoint health check - const stepRes = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...getProtectionBypassHeaders(), - }, - body: JSON.stringify({ endpoint: 'step', timeout: 30000 }), - }); - expect(stepRes.status).toBe(200); - const stepResult = await stepRes.json(); + const stepResult = await healthCheck(world, 'step', { timeout: 30000 }); expect(stepResult.healthy).toBe(true); } ); diff --git a/workbench/astro/src/pages/api/hook.ts b/workbench/astro/src/pages/api/hook.ts deleted file mode 100644 index afaa46ddca..0000000000 --- a/workbench/astro/src/pages/api/hook.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { APIRoute } from 'astro'; -import { getHookByToken, resumeHook } from 'workflow/api'; - -export const POST: APIRoute = async ({ request }: { request: Request }) => { - const { token, data } = await request.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}; - -export const prerender = false; diff --git a/workbench/astro/src/pages/api/test-health-check.ts b/workbench/astro/src/pages/api/test-health-check.ts deleted file mode 100644 index a340a71d14..0000000000 --- a/workbench/astro/src/pages/api/test-health-check.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export async function POST({ request }: { request: Request }) { - try { - const body = await request.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -} - -export const prerender = false; diff --git a/workbench/example/api/hook.ts b/workbench/example/api/hook.ts deleted file mode 100644 index 4a28822c67..0000000000 --- a/workbench/example/api/hook.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getHookByToken, resumeHook } from 'workflow/api'; - -export const POST = async (request: Request) => { - const { token, data } = await request.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}; diff --git a/workbench/example/api/test-health-check.ts b/workbench/example/api/test-health-check.ts deleted file mode 100644 index d838392cd2..0000000000 --- a/workbench/example/api/test-health-check.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export async function POST(req: Request) { - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -} diff --git a/workbench/express/src/index.ts b/workbench/express/src/index.ts index 39099a0bc1..d5a69f6d11 100644 --- a/workbench/express/src/index.ts +++ b/workbench/express/src/index.ts @@ -1,6 +1,4 @@ import express from 'express'; -import { getHookByToken, resumeHook } from 'workflow/api'; -import { getWorld, healthCheck } from 'workflow/runtime'; // Side-effect import to keep _workflows in Nitro's dependency graph for HMR import '../_workflows.js'; @@ -10,54 +8,6 @@ app.use(express.json()); app.use(express.text({ type: 'text/*' })); app.use(express.raw({ type: 'application/octet-stream' })); -app.post('/api/hook', async (req, res) => { - const { token, data } = JSON.parse(req.body); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 422 assuming it's the "invalid" token test case - // NOTE: Need to return 422 because Nitro passes 404 requests to the dev server to handle. - return res.status(422).json(null); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return res.json(hook); -}); - -app.post('/api/test-health-check', async (req, res) => { - // This route tests the queue-based health check functionality - try { - const { endpoint = 'workflow', timeout = 30000 } = req.body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return res.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return res.status(500).json({ - healthy: false, - error: error instanceof Error ? error.message : String(error), - }); - } -}); - app.post('/api/test-direct-step-call', async (req, res) => { // This route tests calling step functions directly outside of any workflow context // After the SWC compiler changes, step functions in client mode have their directive removed diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 983b0f3c0a..77bcae0786 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -1,8 +1,6 @@ import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; import Fastify from 'fastify'; -import { getHookByToken, resumeHook } from 'workflow/api'; -import { getWorld, healthCheck } from 'workflow/runtime'; // Side-effect import to keep _workflows in Nitro's dependency graph for HMR import '../_workflows.js'; @@ -50,52 +48,6 @@ server.get('/', async (req, reply) => { return reply.type('text/html').send(html); }); -server.post('/api/hook', async (req: any, reply) => { - const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; - const { token, data } = body; - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - return reply.code(422).send(null); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return hook; -}); - -server.post('/api/test-health-check', async (req: any, reply) => { - // This route tests the queue-based health check functionality - try { - const { endpoint = 'workflow', timeout = 30000 } = req.body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return reply.send(result); - } catch (error) { - console.error('Health check test failed:', error); - return reply.code(500).send({ - healthy: false, - error: error instanceof Error ? error.message : String(error), - }); - } -}); - server.post('/api/test-direct-step-call', async (req: any, reply) => { // This route tests calling step functions directly outside of any workflow context // After the SWC compiler changes, step functions in client mode have their directive removed diff --git a/workbench/hono/src/index.ts b/workbench/hono/src/index.ts index f0c83c91e4..d5724781f1 100644 --- a/workbench/hono/src/index.ts +++ b/workbench/hono/src/index.ts @@ -1,63 +1,9 @@ import { Hono } from 'hono'; -import { getHookByToken, resumeHook } from 'workflow/api'; -import { getWorld, healthCheck } from 'workflow/runtime'; // Side-effect import to keep _workflows in Nitro's dependency graph for HMR import '../_workflows.js'; const app = new Hono(); -app.post('/api/hook', async ({ req }) => { - const { token, data } = await req.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 422 assuming it's the "invalid" token test case - // NOTE: Need to return 422 because Nitro passes 404 requests to the dev server to handle. - return Response.json(null, { status: 422 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}); - -app.post('/api/test-health-check', async ({ req }) => { - // This route tests the queue-based health check functionality - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -}); - app.post('/api/test-direct-step-call', async ({ req }) => { // This route tests calling step functions directly outside of any workflow context // After the SWC compiler changes, step functions in client mode have their directive removed diff --git a/workbench/nest/src/app.controller.ts b/workbench/nest/src/app.controller.ts index 200e881168..9ddb333238 100644 --- a/workbench/nest/src/app.controller.ts +++ b/workbench/nest/src/app.controller.ts @@ -1,77 +1,7 @@ -import { - Body, - Controller, - HttpCode, - HttpException, - HttpStatus, - Post, - Res, -} from '@nestjs/common'; -import type { Response } from 'express'; -import { getHookByToken, resumeHook } from 'workflow/api'; -import { getWorld, healthCheck } from 'workflow/runtime'; +import { Body, Controller, Post } from '@nestjs/common'; @Controller('api') export class AppController { - @Post('hook') - async resumeWorkflowHook( - @Body() body: { token: string; data: any } | string, - @Res() res: Response - ) { - // Handle body as string (when Content-Type is not application/json) or object - const parsedBody = typeof body === 'string' ? JSON.parse(body) : body; - const { token, data } = parsedBody; - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // Return 422 for invalid token with null body (matching other workbench apps) - return res.status(HttpStatus.UNPROCESSABLE_ENTITY).json(null); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return res.status(HttpStatus.OK).json(hook); - } - - @Post('test-health-check') - @HttpCode(HttpStatus.OK) - async testHealthCheck(@Body() body: { endpoint?: string; timeout?: number }) { - // This route tests the queue-based health check functionality - try { - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint as 'workflow' | 'step', { - timeout, - }); - - console.log(`Health check result:`, result); - - return result; - } catch (error) { - console.error('Health check test failed:', error); - throw new HttpException( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - } - @Post('test-direct-step-call') async invokeStepDirectly(@Body() body: { x: number; y: number }) { // This route tests calling step functions directly outside of any workflow context diff --git a/workbench/nextjs-turbopack/app/api/hook/route.ts b/workbench/nextjs-turbopack/app/api/hook/route.ts deleted file mode 120000 index 9c04d38009..0000000000 --- a/workbench/nextjs-turbopack/app/api/hook/route.ts +++ /dev/null @@ -1 +0,0 @@ -../../../../example/api/hook.ts \ No newline at end of file diff --git a/workbench/nextjs-turbopack/app/api/test-health-check/route.ts b/workbench/nextjs-turbopack/app/api/test-health-check/route.ts deleted file mode 100644 index d838392cd2..0000000000 --- a/workbench/nextjs-turbopack/app/api/test-health-check/route.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export async function POST(req: Request) { - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -} diff --git a/workbench/nextjs-webpack/app/api/hook/route.ts b/workbench/nextjs-webpack/app/api/hook/route.ts deleted file mode 100644 index 4a28822c67..0000000000 --- a/workbench/nextjs-webpack/app/api/hook/route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getHookByToken, resumeHook } from 'workflow/api'; - -export const POST = async (request: Request) => { - const { token, data } = await request.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}; diff --git a/workbench/nextjs-webpack/app/api/test-health-check/route.ts b/workbench/nextjs-webpack/app/api/test-health-check/route.ts deleted file mode 100644 index d838392cd2..0000000000 --- a/workbench/nextjs-webpack/app/api/test-health-check/route.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export async function POST(req: Request) { - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -} diff --git a/workbench/nitro-v2/server/api/hook.post.ts b/workbench/nitro-v2/server/api/hook.post.ts deleted file mode 100644 index 52aba06762..0000000000 --- a/workbench/nitro-v2/server/api/hook.post.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { defineEventHandler, readRawBody } from 'h3'; -import { getHookByToken, resumeHook } from 'workflow/api'; - -export default defineEventHandler(async (event) => { - const body = await readRawBody(event); - const { token, data } = JSON.parse(body as string); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}); diff --git a/workbench/nitro-v2/server/api/test-health-check.post.ts b/workbench/nitro-v2/server/api/test-health-check.post.ts deleted file mode 100644 index 4e48e30b7f..0000000000 --- a/workbench/nitro-v2/server/api/test-health-check.post.ts +++ /dev/null @@ -1,29 +0,0 @@ -// This route tests the queue-based health check functionality - -import { defineEventHandler, readRawBody } from 'h3'; -import { getWorld, healthCheck } from 'workflow/runtime'; - -export default defineEventHandler(async (event) => { - try { - const rawBody = await readRawBody(event); - const body = rawBody ? JSON.parse(rawBody) : {}; - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return result; - } catch (error) { - console.error('Health check test failed:', error); - return { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }; - } -}); diff --git a/workbench/nitro-v3/routes/api/hook.post.ts b/workbench/nitro-v3/routes/api/hook.post.ts deleted file mode 100644 index 6578a4af14..0000000000 --- a/workbench/nitro-v3/routes/api/hook.post.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getHookByToken, resumeHook } from 'workflow/api'; - -export default async ({ req }: { req: Request }) => { - const { token, data } = await req.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}; diff --git a/workbench/nitro-v3/routes/api/test-health-check.post.ts b/workbench/nitro-v3/routes/api/test-health-check.post.ts deleted file mode 100644 index 86222b7a32..0000000000 --- a/workbench/nitro-v3/routes/api/test-health-check.post.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export default async ({ req }: { req: Request }) => { - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -}; diff --git a/workbench/nuxt/server/api/hook.post.ts b/workbench/nuxt/server/api/hook.post.ts deleted file mode 100644 index 52aba06762..0000000000 --- a/workbench/nuxt/server/api/hook.post.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { defineEventHandler, readRawBody } from 'h3'; -import { getHookByToken, resumeHook } from 'workflow/api'; - -export default defineEventHandler(async (event) => { - const body = await readRawBody(event); - const { token, data } = JSON.parse(body as string); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return Response.json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}); diff --git a/workbench/nuxt/server/api/test-health-check.post.ts b/workbench/nuxt/server/api/test-health-check.post.ts deleted file mode 100644 index 4e48e30b7f..0000000000 --- a/workbench/nuxt/server/api/test-health-check.post.ts +++ /dev/null @@ -1,29 +0,0 @@ -// This route tests the queue-based health check functionality - -import { defineEventHandler, readRawBody } from 'h3'; -import { getWorld, healthCheck } from 'workflow/runtime'; - -export default defineEventHandler(async (event) => { - try { - const rawBody = await readRawBody(event); - const body = rawBody ? JSON.parse(rawBody) : {}; - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return result; - } catch (error) { - console.error('Health check test failed:', error); - return { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }; - } -}); diff --git a/workbench/sveltekit/src/routes/api/hook/+server.ts b/workbench/sveltekit/src/routes/api/hook/+server.ts deleted file mode 100644 index a0254e560a..0000000000 --- a/workbench/sveltekit/src/routes/api/hook/+server.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { json, type RequestHandler } from '@sveltejs/kit'; -import { getHookByToken, resumeHook } from 'workflow/api'; - -export const POST: RequestHandler = async ({ - request, -}: { - request: Request; -}) => { - const { token, data } = await request.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 404 assuming it's the "invalid" token test case - return json(null, { status: 404 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return json(hook); -}; diff --git a/workbench/sveltekit/src/routes/api/test-health-check/+server.ts b/workbench/sveltekit/src/routes/api/test-health-check/+server.ts deleted file mode 100644 index c68147a822..0000000000 --- a/workbench/sveltekit/src/routes/api/test-health-check/+server.ts +++ /dev/null @@ -1,31 +0,0 @@ -// This route tests the queue-based health check functionality - -import type { RequestHandler } from '@sveltejs/kit'; -import { getWorld, healthCheck } from 'workflow/runtime'; - -export const POST: RequestHandler = async ({ request }) => { - try { - const body = await request.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -}; diff --git a/workbench/vite/routes/api/hook.post.ts b/workbench/vite/routes/api/hook.post.ts deleted file mode 100644 index ecbdc636cd..0000000000 --- a/workbench/vite/routes/api/hook.post.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { getHookByToken, resumeHook } from 'workflow/api'; - -export default async ({ req }: { req: Request }) => { - const { token, data } = await req.json(); - - let hook: Awaited>; - try { - hook = await getHookByToken(token); - console.log('hook', hook); - } catch (error) { - console.log('error during getHookByToken', error); - // TODO: `WorkflowAPIError` is not exported, so for now - // we'll return 422 assuming it's the "invalid" token test case - // NOTE: Need to return 422 because Nitro passes 404 requests to the dev server to handle. - return Response.json(null, { status: 422 }); - } - - await resumeHook(hook.token, { - ...data, - // @ts-expect-error metadata is not typed - customData: hook.metadata?.customData, - }); - - return Response.json(hook); -}; diff --git a/workbench/vite/routes/api/test-health-check.post.ts b/workbench/vite/routes/api/test-health-check.post.ts deleted file mode 100644 index 86222b7a32..0000000000 --- a/workbench/vite/routes/api/test-health-check.post.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This route tests the queue-based health check functionality - -import { getWorld, healthCheck } from 'workflow/runtime'; - -export default async ({ req }: { req: Request }) => { - try { - const body = await req.json(); - const { endpoint = 'workflow', timeout = 30000 } = body; - - console.log( - `Testing queue-based health check for endpoint: ${endpoint}, timeout: ${timeout}ms` - ); - - const world = getWorld(); - const result = await healthCheck(world, endpoint, { timeout }); - - console.log(`Health check result:`, result); - - return Response.json(result); - } catch (error) { - console.error('Health check test failed:', error); - return Response.json( - { - healthy: false, - error: error instanceof Error ? error.message : String(error), - }, - { status: 500 } - ); - } -};