From 9fea22135a905d08dcbe333c24241f76a39e349a Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:16:37 +0400 Subject: [PATCH 01/60] init Signed-off-by: Sree Narayanan --- workbench/fastify-nitro/.gitignore | 26 +++ workbench/fastify-nitro/nitro.config.ts | 9 + workbench/fastify-nitro/package.json | 25 +++ workbench/fastify-nitro/src/index.ts | 222 ++++++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 workbench/fastify-nitro/.gitignore create mode 100644 workbench/fastify-nitro/nitro.config.ts create mode 100644 workbench/fastify-nitro/package.json create mode 100644 workbench/fastify-nitro/src/index.ts diff --git a/workbench/fastify-nitro/.gitignore b/workbench/fastify-nitro/.gitignore new file mode 100644 index 000000000..f1af274f2 --- /dev/null +++ b/workbench/fastify-nitro/.gitignore @@ -0,0 +1,26 @@ +node_modules + +# Output +.output +.vercel +.netlify +.wrangler +.well-known/ +/build + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* + +# Workflows +_workflows.ts \ No newline at end of file diff --git a/workbench/fastify-nitro/nitro.config.ts b/workbench/fastify-nitro/nitro.config.ts new file mode 100644 index 000000000..c744ea478 --- /dev/null +++ b/workbench/fastify-nitro/nitro.config.ts @@ -0,0 +1,9 @@ +import { defineNitroConfig } from 'nitro/config'; + +export default defineNitroConfig({ + modules: ['workflow/nitro'], + vercel: { entryFormat: 'node' }, + routes: { + '/**': './src/index.ts', + }, +}); diff --git a/workbench/fastify-nitro/package.json b/workbench/fastify-nitro/package.json new file mode 100644 index 000000000..5895fb095 --- /dev/null +++ b/workbench/fastify-nitro/package.json @@ -0,0 +1,25 @@ +{ + "name": "@workbench/fastify", + "private": true, + "type": "module", + "scripts": { + "generate:workflows": "node ../scripts/generate-workflows-registry.js", + "predev": "pnpm generate:workflows", + "prebuild": "pnpm generate:workflows", + "build": "nitro build", + "dev": "nitro dev", + "start": "node .output/server/index.mjs" + }, + "dependencies": { + "@workflow/fastify": "workspace:*", + "fastify": "^5.6.2", + "nitro": "catalog:", + "srvx": "^0.9.6", + "workflow": "workspace:*" + }, + "devDependencies": { + "@types/node": "catalog:", + "tsx": "^4.19.2", + "typescript": "catalog:" + } +} diff --git a/workbench/fastify-nitro/src/index.ts b/workbench/fastify-nitro/src/index.ts new file mode 100644 index 000000000..6a79d8f87 --- /dev/null +++ b/workbench/fastify-nitro/src/index.ts @@ -0,0 +1,222 @@ +import Fastify from 'fastify'; +import { fromNodeHandler } from 'nitro/h3'; +import { getHookByToken, getRun, resumeHook, start } from 'workflow/api'; +import { hydrateWorkflowArguments } from 'workflow/internal/serialization'; +import { + WorkflowRunFailedError, + WorkflowRunNotCompletedError, +} from 'workflow/internal/errors'; +import { allWorkflows } from '../_workflows.js'; + +const server = Fastify({ + logger: true, +}); + +console.log('Fastify Server created!'); + +// Add content type parser for text/* +server.addContentTypeParser( + 'text/*', + { parseAs: 'string' }, + server.getDefaultJsonParser('ignore', 'ignore') +); + +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/trigger', async (req: any, reply) => { + const workflowFile = + (req.query.workflowFile as string) || 'workflows/99_e2e.ts'; + if (!workflowFile) { + return reply.code(400).send('No workflowFile query parameter provided'); + } + const workflows = allWorkflows[workflowFile as keyof typeof allWorkflows]; + if (!workflows) { + return reply.code(400).send(`Workflow file "${workflowFile}" not found`); + } + + const workflowFn = (req.query.workflowFn as string) || 'simple'; + if (!workflowFn) { + return reply.code(400).send('No workflow query parameter provided'); + } + const workflow = workflows[workflowFn as keyof typeof workflows]; + if (!workflow) { + return reply.code(400).send('Workflow not found'); + } + + let args: any[] = []; + + // Args from query string + const argsParam = req.query.args as string; + if (argsParam) { + args = argsParam.split(',').map((arg) => { + const num = parseFloat(arg); + return Number.isNaN(num) ? arg.trim() : num; + }); + } else { + // Args from body + const body = req.body; + if (body && typeof body === 'string') { + args = hydrateWorkflowArguments(JSON.parse(body), globalThis); + } else if (body && typeof body === 'object') { + args = hydrateWorkflowArguments(body, globalThis); + } else { + args = [42]; + } + } + console.log(`Starting "${workflowFn}" workflow with args: ${args}`); + + try { + const run = await start(workflow as any, args as any); + console.log('Run:', run); + return run; + } catch (err) { + console.error(`Failed to start!!`, err); + throw err; + } +}); + +server.get('/api/trigger', async (req: any, reply) => { + const runId = req.query.runId as string | undefined; + if (!runId) { + return reply.code(400).send('No runId provided'); + } + + const outputStreamParam = req.query['output-stream'] as string | undefined; + if (outputStreamParam) { + const namespace = outputStreamParam === '1' ? undefined : outputStreamParam; + const run = getRun(runId); + const stream = run.getReadable({ + namespace, + }); + + // Set headers + reply.header('Content-Type', 'application/octet-stream'); + + // Read from the stream and write to response + const reader = stream.getReader(); + + return (async function* () { + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + // Add JSON framing to each chunk, wrapping binary data in base64 + const data = + value instanceof Uint8Array + ? { data: Buffer.from(value).toString('base64') } + : value; + yield `${JSON.stringify(data)}\n`; + } + } catch (error) { + console.error('Error streaming data:', error); + } + })(); + } + + try { + const run = getRun(runId); + const returnValue = await run.returnValue; + console.log('Return value:', returnValue); + + if (returnValue instanceof ReadableStream) { + // Set headers for streaming response + reply.header('Content-Type', 'application/octet-stream'); + + // Read from the stream and write to response + const reader = returnValue.getReader(); + + return (async function* () { + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + yield value; + } + } catch (streamError) { + console.error('Error streaming return value:', streamError); + } + })(); + } + + return returnValue; + } catch (error) { + if (error instanceof Error) { + if (WorkflowRunNotCompletedError.is(error)) { + return reply.code(202).send({ + ...error, + name: error.name, + message: error.message, + }); + } + + if (WorkflowRunFailedError.is(error)) { + const cause = error.cause; + return reply.code(400).send({ + ...error, + name: error.name, + message: error.message, + cause: { + message: cause.message, + stack: cause.stack, + code: cause.code, + }, + }); + } + } + + console.error( + 'Unexpected error while getting workflow return value:', + error + ); + return reply.code(500).send({ + error: 'Internal server 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 + // and keep their original implementation, allowing them to be called as regular async functions + const { add } = await import('../workflows/99_e2e.js'); + + const { x, y } = req.body; + + console.log(`Calling step function directly with x=${x}, y=${y}`); + + // Call step function directly as a regular async function (no workflow context) + const result = await add(x, y); + console.log(`add(${x}, ${y}) = ${result}`); + + return { result }; +}); + +await server.ready(); + +export default fromNodeHandler((req, res) => { + return new Promise((resolve) => { + res.on('finish', resolve); + server.server.emit('request', req, res); + }); +}); From a12b094bbf70628106609b3d09e78a711a8d58c0 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:17:53 +0400 Subject: [PATCH 02/60] not using my prototype fastify plugin Signed-off-by: Sree Narayanan --- workbench/fastify-nitro/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/workbench/fastify-nitro/package.json b/workbench/fastify-nitro/package.json index 5895fb095..aaac83535 100644 --- a/workbench/fastify-nitro/package.json +++ b/workbench/fastify-nitro/package.json @@ -11,7 +11,6 @@ "start": "node .output/server/index.mjs" }, "dependencies": { - "@workflow/fastify": "workspace:*", "fastify": "^5.6.2", "nitro": "catalog:", "srvx": "^0.9.6", From 5e82da609aa8dd7057a26f49ae98233c3f2b4884 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:19:52 +0400 Subject: [PATCH 03/60] renamed workbench dir Signed-off-by: Sree Narayanan --- workbench/{fastify-nitro => fastify}/.gitignore | 0 workbench/{fastify-nitro => fastify}/nitro.config.ts | 0 workbench/{fastify-nitro => fastify}/package.json | 0 workbench/{fastify-nitro => fastify}/src/index.ts | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename workbench/{fastify-nitro => fastify}/.gitignore (100%) rename workbench/{fastify-nitro => fastify}/nitro.config.ts (100%) rename workbench/{fastify-nitro => fastify}/package.json (100%) rename workbench/{fastify-nitro => fastify}/src/index.ts (100%) diff --git a/workbench/fastify-nitro/.gitignore b/workbench/fastify/.gitignore similarity index 100% rename from workbench/fastify-nitro/.gitignore rename to workbench/fastify/.gitignore diff --git a/workbench/fastify-nitro/nitro.config.ts b/workbench/fastify/nitro.config.ts similarity index 100% rename from workbench/fastify-nitro/nitro.config.ts rename to workbench/fastify/nitro.config.ts diff --git a/workbench/fastify-nitro/package.json b/workbench/fastify/package.json similarity index 100% rename from workbench/fastify-nitro/package.json rename to workbench/fastify/package.json diff --git a/workbench/fastify-nitro/src/index.ts b/workbench/fastify/src/index.ts similarity index 100% rename from workbench/fastify-nitro/src/index.ts rename to workbench/fastify/src/index.ts From 2531ae7cd0521431f931d2419b1f5c1536ad54ce Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:22:17 +0400 Subject: [PATCH 04/60] lockfile update Signed-off-by: Sree Narayanan --- pnpm-lock.yaml | 291 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 797a82b2f..c0abfb07e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1220,6 +1220,28 @@ importers: specifier: 'catalog:' version: 4.1.11 + workbench/fastify: + dependencies: + fastify: + specifier: ^5.6.2 + version: 5.6.2 + nitro: + specifier: 'catalog:' + version: 3.0.1-alpha.1(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(better-sqlite3@11.10.0)(chokidar@4.0.3)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7))(ioredis@5.8.2)(lru-cache@11.2.2)(rollup@4.53.2)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + srvx: + specifier: ^0.9.6 + version: 0.9.6 + workflow: + specifier: workspace:* + version: link:../../packages/workflow + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 22.19.0 + typescript: + specifier: 'catalog:' + version: 5.9.3 + workbench/hono: devDependencies: '@workflow/world-postgres': @@ -2614,9 +2636,27 @@ packages: resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/ajv-compiler@4.0.5': + resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} + '@fastify/busboy@3.2.0': resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} + + '@fastify/fast-json-stringify-compiler@5.0.3': + resolution: {integrity: sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==} + + '@fastify/forwarded@3.0.1': + resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==} + + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} + + '@fastify/proxy-addr@5.1.0': + resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==} + '@floating-ui/core@1.7.3': resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} @@ -4308,6 +4348,9 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -6507,6 +6550,9 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -6536,9 +6582,20 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + alien-signals@3.0.3: resolution: {integrity: sha512-2JXjom6R7ZwrISpUphLhf4htUq1aKRCennTJ6u9kFfr3sLmC9+I4CxxVi+McoFnIg+p1HnVrfLT/iCt4Dlz//Q==} @@ -6649,6 +6706,10 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + autoprefixer@10.4.21: resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} @@ -6656,6 +6717,9 @@ packages: peerDependencies: postcss: ^8.1.0 + avvio@9.1.0: + resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -8077,6 +8141,9 @@ packages: fast-content-type-parse@3.0.0: resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -8094,16 +8161,28 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-json-stringify@6.1.1: + resolution: {integrity: sha512-DbgptncYEXZqDUOEl4krff4mUiVrTZZVI7BBrQR/T3BqMj/eM1flTC1Uk2uUoLcWCxjT95xKulV/Lc6hhOZsBQ==} + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fast-npm-meta@0.4.7: resolution: {integrity: sha512-aZU3i3eRcSb2NCq8i6N6IlyiTyF6vqAqzBGl2NBF6ngNx/GIqfYbkLDIKZ4z4P0o/RmtsFnVqHwdrSm13o4tnQ==} + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-xml-parser@5.2.5: resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true + fastify@5.6.2: + resolution: {integrity: sha512-dPugdGnsvYkBlENLhCgX8yhyGCsCPrpA8lFWbTNU428l+YOnLgYHR69hzV8HWPC79n536EqzqQtvhtdaCE0dKg==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -8156,6 +8235,10 @@ packages: resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} engines: {node: '>= 0.8'} + find-my-way@9.3.0: + resolution: {integrity: sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==} + engines: {node: '>=20'} + find-package@1.0.0: resolution: {integrity: sha512-yVn71XCCaNgxz58ERTl8nA/8YYtIQDY9mHSrgFBfiFtdNNfY0h183Vh8BRkKxD8x9TUw3ec290uJKhDVxqGZBw==} @@ -8740,6 +8823,10 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -8984,9 +9071,15 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -9079,6 +9172,9 @@ packages: lie@3.1.1: resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + lightningcss-darwin-arm64@1.30.1: resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} engines: {node: '>= 12.0.0'} @@ -9966,6 +10062,10 @@ packages: resolution: {integrity: sha512-J7kocOS+ZNyjmW6tUUTtA7jLt8GjQlrOdz9z3yLNTvdsswO+b5lYSdMVzDczWnooyFAkkQiKyap5g/Zba+cFRA==} engines: {node: '>=20'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -10305,6 +10405,16 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@10.1.0: + resolution: {integrity: sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==} + hasBin: true + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -10563,6 +10673,12 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} @@ -10618,6 +10734,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + quote-unquote@1.0.0: resolution: {integrity: sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==} @@ -10797,6 +10916,10 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} @@ -10886,6 +11009,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-in-the-middle@7.5.2: resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} engines: {node: '>=8.6.0'} @@ -10917,6 +11044,10 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -10986,6 +11117,9 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex2@5.0.0: + resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} + safe-stable-stringify@2.5.0: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} @@ -11015,6 +11149,9 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + seedrandom@3.0.5: resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} @@ -11142,6 +11279,9 @@ packages: smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + sonner@2.0.7: resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} peerDependencies: @@ -11457,6 +11597,9 @@ packages: text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + throttleit@2.1.0: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} @@ -13683,8 +13826,31 @@ snapshots: levn: 0.4.1 optional: true + '@fastify/ajv-compiler@4.0.5': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.1.0 + '@fastify/busboy@3.2.0': {} + '@fastify/error@4.2.0': {} + + '@fastify/fast-json-stringify-compiler@5.0.3': + dependencies: + fast-json-stringify: 6.1.1 + + '@fastify/forwarded@3.0.1': {} + + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 + + '@fastify/proxy-addr@5.1.0': + dependencies: + '@fastify/forwarded': 3.0.1 + ipaddr.js: 2.2.0 + '@floating-ui/core@1.7.3': dependencies: '@floating-ui/utils': 0.2.10 @@ -15391,6 +15557,8 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.1 '@parcel/watcher-win32-x64': 2.5.1 + '@pinojs/redact@0.4.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -18132,6 +18300,8 @@ snapshots: dependencies: event-target-shim: 5.0.1 + abstract-logging@2.0.1: {} + accepts@2.0.0: dependencies: mime-types: 3.0.1 @@ -18157,6 +18327,10 @@ snapshots: '@opentelemetry/api': 1.9.0 zod: 4.1.11 + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -18165,6 +18339,13 @@ snapshots: uri-js: 4.4.1 optional: true + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + alien-signals@3.0.3: {} ansi-align@3.0.1: @@ -18271,6 +18452,8 @@ snapshots: async@3.2.6: {} + atomic-sleep@1.0.0: {} + autoprefixer@10.4.21(postcss@8.5.6): dependencies: browserslist: 4.27.0 @@ -18281,6 +18464,11 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 + avvio@9.1.0: + dependencies: + '@fastify/error': 4.2.0 + fastq: 1.19.1 + axobject-query@4.1.0: {} b4a@1.7.3: {} @@ -19791,6 +19979,8 @@ snapshots: fast-content-type-parse@3.0.0: {} + fast-decode-uri-component@1.0.1: {} + fast-deep-equal@3.1.3: {} fast-equals@5.3.2: {} @@ -19808,15 +19998,48 @@ snapshots: fast-json-stable-stringify@2.1.0: optional: true + fast-json-stringify@6.1.1: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.1.0 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.4.1 + fast-levenshtein@2.0.6: optional: true fast-npm-meta@0.4.7: {} + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-uri@3.1.0: {} + fast-xml-parser@5.2.5: dependencies: strnum: 2.1.1 + fastify@5.6.2: + dependencies: + '@fastify/ajv-compiler': 4.0.5 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.0.3 + '@fastify/proxy-addr': 5.1.0 + abstract-logging: 2.0.1 + avvio: 9.1.0 + fast-json-stringify: 6.1.1 + find-my-way: 9.3.0 + light-my-request: 6.6.0 + pino: 10.1.0 + process-warning: 5.0.0 + rfdc: 1.4.1 + secure-json-parse: 4.1.0 + semver: 7.7.3 + toad-cache: 3.7.0 + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -19872,6 +20095,12 @@ snapshots: transitivePeerDependencies: - supports-color + find-my-way@9.3.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 5.0.0 + find-package@1.0.0: dependencies: parents: 1.0.1 @@ -20576,6 +20805,8 @@ snapshots: ipaddr.js@1.9.1: {} + ipaddr.js@2.2.0: {} + iron-webcrypto@1.2.1: {} is-alphabetical@2.0.1: {} @@ -20761,9 +20992,15 @@ snapshots: json-parse-even-better-errors@2.3.1: {} + json-schema-ref-resolver@3.0.0: + dependencies: + dequal: 2.0.3 + json-schema-traverse@0.4.1: optional: true + json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} json-stable-stringify-without-jsonify@1.0.1: @@ -20849,6 +21086,12 @@ snapshots: dependencies: immediate: 3.0.6 + light-my-request@6.6.0: + dependencies: + cookie: 1.0.2 + process-warning: 4.0.1 + set-cookie-parser: 2.7.2 + lightningcss-darwin-arm64@1.30.1: optional: true @@ -22530,6 +22773,8 @@ snapshots: on-change@6.0.0: {} + on-exit-leak-free@2.1.2: {} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -22964,6 +23209,26 @@ snapshots: pify@4.0.1: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.0.0: {} + + pino@10.1.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -23232,6 +23497,10 @@ snapshots: process-nextick-args@2.0.1: {} + process-warning@4.0.1: {} + + process-warning@5.0.0: {} + process@0.11.10: {} prompts@2.4.2: @@ -23299,6 +23568,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + quote-unquote@1.0.0: {} radix-ui@1.4.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): @@ -23596,6 +23867,8 @@ snapshots: readdirp@4.1.2: {} + real-require@0.2.0: {} + recharts-scale@0.4.5: dependencies: decimal.js-light: 2.5.1 @@ -23751,6 +24024,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-in-the-middle@7.5.2: dependencies: debug: 4.4.3(supports-color@8.1.1) @@ -23784,6 +24059,8 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + ret@0.5.0: {} + retry@0.12.0: {} reusify@1.1.0: {} @@ -23872,6 +24149,10 @@ snapshots: safe-buffer@5.2.1: {} + safe-regex2@5.0.0: + dependencies: + ret: 0.5.0 + safe-stable-stringify@2.5.0: {} safer-buffer@2.1.2: {} @@ -23895,6 +24176,8 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + secure-json-parse@4.1.0: {} + seedrandom@3.0.5: {} semver@6.3.1: {} @@ -24082,6 +24365,10 @@ snapshots: smob@1.5.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + sonner@2.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 @@ -24480,6 +24767,10 @@ snapshots: text-hex@1.0.0: {} + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + throttleit@2.1.0: {} tiktok-video-element@0.1.1: {} From 322acda5c70b2a45587ebb4a6b46ceb2dbd63fd8 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:23:08 +0400 Subject: [PATCH 05/60] removed Signed-off-by: Sree Narayanan --- workbench/fastify/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index aaac83535..1c6ebac7e 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -18,7 +18,6 @@ }, "devDependencies": { "@types/node": "catalog:", - "tsx": "^4.19.2", "typescript": "catalog:" } } From 798b76009e9bf6c190c5bced3c68a2e5f9797333 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:26:50 +0400 Subject: [PATCH 06/60] symlinked workflows dir Signed-off-by: Sree Narayanan --- workbench/fastify/workflows | 1 + 1 file changed, 1 insertion(+) create mode 120000 workbench/fastify/workflows diff --git a/workbench/fastify/workflows b/workbench/fastify/workflows new file mode 120000 index 000000000..876d7a80c --- /dev/null +++ b/workbench/fastify/workflows @@ -0,0 +1 @@ +../nitro-v3/workflows \ No newline at end of file From 54d68e77f6097ed33f48e56550ef39cc1ee6c65f Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 12:33:07 +0400 Subject: [PATCH 07/60] added readme Signed-off-by: Sree Narayanan --- workbench/fastify/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 workbench/fastify/README.md diff --git a/workbench/fastify/README.md b/workbench/fastify/README.md new file mode 100644 index 000000000..f662f5fee --- /dev/null +++ b/workbench/fastify/README.md @@ -0,0 +1,26 @@ +# Workflows with Fastify (Nitro v3) + +- Learn more about Fastify: https://fastify.io +- Learn more about Nitro: https://v3.nitro.build/ + +## Commands + +**Local development:** + +```sh +npm run dev +``` + +**Production build (Vercel):** + +```sh +NITRO_PRESET=vercel npm run build +npx vercel --prebuilt +``` + +**Production build (Node.js):** + +```sh +npm run build +node .output/server/index.mjs +``` From e37e83f92325efdc5ad20e3a71df8e53e1d13007 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 20:34:25 +0400 Subject: [PATCH 08/60] symlinked client page Signed-off-by: Sree Narayanan --- workbench/fastify/index.html | 1 + 1 file changed, 1 insertion(+) create mode 120000 workbench/fastify/index.html diff --git a/workbench/fastify/index.html b/workbench/fastify/index.html new file mode 120000 index 000000000..62524c9be --- /dev/null +++ b/workbench/fastify/index.html @@ -0,0 +1 @@ +../nitro-v3/index.html \ No newline at end of file From 34b1bacb1502c7dd09ff47fb26976c6d6a234be1 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 21:56:20 +0400 Subject: [PATCH 09/60] scope nitro route to allow renderer fallback Signed-off-by: Sree Narayanan --- workbench/fastify/nitro.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench/fastify/nitro.config.ts b/workbench/fastify/nitro.config.ts index c744ea478..0ae7d185e 100644 --- a/workbench/fastify/nitro.config.ts +++ b/workbench/fastify/nitro.config.ts @@ -4,6 +4,6 @@ export default defineNitroConfig({ modules: ['workflow/nitro'], vercel: { entryFormat: 'node' }, routes: { - '/**': './src/index.ts', + '/api/**': './src/index.ts', }, }); From 4370c1b9e493029049e2cdde56369ac4c2396091 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Fri, 21 Nov 2025 21:57:15 +0400 Subject: [PATCH 10/60] allow empty json bodies Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 6a79d8f87..bcb7697a6 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -8,19 +8,38 @@ import { } from 'workflow/internal/errors'; import { allWorkflows } from '../_workflows.js'; +type JsonResult = { ok: true; value: any } | { ok: false; error: Error }; +const parseJson = (text: string): JsonResult => { + try { + return { ok: true, value: JSON.parse(text) }; + } catch (error) { + return { ok: false, error: error as Error }; + } +}; + const server = Fastify({ logger: true, }); console.log('Fastify Server created!'); -// Add content type parser for text/* server.addContentTypeParser( 'text/*', { parseAs: 'string' }, server.getDefaultJsonParser('ignore', 'ignore') ); +server.addContentTypeParser( + 'application/json', + { parseAs: 'string' }, + (req, body, done) => { + const text = typeof body === 'string' ? body : body.toString(); + if (!text) return done(null, {}); + const parsed = parseJson(text); + return parsed.ok ? done(null, parsed.value) : done(parsed.error); + } +); + server.post('/api/hook', async (req: any, reply) => { const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; const { token, data } = body; From 75c2fe6cdec67805d3401419e6bf8f12b27dd7ec Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 04:07:13 +0400 Subject: [PATCH 11/60] comments Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index bcb7697a6..ddd675037 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -21,14 +21,13 @@ const server = Fastify({ logger: true, }); -console.log('Fastify Server created!'); - server.addContentTypeParser( 'text/*', { parseAs: 'string' }, server.getDefaultJsonParser('ignore', 'ignore') ); +// allow fastify to parse empty json requests server.addContentTypeParser( 'application/json', { parseAs: 'string' }, From e12ba14dd1443c9e50f010ef636760afe6cfe30b Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 04:47:43 +0400 Subject: [PATCH 12/60] improve error handling and cleanup in /api/trigger Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 102 +++++++++++++++++---------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index ddd675037..249a30d5e 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -116,73 +116,78 @@ server.post('/api/trigger', async (req: any, reply) => { server.get('/api/trigger', async (req: any, reply) => { const runId = req.query.runId as string | undefined; if (!runId) { - return reply.code(400).send('No runId provided'); + return reply.code(400).send({ error: 'No runId provided' }); } const outputStreamParam = req.query['output-stream'] as string | undefined; - if (outputStreamParam) { - const namespace = outputStreamParam === '1' ? undefined : outputStreamParam; - const run = getRun(runId); - const stream = run.getReadable({ - namespace, - }); - - // Set headers - reply.header('Content-Type', 'application/octet-stream'); - - // Read from the stream and write to response - const reader = stream.getReader(); - - return (async function* () { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - - // Add JSON framing to each chunk, wrapping binary data in base64 - const data = - value instanceof Uint8Array - ? { data: Buffer.from(value).toString('base64') } - : value; - yield `${JSON.stringify(data)}\n`; - } - } catch (error) { - console.error('Error streaming data:', error); - } - })(); - } try { const run = getRun(runId); + + if (outputStreamParam) { + const namespace = + outputStreamParam === '1' ? undefined : outputStreamParam; + const stream = run.getReadable({ namespace }); + const reader = stream.getReader(); + + reply.type('application/octet-stream'); + + return reply.send( + (async function* () { + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const data = + value instanceof Uint8Array + ? { data: Buffer.from(value).toString('base64') } + : value; + yield `${JSON.stringify(data)}\n`; + } + } catch (error) { + console.error('Error streaming data:', error); + throw error; + } finally { + reader.releaseLock(); + } + })() + ); + } + const returnValue = await run.returnValue; console.log('Return value:', returnValue); if (returnValue instanceof ReadableStream) { - // Set headers for streaming response - reply.header('Content-Type', 'application/octet-stream'); - - // Read from the stream and write to response const reader = returnValue.getReader(); - return (async function* () { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - yield value; + reply.type('application/octet-stream'); + + return reply.send( + (async function* () { + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + yield value; + } + } catch (streamError) { + console.error('Error streaming return value:', streamError); + throw streamError; + } finally { + reader.releaseLock(); } - } catch (streamError) { - console.error('Error streaming return value:', streamError); - } - })(); + })() + ); } + // For async handlers, simply return the value + // Fastify will automatically serialize it as JSON return returnValue; } catch (error) { if (error instanceof Error) { if (WorkflowRunNotCompletedError.is(error)) { return reply.code(202).send({ - ...error, name: error.name, message: error.message, }); @@ -191,7 +196,6 @@ server.get('/api/trigger', async (req: any, reply) => { if (WorkflowRunFailedError.is(error)) { const cause = error.cause; return reply.code(400).send({ - ...error, name: error.name, message: error.message, cause: { @@ -207,8 +211,10 @@ server.get('/api/trigger', async (req: any, reply) => { 'Unexpected error while getting workflow return value:', error ); + return reply.code(500).send({ error: 'Internal server error', + message: error instanceof Error ? error.message : 'Unknown error', }); } }); From 68d8e89447a2eaea6c38d8cec136d10e64b47e1a Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 05:01:50 +0400 Subject: [PATCH 13/60] consistent server replies Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 249a30d5e..6b1ddd122 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -116,7 +116,7 @@ server.post('/api/trigger', async (req: any, reply) => { server.get('/api/trigger', async (req: any, reply) => { const runId = req.query.runId as string | undefined; if (!runId) { - return reply.code(400).send({ error: 'No runId provided' }); + return reply.code(400).send('No runId provided'); } const outputStreamParam = req.query['output-stream'] as string | undefined; @@ -214,7 +214,6 @@ server.get('/api/trigger', async (req: any, reply) => { return reply.code(500).send({ error: 'Internal server error', - message: error instanceof Error ? error.message : 'Unknown error', }); } }); @@ -233,7 +232,7 @@ server.post('/api/test-direct-step-call', async (req: any, reply) => { const result = await add(x, y); console.log(`add(${x}, ${y}) = ${result}`); - return { result }; + return reply.send(result); }); await server.ready(); From 657fa0d9dc4e83b3016afe3c0542f0af2d66d11e Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 05:07:46 +0400 Subject: [PATCH 14/60] expect json res Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 6b1ddd122..076756e45 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -232,7 +232,7 @@ server.post('/api/test-direct-step-call', async (req: any, reply) => { const result = await add(x, y); console.log(`add(${x}, ${y}) = ${result}`); - return reply.send(result); + return reply.send({ result }); }); await server.ready(); From aefe1b85221fb5129fc0e451f1090311267a0f55 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 05:23:24 +0400 Subject: [PATCH 15/60] fix json res for e2e test 3,4,5,11 Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 076756e45..f8e04b861 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -181,9 +181,14 @@ server.get('/api/trigger', async (req: any, reply) => { ); } - // For async handlers, simply return the value - // Fastify will automatically serialize it as JSON - return returnValue; + // Fastify sends strings as text/plain by default; JSON-encode primitives to match Hono/Response.json + const payload = + typeof returnValue === 'string' || + typeof returnValue === 'number' || + typeof returnValue === 'boolean' + ? JSON.stringify(returnValue) + : returnValue; + return reply.type('application/json').send(payload); } catch (error) { if (error instanceof Error) { if (WorkflowRunNotCompletedError.is(error)) { From e781d3905e9f47cdd99e8eca58d9e00105fbf837 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 05:49:17 +0400 Subject: [PATCH 16/60] fix fastify streaming responses Stream web streams the same way express or hono do. Read the web reader and write each json chunk to reply.raw. Avoids fastifys async iterator quirks that reordered frames and sent undefined data in the output stream tests Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 40 ++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index f8e04b861..a1b89730d 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -132,27 +132,25 @@ server.get('/api/trigger', async (req: any, reply) => { reply.type('application/octet-stream'); - return reply.send( - (async function* () { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - - const data = - value instanceof Uint8Array - ? { data: Buffer.from(value).toString('base64') } - : value; - yield `${JSON.stringify(data)}\n`; - } - } catch (error) { - console.error('Error streaming data:', error); - throw error; - } finally { - reader.releaseLock(); - } - })() - ); + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const data = + value instanceof Uint8Array + ? { data: Buffer.from(value).toString('base64') } + : value; + reply.raw.write(`${JSON.stringify(data)}\n`); + } + reply.raw.end(); + } catch (error) { + console.error('Error streaming data:', error); + reply.raw.end(); + } finally { + reader.releaseLock(); + } + return; } const returnValue = await run.returnValue; From 37aaca528cf798a8c008f365b22876a2109fab12 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 05:58:39 +0400 Subject: [PATCH 17/60] fix stream responses for e2e tests Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index a1b89730d..356fb08ea 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -158,25 +158,24 @@ server.get('/api/trigger', async (req: any, reply) => { if (returnValue instanceof ReadableStream) { const reader = returnValue.getReader(); - reply.type('application/octet-stream'); - return reply.send( - (async function* () { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - yield value; - } - } catch (streamError) { - console.error('Error streaming return value:', streamError); - throw streamError; - } finally { - reader.releaseLock(); - } - })() - ); + // Workflow returns a Web ReadableStream; stream it by pulling from + // its reader and writing to reply.raw so Fastify can flush it to the client + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + reply.raw.write(value); + } + reply.raw.end(); + } catch (streamError) { + console.error('Error streaming return value:', streamError); + reply.raw.end(); + } finally { + reader.releaseLock(); + } + return; } // Fastify sends strings as text/plain by default; JSON-encode primitives to match Hono/Response.json From 2d014cd30b0ac4ffb35a29637f2c7caf8effa438 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 06:01:03 +0400 Subject: [PATCH 18/60] clearer comments Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 356fb08ea..2deeeadf1 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -131,7 +131,8 @@ server.get('/api/trigger', async (req: any, reply) => { const reader = stream.getReader(); reply.type('application/octet-stream'); - + // Fastify runs on Node and doesn’t send Web ReadableStreams directly + // read from the Web reader and write framed chunks to the raw response try { while (true) { const { done, value } = await reader.read(); @@ -178,7 +179,7 @@ server.get('/api/trigger', async (req: any, reply) => { return; } - // Fastify sends strings as text/plain by default; JSON-encode primitives to match Hono/Response.json + // Fastify sends strings as text/plain by default const payload = typeof returnValue === 'string' || typeof returnValue === 'number' || From 41794c894cfb1748c64cf846156405907a3b8786 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 06:11:29 +0400 Subject: [PATCH 19/60] fix streaming res content type. passes all core e2e tests Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 2deeeadf1..f4c96e919 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -159,7 +159,8 @@ server.get('/api/trigger', async (req: any, reply) => { if (returnValue instanceof ReadableStream) { const reader = returnValue.getReader(); - reply.type('application/octet-stream'); + // reply.type() doesn't apply when we write directly to reply.raw + reply.raw.setHeader('Content-Type', 'application/octet-stream'); // Workflow returns a Web ReadableStream; stream it by pulling from // its reader and writing to reply.raw so Fastify can flush it to the client From 85870a92a901c907002586e1efe6db1b64b076d2 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 06:36:12 +0400 Subject: [PATCH 20/60] updated dev deps fastify bench Signed-off-by: Sree Narayanan --- pnpm-lock.yaml | 18 +++++++++++++++--- workbench/fastify/package.json | 10 +++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0abfb07e..7a5ed3eee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1231,16 +1231,28 @@ importers: srvx: specifier: ^0.9.6 version: 0.9.6 - workflow: - specifier: workspace:* - version: link:../../packages/workflow devDependencies: '@types/node': specifier: 'catalog:' version: 22.19.0 + ai: + specifier: 'catalog:' + version: 5.0.76(zod@4.1.11) + lodash.chunk: + specifier: ^4.2.0 + version: 4.2.0 + openai: + specifier: ^6.6.0 + version: 6.6.0(ws@8.18.3)(zod@4.1.11) typescript: specifier: 'catalog:' version: 5.9.3 + workflow: + specifier: workspace:* + version: link:../../packages/workflow + zod: + specifier: 'catalog:' + version: 4.1.11 workbench/hono: devDependencies: diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index 1c6ebac7e..93deca0fe 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -13,11 +13,15 @@ "dependencies": { "fastify": "^5.6.2", "nitro": "catalog:", - "srvx": "^0.9.6", - "workflow": "workspace:*" + "srvx": "^0.9.6" }, "devDependencies": { "@types/node": "catalog:", - "typescript": "catalog:" + "ai": "catalog:", + "lodash.chunk": "^4.2.0", + "openai": "^6.6.0", + "typescript": "catalog:", + "workflow": "workspace:*", + "zod": "catalog:" } } From 9b2de1b2d73a23382a5b37cfb777e6148b5bf8ac Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 07:13:08 +0400 Subject: [PATCH 21/60] fastify logo (light/dark mode) Signed-off-by: Sree Narayanan --- docs/app/(home)/components/frameworks.tsx | 92 ++++++++++++++--------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/docs/app/(home)/components/frameworks.tsx b/docs/app/(home)/components/frameworks.tsx index 1d21d9755..f24283b6a 100644 --- a/docs/app/(home)/components/frameworks.tsx +++ b/docs/app/(home)/components/frameworks.tsx @@ -1,12 +1,12 @@ -"use client"; +'use client'; -import { track } from "@vercel/analytics"; -import Link from "next/link"; -import type { ComponentProps } from "react"; -import { toast } from "sonner"; -import { Badge } from "@/components/ui/badge"; +import { track } from '@vercel/analytics'; +import Link from 'next/link'; +import type { ComponentProps } from 'react'; +import { toast } from 'sonner'; +import { Badge } from '@/components/ui/badge'; -export const Express = (props: ComponentProps<"svg">) => ( +export const Express = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const AstroDark = (props: ComponentProps<"svg">) => ( +export const Fastify = (props: ComponentProps<'svg'>) => ( + + Fastify + + +); + +export const AstroDark = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const AstroLight = (props: ComponentProps<"svg">) => ( +export const AstroLight = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const AstroGray = (props: ComponentProps<"svg">) => ( +export const AstroGray = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const TanStack = (props: ComponentProps<"svg">) => ( +export const TanStack = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const TanStackGray = (props: ComponentProps<"svg">) => ( +export const TanStackGray = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const Vite = (props: ComponentProps<"svg">) => ( +export const Vite = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const Nitro = (props: ComponentProps<"svg">) => ( +export const Nitro = (props: ComponentProps<'svg'>) => ( ) => ( /> ) => ( ); -export const SvelteKit = (props: ComponentProps<"svg">) => ( +export const SvelteKit = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const SvelteKitGray = (props: ComponentProps<"svg">) => ( +export const SvelteKitGray = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const Nuxt = (props: ComponentProps<"svg">) => ( +export const Nuxt = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const NuxtGray = (props: ComponentProps<"svg">) => ( +export const NuxtGray = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const Hono = (props: ComponentProps<"svg">) => ( +export const Hono = (props: ComponentProps<'svg'>) => ( Hono ) => ( ); -export const HonoGray = (props: ComponentProps<"svg">) => ( +export const HonoGray = (props: ComponentProps<'svg'>) => ( Hono ) => ( ); -export const Bun = (props: ComponentProps<"svg">) => ( +export const Bun = (props: ComponentProps<'svg'>) => ( ) => ( id="Top" d="M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z" fill="#ccbea7" - style={{ fillRule: "evenodd" }} + style={{ fillRule: 'evenodd' }} /> ) => ( ); -export const BunGray = (props: ComponentProps<"svg">) => ( +export const BunGray = (props: ComponentProps<'svg'>) => ( ) => ( id="Top" d="M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z" fill="var(--color-background)" - style={{ fillRule: "evenodd" }} + style={{ fillRule: 'evenodd' }} /> ) => ( ); -export const Nest = (props: ComponentProps<"svg">) => ( +export const Nest = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const NestGray = (props: ComponentProps<"svg">) => ( +export const NestGray = (props: ComponentProps<'svg'>) => ( ) => ( ); -export const Next = (props: ComponentProps<"svg">) => ( +export const Next = (props: ComponentProps<'svg'>) => ( Next.js @@ -681,8 +696,8 @@ export const Next = (props: ComponentProps<"svg">) => ( export const Frameworks = () => { const handleRequest = (framework: string) => { - track("Framework requested", { framework: framework.toLowerCase() }); - toast.success("Request received", { + track('Framework requested', { framework: framework.toLowerCase() }); + toast.success('Request received', { description: `Thanks for expressing interest in ${framework}. We will be adding support for it soon.`, }); }; @@ -723,6 +738,9 @@ export const Frameworks = () => { + + +
@@ -742,21 +760,21 @@ export const Frameworks = () => {
handleRequest("NestJS")} + onClick={() => handleRequest('NestJS')} >
handleRequest("TanStack")} + onClick={() => handleRequest('TanStack')} >
handleRequest("Astro")} + onClick={() => handleRequest('Astro')} > From 38660cd1238de5127d1ff5d79c1443e7db6488db Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 07:13:42 +0400 Subject: [PATCH 22/60] update url Signed-off-by: Sree Narayanan --- workbench/fastify/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench/fastify/README.md b/workbench/fastify/README.md index f662f5fee..f68da1fba 100644 --- a/workbench/fastify/README.md +++ b/workbench/fastify/README.md @@ -1,6 +1,6 @@ # Workflows with Fastify (Nitro v3) -- Learn more about Fastify: https://fastify.io +- Learn more about Fastify: https://fastify.dev - Learn more about Nitro: https://v3.nitro.build/ ## Commands From 23c4138c8dd30b344b796bc9d059d4c889b10b8e Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 22 Nov 2025 08:17:37 +0400 Subject: [PATCH 23/60] fastify docs Signed-off-by: Sree Narayanan --- docs/content/docs/getting-started/fastify.mdx | 222 ++++++++++++++++++ docs/content/docs/getting-started/index.mdx | 8 +- 2 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 docs/content/docs/getting-started/fastify.mdx diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx new file mode 100644 index 000000000..a0655f47b --- /dev/null +++ b/docs/content/docs/getting-started/fastify.mdx @@ -0,0 +1,222 @@ +--- +title: Fastify +--- + +This guide will walk through setting up your first workflow in a Fastify app. Along the way, you'll learn more about the concepts that are fundamental to using the development kit in your own projects. + +--- + + + + +## Create Your Fastify Project + +Start by creating a new Fastify project. + +```bash +mkdir my-workflow-app +``` + +Enter the newly made directory: + +```bash +cd my-workflow-app +``` + +Initialize the project: + +```bash +npm init --y +``` + +### Install `workflow`, `fastify` and `nitro` + +```package-install +npm i workflow fastify nitro rollup +``` + + +Fastify doesn’t ship with a build system. Nitro provides one so you can compile workflows and run them in development and production. Learn more about Nitro [here](https://v3.nitro.build). + + +If using TypeScript, add types: + +```bash +npm i -D @types/node typescript +``` + +### Configure Nitro + +Create `nitro.config.ts` with the `workflow/nitro` module. This enables the `"use workflow"` and `"use step"` directives. + +```typescript title="nitro.config.ts" lineNumbers +import { defineNitroConfig } from "nitro/config"; + +export default defineNitroConfig({ + modules: ["workflow/nitro"], + vercel: { entryFormat: "node" }, + preset: "vercel", + routes: { + "/**": { handler: "./src/index.ts" }, + }, +}); +``` + + + + + Setup IntelliSense for TypeScript (Optional) + + +To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.json`: + +```json title="tsconfig.json" lineNumbers +{ + "compilerOptions": { + // ... rest of your TypeScript config + "plugins": [ + { + "name": "workflow" // [!code highlight] + } + ] + } +} +``` + + + + + +### Update `package.json` + +Add Nitro scripts: + +```json title="package.json" lineNumbers +{ + // ... + "scripts": { + "dev": "nitro dev", + "build": "nitro build" + }, + // ... +} +``` + + + + + +## Create Your First Workflow + +Create a new file for our first workflow: + +```typescript title="workflows/user-signup.ts" lineNumbers +import { sleep } from "workflow"; + +export async function handleUserSignup(email: string) { + "use workflow"; // [!code highlight] + + const user = await createUser(email); + await sendWelcomeEmail(user); + + await sleep("5s"); // Pause for 5s - doesn't consume any resources + await sendOnboardingEmail(user); + + return { userId: user.id, status: "onboarded" }; +} +``` + +We'll fill in those functions next: + +```typescript title="workflows/user-signup.ts" lineNumbers +import { FatalError } from "workflow"; + +// Our workflow function defined earlier + +async function createUser(email: string) { + "use step"; // [!code highlight] + console.log(`Creating user with email: ${email}`); + return { id: crypto.randomUUID(), email }; +} + +async function sendWelcomeEmail(user: { id: string; email: string }) { + "use step"; // [!code highlight] + console.log(`Sending welcome email to user: ${user.id}`); + if (Math.random() < 0.3) { + // Steps retry on unhandled errors + throw new Error("Retryable!"); + } +} + +async function sendOnboardingEmail(user: { id: string; email: string }) { + "use step"; // [!code highlight] + if (!user.email.includes("@")) { + // FatalError skips retries + throw new FatalError("Invalid Email"); + } + console.log(`Sending onboarding email to user: ${user.id}`); +} +``` + + + + + +## Create Your Route Handler + +Wire up a Fastify route to start the workflow at `src/index.ts`: + +```typescript title="src/index.ts" +import Fastify from "fastify"; +import { fromNodeHandler } from "nitro/h3"; +import { start } from "workflow/api"; +import { handleUserSignup } from "../workflows/user-signup.js"; + +const app = Fastify({ logger: true }); +app.post("/api/signup", async (req, reply) => { + const { email } = req.body as { email: string }; + await start(handleUserSignup, [email]); + return reply.send({ message: "User signup workflow started" }); +}); + +// Wait for Fastify to be ready before handling requests +await app.ready(); + +// Expose Fastify app as a Nitro handler +export default fromNodeHandler((req, res) => { + return new Promise((resolve) => { + res.on("finish", resolve); + app.server.emit("request", req, res); + }); +}); +``` + + + + + +## Run in development + +Start the dev server from your Fastify app root: + +```bash +npm run dev +``` + +Trigger the workflow: + +```bash +curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup +``` + +Check the Fastify logs to see the workflow orchestration and steps. You can also use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect runs: + +```bash +npx workflow inspect runs # add '--web' for an interactive Web based UI +``` + +Workflow DevKit Web UI + + + + diff --git a/docs/content/docs/getting-started/index.mdx b/docs/content/docs/getting-started/index.mdx index 11a399aea..327aa25ce 100644 --- a/docs/content/docs/getting-started/index.mdx +++ b/docs/content/docs/getting-started/index.mdx @@ -3,7 +3,7 @@ title: Getting Started description: Start by choosing your framework. Each guide will walk you through the steps to install the dependencies and start running your first workflow. --- -import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite, Express } from '@/app/(home)/components/frameworks'; +import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite, Express, Fastify } from '@/app/(home)/components/frameworks'; @@ -24,6 +24,12 @@ import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStac Express
+ +
+ + Fastify +
+
From df5dfc9849af3cd9e818cd816feec5586137eae7 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 02:26:30 +0400 Subject: [PATCH 24/60] Apply suggestions from code review Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index a0655f47b..f01c56d8c 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -126,7 +126,10 @@ export async function handleUserSignup(email: string) { } ``` -We'll fill in those functions next: +We'll fill in those functions next, but let's take a look at this code: + +- We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**. +- The Workflow DevKit's `sleep` function allows us to suspend execution of the workflow without using up any resources. A sleep can be a few seconds, hours, days, or even months long. ```typescript title="workflows/user-signup.ts" lineNumbers import { FatalError } from "workflow"; From 809bacb88461da5e92aec5d31d936222407593b6 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:24:01 +0400 Subject: [PATCH 25/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index f01c56d8c..8e526a78d 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -36,7 +36,7 @@ npm i workflow fastify nitro rollup ``` -Fastify doesn’t ship with a build system. Nitro provides one so you can compile workflows and run them in development and production. Learn more about Nitro [here](https://v3.nitro.build). +By default, Fastify doesn't include a build system. Nitro adds one which enables compiling workflows, runs, and deploys for development and production. Learn more about [Nitro](https://v3.nitro.build). If using TypeScript, add types: From b270d02ee69ac072eaa4538a31ed110edf852cc2 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:24:15 +0400 Subject: [PATCH 26/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 8e526a78d..0153f1fa9 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -160,7 +160,16 @@ async function sendOnboardingEmail(user: { id: string; email: string }) { console.log(`Sending onboarding email to user: ${user.id}`); } ``` +Taking a look at this code: +- Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`. +- If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count). +- Steps can throw a `FatalError` if an error is intentional and should not be retried. + + + We'll dive deeper into workflows, steps, and other ways to suspend or handle + events in [Foundations](/docs/foundations). + From cb73ae5b1f3f7059f4c432b8226f8eb9b0492724 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:24:30 +0400 Subject: [PATCH 27/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 0153f1fa9..0adeaeb78 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -221,7 +221,9 @@ Trigger the workflow: curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup ``` -Check the Fastify logs to see the workflow orchestration and steps. You can also use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect runs: +Check the Fastify development server logs to see your workflow execute as well as the steps that are being processed. + +Additionally, you can use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail. ```bash npx workflow inspect runs # add '--web' for an interactive Web based UI From 2ee3af65040e969b91a491b2bb285cd2ed447e10 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:24:41 +0400 Subject: [PATCH 28/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 0adeaeb78..103fe91ec 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -202,7 +202,7 @@ export default fromNodeHandler((req, res) => { }); }); ``` - +This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow. From cab1381b0e08e3453a3e5a66f55d02a8effff0e3 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:24:56 +0400 Subject: [PATCH 29/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 103fe91ec..1788dd801 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -47,7 +47,7 @@ npm i -D @types/node typescript ### Configure Nitro -Create `nitro.config.ts` with the `workflow/nitro` module. This enables the `"use workflow"` and `"use step"` directives. +Create a new file `nitro.config.ts` for your Nitro configuration with module `workflow/nitro`. This enables usage of the `"use workflow"` and `"use step"` directives ```typescript title="nitro.config.ts" lineNumbers import { defineNitroConfig } from "nitro/config"; From 9c7471b2fba60079c71951433d9d0649d8399ba3 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:25:08 +0400 Subject: [PATCH 30/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 1788dd801..d171b9791 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -215,7 +215,7 @@ Start the dev server from your Fastify app root: npm run dev ``` -Trigger the workflow: +Once your development server is running, you can trigger your workflow by running this command in the terminal: ```bash curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup From 4583452a27c704ba474080d0c560a1b1b9724058 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:25:29 +0400 Subject: [PATCH 31/60] Update docs/content/docs/getting-started/fastify.mdx Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index d171b9791..727b21782 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -209,7 +209,7 @@ This route handler creates a `POST` request endpoint at `/api/signup` that will ## Run in development -Start the dev server from your Fastify app root: +To start your development server, run the following command in your terminal in the Fastify root directory: ```bash npm run dev From fcaeba09180193c594aac2153a18d4ae51a75245 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:34:27 +0400 Subject: [PATCH 32/60] Sree Narayanan DCO Remediation Commit for Sree Narayanan I, Sree Narayanan , hereby add my Signed-off-by to this commit: c3b6cf9bc4d326833c1ecc1e96a7dc450db1d311 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 3628b82c1e23197378331e312d43ed240383c1b5 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 600117f95a058e9fba0d872af59c7b4a9f04bd81 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 9111151b48211fbb61674bf256fe42cbe04a3428 I, Sree Narayanan , hereby add my Signed-off-by to this commit: aceb6a8cebc3178c997c0646d0a9c6caf07431ee I, Sree Narayanan , hereby add my Signed-off-by to this commit: b93df58edbfb9b069bfa79bcf7a0c212703cf529 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 628718750e589365d3e8783312f0878a3dea69cd I, Sree Narayanan , hereby add my Signed-off-by to this commit: 7f523e80132c1931c92cf27301c53418a2c09a2c Signed-off-by: Sree Narayanan From 528e785ed9ea211233f42802c1ff010122e4e96b Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:38:52 +0400 Subject: [PATCH 33/60] Apply suggestions from code review Signed-off-by: Sree Narayanan Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 727b21782..e06a4975e 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -89,7 +89,7 @@ To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.jso ### Update `package.json` -Add Nitro scripts: +To use the Nitro builder, update your `package.json` to include the following scripts: ```json title="package.json" lineNumbers { @@ -130,7 +130,9 @@ We'll fill in those functions next, but let's take a look at this code: - We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**. - The Workflow DevKit's `sleep` function allows us to suspend execution of the workflow without using up any resources. A sleep can be a few seconds, hours, days, or even months long. +## Create Your Workflow Steps +Let's now define those missing functions: ```typescript title="workflows/user-signup.ts" lineNumbers import { FatalError } from "workflow"; @@ -176,7 +178,7 @@ Taking a look at this code: ## Create Your Route Handler -Wire up a Fastify route to start the workflow at `src/index.ts`: +To invoke your new workflow, we'll create both the Fastify app and a new API route handler at `src/index.ts` with the following code: ```typescript title="src/index.ts" import Fastify from "fastify"; @@ -234,3 +236,18 @@ npx workflow inspect runs # add '--web' for an interactive Web based UI + +--- + +## Deploying to production + +Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration. + +Check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere. + +## Next Steps + +- Learn more about the [Foundations](/docs/foundations). +- Check [Errors](/docs/errors) if you encounter issues. +- Explore the [API Reference](/docs/api-reference). + From e7de3ded5b9c92f54ddde582e1238d12a665a9ab Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:51:14 +0400 Subject: [PATCH 34/60] nit: standardized package.json Signed-off-by: Sree Narayanan --- workbench/fastify/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index 93deca0fe..bd2667f7c 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -1,7 +1,10 @@ { - "name": "@workbench/fastify", + "name": "@workbench/example-fastify", + "version": "0.0.0", "private": true, + "description": "", "type": "module", + "main": "index.js", "scripts": { "generate:workflows": "node ../scripts/generate-workflows-registry.js", "predev": "pnpm generate:workflows", From 3be11be94d474e83a34175d7f3899ef9f3215610 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:52:40 +0400 Subject: [PATCH 35/60] mom, my commits are in vercel CI Signed-off-by: Sree Narayanan --- packages/core/e2e/local-build.test.ts | 1 + scripts/create-test-matrix.mjs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/packages/core/e2e/local-build.test.ts b/packages/core/e2e/local-build.test.ts index 4daca2b01..0eb264c9b 100644 --- a/packages/core/e2e/local-build.test.ts +++ b/packages/core/e2e/local-build.test.ts @@ -14,6 +14,7 @@ describe.each([ 'nuxt', 'hono', 'express', + 'fastify', ])('e2e', (project) => { test('builds without errors', { timeout: 180_000 }, async () => { // skip if we're targeting specific app to test diff --git a/scripts/create-test-matrix.mjs b/scripts/create-test-matrix.mjs index 369ec344d..d7cc3c18f 100644 --- a/scripts/create-test-matrix.mjs +++ b/scripts/create-test-matrix.mjs @@ -49,6 +49,12 @@ const DEV_TEST_CONFIGS = { apiFilePath: './src/index.ts', apiFileImportPath: '..', }, + fastify: { + generatedStepPath: 'node_modules/.nitro/workflow/steps.mjs', + generatedWorkflowPath: 'node_modules/.nitro/workflow/workflows.mjs', + apiFilePath: './src/index.ts', + apiFileImportPath: '..', + }, }; const matrix = { @@ -112,4 +118,10 @@ matrix.app.push({ ...DEV_TEST_CONFIGS.express, }); +matrix.app.push({ + name: 'fastify', + project: 'workbench-fastify-workflow', + ...DEV_TEST_CONFIGS.fastify, +}); + console.log(JSON.stringify(matrix)); From 55b7b5f4de36e924b0462dcc223cfe9df0f8e964 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 03:56:13 +0400 Subject: [PATCH 36/60] Update docs/content/docs/getting-started/fastify.mdx Signed-off-by: Sree Narayanan Co-authored-by: Adrian --- docs/content/docs/getting-started/fastify.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index e06a4975e..17b437459 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -39,7 +39,7 @@ npm i workflow fastify nitro rollup By default, Fastify doesn't include a build system. Nitro adds one which enables compiling workflows, runs, and deploys for development and production. Learn more about [Nitro](https://v3.nitro.build). -If using TypeScript, add types: +If using TypeScript, you need to install the `@types/node` and `typescript` packages ```bash npm i -D @types/node typescript From 4df0108d59ac836636b20d50730aa24a90b90917 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 04:03:42 +0400 Subject: [PATCH 37/60] Update workbench/fastify/package.json Signed-off-by: Sree Narayanan Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> --- workbench/fastify/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index bd2667f7c..97a62bf9f 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -1,5 +1,5 @@ { - "name": "@workbench/example-fastify", + "name": "@workflow/example-fastify", "version": "0.0.0", "private": true, "description": "", From f4891e937960c2f4b52ba7f8c595213761a69197 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sun, 23 Nov 2025 21:38:04 +0400 Subject: [PATCH 38/60] passing workflow error object to err responses Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index f4c96e919..45fffd350 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -192,6 +192,7 @@ server.get('/api/trigger', async (req: any, reply) => { if (error instanceof Error) { if (WorkflowRunNotCompletedError.is(error)) { return reply.code(202).send({ + ...error, name: error.name, message: error.message, }); @@ -200,6 +201,7 @@ server.get('/api/trigger', async (req: any, reply) => { if (WorkflowRunFailedError.is(error)) { const cause = error.cause; return reply.code(400).send({ + ...error, name: error.name, message: error.message, cause: { From 682dc312767779f2e34057d263ac604a8d260a69 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Mon, 24 Nov 2025 21:03:31 +0400 Subject: [PATCH 39/60] Update workbench/fastify/nitro.config.ts Signed-off-by: Sree Narayanan Co-authored-by: Adrian --- workbench/fastify/nitro.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench/fastify/nitro.config.ts b/workbench/fastify/nitro.config.ts index 0ae7d185e..c744ea478 100644 --- a/workbench/fastify/nitro.config.ts +++ b/workbench/fastify/nitro.config.ts @@ -4,6 +4,6 @@ export default defineNitroConfig({ modules: ['workflow/nitro'], vercel: { entryFormat: 'node' }, routes: { - '/api/**': './src/index.ts', + '/**': './src/index.ts', }, }); From 03229ad140d364f06adbe0fd813f9d107770c04a Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Mon, 24 Nov 2025 21:03:43 +0400 Subject: [PATCH 40/60] Update workbench/fastify/src/index.ts Signed-off-by: Sree Narayanan Co-authored-by: Adrian --- workbench/fastify/src/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 45fffd350..df600208a 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -39,6 +39,13 @@ server.addContentTypeParser( } ); +server.get('/', async (_, reply) => { + const stream = fs.createReadStream('./index.html'); + console.log(stream); + + return reply.type('text/html').send(stream); +}); + server.post('/api/hook', async (req: any, reply) => { const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; const { token, data } = body; From 8e3ede06ed8defbfc7f47e35dee606a648aa98a5 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 09:21:56 -0800 Subject: [PATCH 41/60] feat: add start pg world plugin --- workbench/fastify/nitro.config.ts | 1 + workbench/fastify/plugins/start-pg-world.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 workbench/fastify/plugins/start-pg-world.ts diff --git a/workbench/fastify/nitro.config.ts b/workbench/fastify/nitro.config.ts index c744ea478..8e89eea15 100644 --- a/workbench/fastify/nitro.config.ts +++ b/workbench/fastify/nitro.config.ts @@ -6,4 +6,5 @@ export default defineNitroConfig({ routes: { '/**': './src/index.ts', }, + plugins: ['plugins/start-pg-world.ts'], }); diff --git a/workbench/fastify/plugins/start-pg-world.ts b/workbench/fastify/plugins/start-pg-world.ts new file mode 100644 index 000000000..7e9cff224 --- /dev/null +++ b/workbench/fastify/plugins/start-pg-world.ts @@ -0,0 +1,12 @@ +import { defineNitroPlugin } from 'nitro/~internal/runtime/plugin'; + +// Start the Postgres World +// Needed since we test this in CI +export default defineNitroPlugin(async () => { + if (process.env.WORKFLOW_TARGET_WORLD === '@workflow/world-postgres') { + import('workflow/runtime').then(async ({ getWorld }) => { + console.log('Starting Postgres World...'); + await getWorld().start?.(); + }); + } +}); From 453b8456755332df05343182063b780ca0e29af2 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Mon, 24 Nov 2025 21:28:22 +0400 Subject: [PATCH 42/60] import createReadStream to serve index.html Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index df600208a..c9780b0a5 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -1,4 +1,5 @@ import Fastify from 'fastify'; +import { createReadStream } from 'node:fs'; import { fromNodeHandler } from 'nitro/h3'; import { getHookByToken, getRun, resumeHook, start } from 'workflow/api'; import { hydrateWorkflowArguments } from 'workflow/internal/serialization'; @@ -40,9 +41,7 @@ server.addContentTypeParser( ); server.get('/', async (_, reply) => { - const stream = fs.createReadStream('./index.html'); - console.log(stream); - + const stream = createReadStream('./index.html'); return reply.type('text/html').send(stream); }); From 982a2c183d8db3df963fa0a46a9eadbf58bd7852 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 09:27:14 -0800 Subject: [PATCH 43/60] test: add fastify deploy --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7bd31d34f..5043420d1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -75,6 +75,8 @@ jobs: project-id: "prj_p0GIEsfl53L7IwVbosPvi9rPSOYW" - name: "express" project-id: "prj_cCZjpBy92VRbKHHbarDMhOHtkuIr" + - name: "fastify" + project-id: "prj_5Yap0VDQ633v998iqQ3L3aQ25Cck" env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }} From 5c909c97b921dfe96773ae790bd73eed307942ca Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 09:28:43 -0800 Subject: [PATCH 44/60] fix: add postgres world dep --- pnpm-lock.yaml | 3 +++ workbench/fastify/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a5ed3eee..e36e26206 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1235,6 +1235,9 @@ importers: '@types/node': specifier: 'catalog:' version: 22.19.0 + '@workflow/world-postgres': + specifier: workspace:* + version: link:../../packages/world-postgres ai: specifier: 'catalog:' version: 5.0.76(zod@4.1.11) diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index 97a62bf9f..841233bf8 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -25,6 +25,7 @@ "openai": "^6.6.0", "typescript": "catalog:", "workflow": "workspace:*", + "@workflow/world-postgres": "workspace:*", "zod": "catalog:" } } From 12acb3f2e9373792863eed1dffcc80776d2c25a7 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 12:19:05 -0800 Subject: [PATCH 45/60] use symlink --- workbench/fastify/plugins | 1 + workbench/fastify/plugins/start-pg-world.ts | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) create mode 120000 workbench/fastify/plugins delete mode 100644 workbench/fastify/plugins/start-pg-world.ts diff --git a/workbench/fastify/plugins b/workbench/fastify/plugins new file mode 120000 index 000000000..2c8250f9c --- /dev/null +++ b/workbench/fastify/plugins @@ -0,0 +1 @@ +../nitro-v3/plugins \ No newline at end of file diff --git a/workbench/fastify/plugins/start-pg-world.ts b/workbench/fastify/plugins/start-pg-world.ts deleted file mode 100644 index 7e9cff224..000000000 --- a/workbench/fastify/plugins/start-pg-world.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineNitroPlugin } from 'nitro/~internal/runtime/plugin'; - -// Start the Postgres World -// Needed since we test this in CI -export default defineNitroPlugin(async () => { - if (process.env.WORKFLOW_TARGET_WORLD === '@workflow/world-postgres') { - import('workflow/runtime').then(async ({ getWorld }) => { - console.log('Starting Postgres World...'); - await getWorld().start?.(); - }); - } -}); From 9fb7813abfecf65d29bf70288157e5e5f9885965 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 13:11:56 -0800 Subject: [PATCH 46/60] chore(deps): remove unused deps from fastify --- pnpm-lock.yaml | 3 --- workbench/fastify/package.json | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e36e26206..764d53ec7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1228,9 +1228,6 @@ importers: nitro: specifier: 'catalog:' version: 3.0.1-alpha.1(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(better-sqlite3@11.10.0)(chokidar@4.0.3)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7))(ioredis@5.8.2)(lru-cache@11.2.2)(rollup@4.53.2)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) - srvx: - specifier: ^0.9.6 - version: 0.9.6 devDependencies: '@types/node': specifier: 'catalog:' diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index 841233bf8..e90fa07f3 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -15,17 +15,16 @@ }, "dependencies": { "fastify": "^5.6.2", - "nitro": "catalog:", - "srvx": "^0.9.6" + "nitro": "catalog:" }, "devDependencies": { "@types/node": "catalog:", + "@workflow/world-postgres": "workspace:*", "ai": "catalog:", "lodash.chunk": "^4.2.0", "openai": "^6.6.0", "typescript": "catalog:", "workflow": "workspace:*", - "@workflow/world-postgres": "workspace:*", "zod": "catalog:" } } From 7e231cd9e84d50c9fea86afd3e820afd0783c0af Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 13:50:35 -0800 Subject: [PATCH 47/60] docs: update fastify --- docs/content/docs/getting-started/fastify.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 17b437459..043ae4351 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -57,7 +57,7 @@ export default defineNitroConfig({ vercel: { entryFormat: "node" }, preset: "vercel", routes: { - "/**": { handler: "./src/index.ts" }, + "/**": "./src/index.ts", }, }); ``` @@ -250,4 +250,3 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b - Learn more about the [Foundations](/docs/foundations). - Check [Errors](/docs/errors) if you encounter issues. - Explore the [API Reference](/docs/api-reference). - From 3a33776df67c074d46eacfb17fcd6f570e2f9bde Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Tue, 25 Nov 2025 05:23:54 +0400 Subject: [PATCH 48/60] Sree Narayanan DCO Remediation Commit for Sree Narayanan I, Sree Narayanan , hereby add my Signed-off-by to this commit: 54c3e8a50a663c8e9aacf9c95618f59af1bd2e4c I, Sree Narayanan , hereby add my Signed-off-by to this commit: 423f722209c64382e86f9f8821253dc4facffe96 I, Sree Narayanan , hereby add my Signed-off-by to this commit: f76061627fe8d320ce498d44d0a3234abb6432ab I, Sree Narayanan , hereby add my Signed-off-by to this commit: a269b8aa8d2fcf0b605cce5a1486cac481cca16e I, Sree Narayanan , hereby add my Signed-off-by to this commit: b3cedf7defdb7f97b37862bf2a736d41a6bc5ec8 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 596cf21e79bc82a73b56acb9cab1fc33dbfde975 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 0ea1aa7d95e375d1f04e5501254a9fda815c7694 I, Sree Narayanan , hereby add my Signed-off-by to this commit: dbc8638b4a952c303e35035204cfdca43b99a059 Signed-off-by: Sree Narayanan From 4da6a6f750fb8d1bdfab402735a8a605131f844b Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Mon, 24 Nov 2025 21:43:30 -0800 Subject: [PATCH 49/60] remove fromNodeHandler inside fastify app --- docs/content/docs/getting-started/fastify.mdx | 14 +++++--------- workbench/fastify/nitro.config.ts | 2 +- workbench/fastify/src/index.ts | 10 +++------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 043ae4351..551ca036e 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -57,7 +57,7 @@ export default defineNitroConfig({ vercel: { entryFormat: "node" }, preset: "vercel", routes: { - "/**": "./src/index.ts", + "/**": { handler: "./src/index.ts", format: "node" }, }, }); ``` @@ -182,7 +182,6 @@ To invoke your new workflow, we'll create both the Fastify app and a new API rou ```typescript title="src/index.ts" import Fastify from "fastify"; -import { fromNodeHandler } from "nitro/h3"; import { start } from "workflow/api"; import { handleUserSignup } from "../workflows/user-signup.js"; @@ -196,13 +195,10 @@ app.post("/api/signup", async (req, reply) => { // Wait for Fastify to be ready before handling requests await app.ready(); -// Expose Fastify app as a Nitro handler -export default fromNodeHandler((req, res) => { - return new Promise((resolve) => { - res.on("finish", resolve); - app.server.emit("request", req, res); - }); -}); + +export default (req: any, res: any) => { + app.server.emit("request", req, res); +}; ``` This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow. diff --git a/workbench/fastify/nitro.config.ts b/workbench/fastify/nitro.config.ts index 8e89eea15..175d1ace4 100644 --- a/workbench/fastify/nitro.config.ts +++ b/workbench/fastify/nitro.config.ts @@ -4,7 +4,7 @@ export default defineNitroConfig({ modules: ['workflow/nitro'], vercel: { entryFormat: 'node' }, routes: { - '/**': './src/index.ts', + '/**': { handler: './src/index.ts', format: 'node' }, }, plugins: ['plugins/start-pg-world.ts'], }); diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index c9780b0a5..e3e6386c9 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -1,6 +1,5 @@ import Fastify from 'fastify'; import { createReadStream } from 'node:fs'; -import { fromNodeHandler } from 'nitro/h3'; import { getHookByToken, getRun, resumeHook, start } from 'workflow/api'; import { hydrateWorkflowArguments } from 'workflow/internal/serialization'; import { @@ -249,9 +248,6 @@ server.post('/api/test-direct-step-call', async (req: any, reply) => { await server.ready(); -export default fromNodeHandler((req, res) => { - return new Promise((resolve) => { - res.on('finish', resolve); - server.server.emit('request', req, res); - }); -}); +export default (req: any, res: any) => { + server.server.emit('request', req, res); +}; From de49972ee6366e48084531cf0314dd08cea1822f Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Tue, 25 Nov 2025 12:06:53 +0400 Subject: [PATCH 50/60] debug print to see stream chunks Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index e3e6386c9..8472e82cb 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -135,19 +135,47 @@ server.get('/api/trigger', async (req: any, reply) => { const stream = run.getReadable({ namespace }); const reader = stream.getReader(); + const toFramedChunk = (value: unknown) => { + if (typeof value === 'string') { + return { data: Buffer.from(value).toString('base64') }; + } + if (value instanceof ArrayBuffer) { + return { data: Buffer.from(value).toString('base64') }; + } + if (ArrayBuffer.isView(value)) { + const view = value as ArrayBufferView; + const buf = Buffer.from( + view.buffer, + view.byteOffset, + view.byteLength + ); + return { data: buf.toString('base64') }; + } + return value; + }; + reply.type('application/octet-stream'); // Fastify runs on Node and doesn’t send Web ReadableStreams directly // read from the Web reader and write framed chunks to the raw response try { + let chunkCount = 0; while (true) { const { done, value } = await reader.read(); if (done) break; - const data = - value instanceof Uint8Array - ? { data: Buffer.from(value).toString('base64') } - : value; - reply.raw.write(`${JSON.stringify(data)}\n`); + if (chunkCount < 4) { + console.log( + '[fastify output-stream] chunk', + chunkCount, + value?.constructor?.name, + typeof value, + value + ); + } + chunkCount += 1; + + const framed = toFramedChunk(value); + reply.raw.write(`${JSON.stringify(framed)}\n`); } reply.raw.end(); } catch (error) { From 396ceb5794cbb9e8b9c4db6983e0d4b00635d485 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Tue, 25 Nov 2025 11:11:02 -0800 Subject: [PATCH 51/60] use readfile and resolve for root route --- workbench/fastify/src/index.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 8472e82cb..9546eff20 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -1,5 +1,4 @@ import Fastify from 'fastify'; -import { createReadStream } from 'node:fs'; import { getHookByToken, getRun, resumeHook, start } from 'workflow/api'; import { hydrateWorkflowArguments } from 'workflow/internal/serialization'; import { @@ -7,6 +6,8 @@ import { WorkflowRunNotCompletedError, } from 'workflow/internal/errors'; import { allWorkflows } from '../_workflows.js'; +import { resolve } from 'node:path'; +import { readFile } from 'node:fs/promises'; type JsonResult = { ok: true; value: any } | { ok: false; error: Error }; const parseJson = (text: string): JsonResult => { @@ -39,9 +40,9 @@ server.addContentTypeParser( } ); -server.get('/', async (_, reply) => { - const stream = createReadStream('./index.html'); - return reply.type('text/html').send(stream); +server.get('/', async (req, reply) => { + const html = await readFile(resolve('./index.html'), 'utf-8'); + return reply.type('text/html').send(html); }); server.post('/api/hook', async (req: any, reply) => { From 27d5d378fe62176a6386f67baa2daa1936fd0737 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Wed, 26 Nov 2025 00:10:11 +0400 Subject: [PATCH 52/60] moving index.html to /public Signed-off-by: Sree Narayanan --- workbench/fastify/index.html | 1 - 1 file changed, 1 deletion(-) delete mode 120000 workbench/fastify/index.html diff --git a/workbench/fastify/index.html b/workbench/fastify/index.html deleted file mode 120000 index 62524c9be..000000000 --- a/workbench/fastify/index.html +++ /dev/null @@ -1 +0,0 @@ -../nitro-v3/index.html \ No newline at end of file From bf297fefeac2d0309baca9baeb5b325d4903bcb4 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Wed, 26 Nov 2025 00:21:39 +0400 Subject: [PATCH 53/60] added back symlinked index.html (to copy during prebuildstep) Signed-off-by: Sree Narayanan --- workbench/fastify/index.html | 1 + 1 file changed, 1 insertion(+) create mode 120000 workbench/fastify/index.html diff --git a/workbench/fastify/index.html b/workbench/fastify/index.html new file mode 120000 index 000000000..62524c9be --- /dev/null +++ b/workbench/fastify/index.html @@ -0,0 +1 @@ +../nitro-v3/index.html \ No newline at end of file From 28e3decab04212c1d5e1b5137e39853a883b768c Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Wed, 26 Nov 2025 00:25:11 +0400 Subject: [PATCH 54/60] prebuild and postbuild script to copy and remove index.html Signed-off-by: Sree Narayanan --- workbench/fastify/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index e90fa07f3..3148bda5b 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -8,7 +8,9 @@ "scripts": { "generate:workflows": "node ../scripts/generate-workflows-registry.js", "predev": "pnpm generate:workflows", - "prebuild": "pnpm generate:workflows", + "copy:index": "mkdir -p public && cp index.html public/index.html", + "prebuild": "pnpm generate:workflows && pnpm copy:index", + "postbuild": "rm -f public/index.html", "build": "nitro build", "dev": "nitro dev", "start": "node .output/server/index.mjs" From 20291c13d48cf32fcda29e5b99c954377a05c423 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Wed, 26 Nov 2025 00:34:24 +0400 Subject: [PATCH 55/60] Sree Narayanan DCO Remediation Commit for Sree Narayanan I, Sree Narayanan , hereby add my Signed-off-by to this commit: b78bf227f41738c778e4a716d6e3240d4393cbd6 I, Sree Narayanan , hereby add my Signed-off-by to this commit: e7a456548e58f1cddcc690de0d9446b96772e593 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 37ee9ddaa629c76eaadbbcbaf22eb6f1c9458338 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 72912dc279a32993de897c089a13adfde86f68bd I, Sree Narayanan , hereby add my Signed-off-by to this commit: 4ebda5b505bb338f175e9cf41bc4dc166f46aa5b I, Sree Narayanan , hereby add my Signed-off-by to this commit: ccb690f36716c12b80443de7698f3db9da85cc09 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 6b80913d38e5e921b13de97152ba6510b1bf2473 I, Sree Narayanan , hereby add my Signed-off-by to this commit: c9fb3ebd801e95b74ed72a0dbff2cc3283ed2df6 Signed-off-by: Sree Narayanan From d199e8c7eb408fd4e52d84db0230eea016a58c55 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Tue, 25 Nov 2025 12:51:56 -0800 Subject: [PATCH 56/60] docs: remove preset in fastify docs --- docs/content/docs/getting-started/fastify.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/content/docs/getting-started/fastify.mdx b/docs/content/docs/getting-started/fastify.mdx index 551ca036e..53a7f5c6e 100644 --- a/docs/content/docs/getting-started/fastify.mdx +++ b/docs/content/docs/getting-started/fastify.mdx @@ -55,7 +55,6 @@ import { defineNitroConfig } from "nitro/config"; export default defineNitroConfig({ modules: ["workflow/nitro"], vercel: { entryFormat: "node" }, - preset: "vercel", routes: { "/**": { handler: "./src/index.ts", format: "node" }, }, From 6df6ba5c945b65535a869b0536f81c278cfa4da8 Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Tue, 25 Nov 2025 12:56:19 -0800 Subject: [PATCH 57/60] move public/index.html symlink --- workbench/fastify/index.html | 1 - workbench/fastify/package.json | 4 +--- workbench/fastify/public/index.html | 1 + 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 120000 workbench/fastify/index.html create mode 120000 workbench/fastify/public/index.html diff --git a/workbench/fastify/index.html b/workbench/fastify/index.html deleted file mode 120000 index 62524c9be..000000000 --- a/workbench/fastify/index.html +++ /dev/null @@ -1 +0,0 @@ -../nitro-v3/index.html \ No newline at end of file diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index 3148bda5b..e90fa07f3 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -8,9 +8,7 @@ "scripts": { "generate:workflows": "node ../scripts/generate-workflows-registry.js", "predev": "pnpm generate:workflows", - "copy:index": "mkdir -p public && cp index.html public/index.html", - "prebuild": "pnpm generate:workflows && pnpm copy:index", - "postbuild": "rm -f public/index.html", + "prebuild": "pnpm generate:workflows", "build": "nitro build", "dev": "nitro dev", "start": "node .output/server/index.mjs" diff --git a/workbench/fastify/public/index.html b/workbench/fastify/public/index.html new file mode 120000 index 000000000..c4ebf3ef4 --- /dev/null +++ b/workbench/fastify/public/index.html @@ -0,0 +1 @@ +../../nitro-v3/index.html \ No newline at end of file From e60e0e882903e5f2f445441567f6b555c472ee5c Mon Sep 17 00:00:00 2001 From: Adrian Lam Date: Tue, 25 Nov 2025 13:24:11 -0800 Subject: [PATCH 58/60] Revert "move public/index.html symlink" This reverts commit 081d29fe16e7817912d69f1b3a3bcd3a38000d5a. --- workbench/fastify/index.html | 1 + workbench/fastify/package.json | 4 +++- workbench/fastify/public/index.html | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) create mode 120000 workbench/fastify/index.html delete mode 120000 workbench/fastify/public/index.html diff --git a/workbench/fastify/index.html b/workbench/fastify/index.html new file mode 120000 index 000000000..62524c9be --- /dev/null +++ b/workbench/fastify/index.html @@ -0,0 +1 @@ +../nitro-v3/index.html \ No newline at end of file diff --git a/workbench/fastify/package.json b/workbench/fastify/package.json index e90fa07f3..3148bda5b 100644 --- a/workbench/fastify/package.json +++ b/workbench/fastify/package.json @@ -8,7 +8,9 @@ "scripts": { "generate:workflows": "node ../scripts/generate-workflows-registry.js", "predev": "pnpm generate:workflows", - "prebuild": "pnpm generate:workflows", + "copy:index": "mkdir -p public && cp index.html public/index.html", + "prebuild": "pnpm generate:workflows && pnpm copy:index", + "postbuild": "rm -f public/index.html", "build": "nitro build", "dev": "nitro dev", "start": "node .output/server/index.mjs" diff --git a/workbench/fastify/public/index.html b/workbench/fastify/public/index.html deleted file mode 120000 index c4ebf3ef4..000000000 --- a/workbench/fastify/public/index.html +++ /dev/null @@ -1 +0,0 @@ -../../nitro-v3/index.html \ No newline at end of file From 95938f0fbd5da7f15ee4cba91581ee1fd56d5b2c Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 29 Nov 2025 00:58:05 +0400 Subject: [PATCH 59/60] removed stream output chunk debug log Signed-off-by: Sree Narayanan --- workbench/fastify/src/index.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/workbench/fastify/src/index.ts b/workbench/fastify/src/index.ts index 9546eff20..7c354822c 100644 --- a/workbench/fastify/src/index.ts +++ b/workbench/fastify/src/index.ts @@ -164,15 +164,6 @@ server.get('/api/trigger', async (req: any, reply) => { const { done, value } = await reader.read(); if (done) break; - if (chunkCount < 4) { - console.log( - '[fastify output-stream] chunk', - chunkCount, - value?.constructor?.name, - typeof value, - value - ); - } chunkCount += 1; const framed = toFramedChunk(value); From 8a83ad2367cc37e8a494686ce914bbc1b077bce7 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Sat, 29 Nov 2025 00:59:33 +0400 Subject: [PATCH 60/60] Sree Narayanan DCO Remediation Commit for Sree Narayanan I, Sree Narayanan , hereby add my Signed-off-by to this commit: df5dfc9849af3cd9e818cd816feec5586137eae7 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 809bacb88461da5e92aec5d31d936222407593b6 I, Sree Narayanan , hereby add my Signed-off-by to this commit: b270d02ee69ac072eaa4538a31ed110edf852cc2 I, Sree Narayanan , hereby add my Signed-off-by to this commit: cb73ae5b1f3f7059f4c432b8226f8eb9b0492724 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 2ee3af65040e969b91a491b2bb285cd2ed447e10 I, Sree Narayanan , hereby add my Signed-off-by to this commit: cab1381b0e08e3453a3e5a66f55d02a8effff0e3 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 9c7471b2fba60079c71951433d9d0649d8399ba3 I, Sree Narayanan , hereby add my Signed-off-by to this commit: 4583452a27c704ba474080d0c560a1b1b9724058 Signed-off-by: Sree Narayanan