@silkweave/fastify 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter/fastify.ts"],"mappings":";;;;;;;UAqBiB,qBAAA,SAA8B,kBAAA,CAAmB,MAAA,EAAQ,iBAAA;EACxE,IAAA;EACA,IAAA;EACA,IAAA,GAAO,UAAA;;EAEP,IAAA,GAAO,oBAAA;AAAA;AAAA,cA2KI,OAAA,EAAS,cAAA,CAAe,qBAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter/fastify.ts"],"mappings":";;;;;;;UAqBiB,qBAAA,SAA8B,kBAAA,CAAmB,MAAA,EAAQ,iBAAA;EACxE,IAAA;EACA,IAAA;EACA,IAAA,GAAO,UAAA;;EAEP,IAAA,GAAO,oBAAA;AAAA;AAAA,cA4LI,OAAA,EAAS,cAAA,CAAe,qBAAA"}
package/build/index.mjs CHANGED
@@ -28,10 +28,11 @@ function sendOAuth(reply, oauthRes) {
28
28
  }
29
29
  function mountOAuthRoutes(instance, auth) {
30
30
  const provider = auth.provider;
31
+ const callbackPath = auth.callbackPath ?? "/auth/callback";
31
32
  const paths = new Set([
32
33
  "/.well-known/oauth-authorization-server",
33
34
  "/authorize",
34
- "/auth/callback",
35
+ callbackPath,
35
36
  "/token",
36
37
  "/register"
37
38
  ]);
@@ -41,7 +42,7 @@ function mountOAuthRoutes(instance, auth) {
41
42
  instance.get("/authorize", async (req, reply) => {
42
43
  return sendOAuth(reply, await provider.authorize(toOAuthReq(req)));
43
44
  });
44
- instance.get("/auth/callback", async (req, reply) => {
45
+ instance.get(callbackPath, async (req, reply) => {
45
46
  return sendOAuth(reply, await provider.callback(toOAuthReq(req)));
46
47
  });
47
48
  instance.post("/token", async (req, reply) => {
@@ -70,30 +71,46 @@ function pickStreamFormat(acceptHeader) {
70
71
  if (acceptHeader.includes("application/x-ndjson") || acceptHeader.includes("application/ndjson")) return "ndjson";
71
72
  return null;
72
73
  }
74
+ function encodeChunk(format, chunk) {
75
+ const payload = JSON.stringify(chunk);
76
+ return format === "sse" ? `data: ${payload}\n\n` : `${payload}\n`;
77
+ }
78
+ function encodeStreamError(format, error) {
79
+ const payload = JSON.stringify({
80
+ error: error instanceof Error ? error.message : String(error),
81
+ name: error instanceof Error ? error.name : "Error"
82
+ });
83
+ return format === "sse" ? `event: error\ndata: ${payload}\n\n` : `${payload}\n`;
84
+ }
73
85
  async function streamAction(reply, format, action, input, context) {
74
86
  reply.raw.setHeader("Content-Type", format === "sse" ? "text/event-stream" : "application/x-ndjson");
75
87
  reply.raw.setHeader("Cache-Control", "no-cache, no-transform");
76
88
  reply.raw.setHeader("Connection", "keep-alive");
77
89
  reply.raw.flushHeaders?.();
78
90
  reply.hijack();
79
- const streamRun = action.run;
80
- const iter = streamRun(input, context);
91
+ const raw = reply.raw;
92
+ const iter = action.run(input, context);
93
+ const gone = { value: raw.destroyed || raw.writableEnded };
94
+ const onClose = () => {
95
+ gone.value = true;
96
+ };
97
+ raw.on("close", onClose);
98
+ const closed = once(raw, "close");
81
99
  try {
82
100
  for await (const chunk of iter) {
83
- const payload = JSON.stringify(chunk);
84
- const line = format === "sse" ? `data: ${payload}\n\n` : `${payload}\n`;
85
- if (!reply.raw.write(line)) await once(reply.raw, "drain");
101
+ if (gone.value) break;
102
+ if (!raw.write(encodeChunk(format, chunk))) {
103
+ await Promise.race([once(raw, "drain"), closed]);
104
+ if (gone.value) break;
105
+ }
86
106
  }
87
- if (format === "sse") reply.raw.write("event: done\ndata: {}\n\n");
107
+ if (!gone.value && format === "sse") raw.write("event: done\ndata: {}\n\n");
88
108
  } catch (error) {
89
- const payload = JSON.stringify({
90
- error: error instanceof Error ? error.message : String(error),
91
- name: error instanceof Error ? error.name : "Error"
92
- });
93
- if (format === "sse") reply.raw.write(`event: error\ndata: ${payload}\n\n`);
94
- else reply.raw.write(`${payload}\n`);
109
+ if (!gone.value) raw.write(encodeStreamError(format, error));
95
110
  } finally {
96
- reply.raw.end();
111
+ raw.off("close", onClose);
112
+ await iter.return?.().catch(() => {});
113
+ if (!raw.writableEnded) raw.end();
97
114
  }
98
115
  }
99
116
  function createActionLogger(instance) {
@@ -223,11 +240,11 @@ const fastify = ({ host, port, auth, cors: corsConfig, ...fastifyOptions }) => {
223
240
  request,
224
241
  ...authInfo ? { auth: authInfo } : {}
225
242
  });
226
- const input = resolveActionInput(action, {
243
+ const input = action.input.parse(resolveActionInput(action, {
227
244
  params: request.params,
228
245
  query: request.query,
229
246
  body: request.body
230
- });
247
+ }));
231
248
  if (streaming) {
232
249
  const format = pickStreamFormat(request.headers.accept);
233
250
  if (format) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["fastifyInstance"],"sources":["../src/adapter/fastify.ts"],"sourcesContent":["import type { FastifyCorsOptions } from '@fastify/cors'\nimport { AuthConfig, AuthInfo, generateProtectedResourceMetadata, OAuthRequest, OAuthResponse, validateToken } from '@silkweave/auth'\nimport { Action, actionMethod, ActionStreamRun, AdapterFactory, buildLogLevels, HttpMethod, isStreamingAction, Logger, LogLevel, methodHasBody, pathParamNames, resolveActionInput, runStreamingAction, SilkweaveContext, SilkweaveError, validateActionRouting } from '@silkweave/core'\nimport { once } from 'events'\nimport { FastifyBaseLogger, FastifyHttpOptions, fastify as fastifyInstance, FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'\nimport { Server } from 'http'\nimport z from 'zod/v4'\n\ntype FastifyLogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'\n\nconst PINO_LEVEL_MAP: Record<LogLevel, FastifyLogLevel> = {\n emergency: 'fatal',\n alert: 'fatal',\n critical: 'fatal',\n error: 'error',\n warning: 'warn',\n notice: 'debug',\n info: 'info',\n debug: 'debug'\n}\n\nexport interface FastifyAdapterOptions extends FastifyHttpOptions<Server, FastifyBaseLogger> {\n host?: string\n port?: number\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/`undefined` for permissive defaults, or a FastifyCorsOptions object. */\n cors?: FastifyCorsOptions | boolean\n}\n\nfunction toOAuthReq(request: FastifyRequest): OAuthRequest {\n return {\n method: request.method,\n url: new URL(request.url, `http://${request.hostname}`),\n headers: Object.fromEntries(Object.entries(request.headers).map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])),\n body: request.body as Record<string, string> | undefined\n }\n}\n\nfunction sendOAuth(reply: FastifyReply, oauthRes: OAuthResponse) {\n for (const [key, value] of Object.entries(oauthRes.headers)) { reply.header(key, value) }\n return reply.status(oauthRes.status).send(oauthRes.body)\n}\n\nfunction mountOAuthRoutes(instance: FastifyInstance, auth: AuthConfig): Set<string> {\n const provider = auth.provider!\n\n const paths = new Set([\n '/.well-known/oauth-authorization-server',\n '/authorize',\n '/auth/callback',\n '/token',\n '/register'\n ])\n\n instance.get('/.well-known/oauth-authorization-server', async (_req, reply) => {\n return sendOAuth(reply, provider.metadata())\n })\n instance.get('/authorize', async (req, reply) => {\n return sendOAuth(reply, await provider.authorize(toOAuthReq(req)))\n })\n instance.get('/auth/callback', async (req, reply) => {\n return sendOAuth(reply, await provider.callback(toOAuthReq(req)))\n })\n instance.post('/token', async (req, reply) => {\n return sendOAuth(reply, await provider.token(toOAuthReq(req)))\n })\n instance.post('/register', async (req, reply) => {\n return sendOAuth(reply, await provider.register(toOAuthReq(req)))\n })\n\n return paths\n}\n\nfunction mountAuthMiddleware(instance: FastifyInstance, auth: AuthConfig, oauthPaths: Set<string>, context: SilkweaveContext) {\n instance.decorateRequest('__silkweave_auth', undefined)\n instance.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n if (request.url.startsWith('/.well-known/') || oauthPaths.has(request.url.split('?')[0])) { return }\n const result = await validateToken(request.headers.authorization, auth, context.fork({ request }))\n if (result.error) {\n for (const [key, value] of Object.entries(result.error.headers)) {\n reply.header(key, value)\n }\n return reply.status(result.error.statusCode).send(result.error.body)\n }\n if (result.auth) {\n (request as FastifyRequest & { __silkweave_auth?: AuthInfo }).__silkweave_auth = result.auth\n }\n })\n}\n\ntype StreamFormat = 'sse' | 'ndjson'\n\nfunction pickStreamFormat(acceptHeader: string | undefined): StreamFormat | null {\n if (!acceptHeader) { return null }\n if (acceptHeader.includes('text/event-stream')) { return 'sse' }\n if (acceptHeader.includes('application/x-ndjson') || acceptHeader.includes('application/ndjson')) { return 'ndjson' }\n return null\n}\n\nasync function streamAction(\n reply: FastifyReply,\n format: StreamFormat,\n action: Action,\n input: object,\n context: SilkweaveContext\n): Promise<void> {\n reply.raw.setHeader('Content-Type', format === 'sse' ? 'text/event-stream' : 'application/x-ndjson')\n reply.raw.setHeader('Cache-Control', 'no-cache, no-transform')\n reply.raw.setHeader('Connection', 'keep-alive')\n reply.raw.flushHeaders?.()\n reply.hijack()\n const streamRun = action.run as ActionStreamRun<object, unknown>\n const iter = streamRun(input, context)\n try {\n for await (const chunk of iter) {\n const payload = JSON.stringify(chunk)\n const line = format === 'sse' ? `data: ${payload}\\n\\n` : `${payload}\\n`\n if (!reply.raw.write(line)) {\n await once(reply.raw, 'drain')\n }\n }\n if (format === 'sse') {\n reply.raw.write('event: done\\ndata: {}\\n\\n')\n }\n } catch (error) {\n const payload = JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n name: error instanceof Error ? error.name : 'Error'\n })\n if (format === 'sse') {\n reply.raw.write(`event: error\\ndata: ${payload}\\n\\n`)\n } else {\n reply.raw.write(`${payload}\\n`)\n }\n } finally {\n reply.raw.end()\n }\n}\n\nfunction createActionLogger(instance: FastifyInstance): Logger {\n return {\n ...buildLogLevels((level, data) => {\n const pinoLevel = PINO_LEVEL_MAP[level] ?? 'info'\n instance.log[pinoLevel](data)\n }),\n progress: ({ progress, total, message }) => { instance.log.trace({ progress, total }, message) }\n }\n}\n\ninterface ObjectSchema {\n type: 'object'\n properties: Record<string, unknown>\n required: string[]\n}\n\n/**\n * Split an action's input JSON Schema into Fastify `params`/`querystring`/`body`\n * schemas based on its `path` placeholders and `queryParams`. Fastify's own AJV\n * validation, type coercion, and default-filling then apply per source, and the\n * three are merged back into a single input by `resolveActionInput` at runtime.\n */\nfunction splitInputSchema(action: Action, method: HttpMethod): {\n params?: ObjectSchema\n querystring?: ObjectSchema\n body?: ObjectSchema\n} {\n const json = z.toJSONSchema(action.input) as { properties?: Record<string, unknown>; required?: string[] }\n const properties = json.properties ?? {}\n const required = new Set(json.required ?? [])\n const pathParams = new Set(pathParamNames(action.path))\n const queryKeys = new Set((action.queryParams ?? []).map(String))\n const hasBody = methodHasBody(method)\n\n const params: ObjectSchema = { type: 'object', properties: {}, required: [] }\n const querystring: ObjectSchema = { type: 'object', properties: {}, required: [] }\n const body: ObjectSchema = { type: 'object', properties: {}, required: [] }\n\n for (const [key, prop] of Object.entries(properties)) {\n if (pathParams.has(key)) {\n params.properties[key] = prop\n params.required.push(key)\n } else if (!hasBody || queryKeys.has(key)) {\n querystring.properties[key] = prop\n if (required.has(key)) { querystring.required.push(key) }\n } else {\n body.properties[key] = prop\n if (required.has(key)) { body.required.push(key) }\n }\n }\n\n return {\n params: Object.keys(params.properties).length ? params : undefined,\n querystring: Object.keys(querystring.properties).length ? querystring : undefined,\n body: hasBody && Object.keys(body.properties).length ? body : undefined\n }\n}\n\nexport const fastify: AdapterFactory<FastifyAdapterOptions> = ({ host, port, auth, cors: corsConfig, ...fastifyOptions }) => {\n const instance = fastifyInstance(fastifyOptions)\n return (options, baseContext) => {\n const context = baseContext.fork({ adapter: 'fastify' })\n return {\n context,\n start: async (actions) => {\n if (corsConfig !== false) {\n const userConfig = corsConfig === true || corsConfig === undefined ? {} : corsConfig\n await instance.register(import('@fastify/cors'), { origin: '*', ...userConfig })\n }\n\n await instance.register(import('@fastify/swagger'), {\n openapi: {\n info: {\n title: options.name,\n description: options.description,\n version: options.version\n }\n }\n })\n await instance.register(import('@scalar/fastify-api-reference'), { routePrefix: '/' })\n\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n instance.get('/.well-known/oauth-protected-resource', () => {\n return generateProtectedResourceMetadata(auth.resourceUrl!, auth.authorizationServers!, auth.requiredScopes)\n })\n }\n\n const oauthPaths = auth?.provider ? mountOAuthRoutes(instance, auth) : new Set<string>()\n\n if (auth) {\n mountAuthMiddleware(instance, auth, oauthPaths, context)\n }\n\n instance.setErrorHandler((error, _request, reply) => {\n if (error instanceof SilkweaveError) {\n return reply.status(error.statusCode).send({ error: error.code, message: error.message })\n }\n if (error instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: error.issues })\n }\n // Fastify's schema (AJV) validation failures for body/querystring/params.\n const validation = (error as { validation?: unknown }).validation\n if (validation) {\n return reply.status(400).send({ error: 'validation_error', issues: validation })\n }\n instance.log.error(error)\n return reply.status(500).send({ error: 'internal', message: 'Internal server error' })\n })\n\n const logger = createActionLogger(instance)\n\n for (const action of actions) {\n validateActionRouting(action)\n const method = actionMethod(action)\n const url = action.path ? `/${action.path.replace(/^\\//, '')}` : `/${action.name}`\n const { params, querystring, body } = splitInputSchema(action, method)\n const streaming = isStreamingAction(action)\n instance.route({\n method,\n url,\n schema: {\n description: action.description,\n ...(params ? { params } : {}),\n ...(querystring ? { querystring } : {}),\n ...(body ? { body } : {}),\n response: {\n 200: { description: 'Successful response' }\n }\n },\n handler: async (request, reply) => {\n const authInfo = auth ? (request as FastifyRequest & { __silkweave_auth?: AuthInfo }).__silkweave_auth : undefined\n const actionContext = context.fork({ logger, request, ...(authInfo ? { auth: authInfo } : {}) })\n const input = resolveActionInput(action, {\n params: request.params as Record<string, string | undefined>,\n query: request.query as Record<string, unknown>,\n body: request.body\n })\n if (streaming) {\n const format = pickStreamFormat(request.headers.accept)\n if (format) {\n await streamAction(reply, format, action, input, actionContext)\n return reply\n }\n return runStreamingAction(action, input, actionContext)\n }\n return action.run(input, actionContext)\n }\n })\n }\n await instance.listen({ host, port })\n },\n stop: async () => { await instance.close() }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["fastifyInstance"],"sources":["../src/adapter/fastify.ts"],"sourcesContent":["import type { FastifyCorsOptions } from '@fastify/cors'\nimport { AuthConfig, AuthInfo, generateProtectedResourceMetadata, OAuthRequest, OAuthResponse, validateToken } from '@silkweave/auth'\nimport { Action, actionMethod, ActionStreamRun, AdapterFactory, buildLogLevels, HttpMethod, isStreamingAction, Logger, LogLevel, methodHasBody, pathParamNames, resolveActionInput, runStreamingAction, SilkweaveContext, SilkweaveError, validateActionRouting } from '@silkweave/core'\nimport { once } from 'events'\nimport { FastifyBaseLogger, FastifyHttpOptions, fastify as fastifyInstance, FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'\nimport { Server } from 'http'\nimport z from 'zod/v4'\n\ntype FastifyLogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'\n\nconst PINO_LEVEL_MAP: Record<LogLevel, FastifyLogLevel> = {\n emergency: 'fatal',\n alert: 'fatal',\n critical: 'fatal',\n error: 'error',\n warning: 'warn',\n notice: 'debug',\n info: 'info',\n debug: 'debug'\n}\n\nexport interface FastifyAdapterOptions extends FastifyHttpOptions<Server, FastifyBaseLogger> {\n host?: string\n port?: number\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/`undefined` for permissive defaults, or a FastifyCorsOptions object. */\n cors?: FastifyCorsOptions | boolean\n}\n\nfunction toOAuthReq(request: FastifyRequest): OAuthRequest {\n return {\n method: request.method,\n url: new URL(request.url, `http://${request.hostname}`),\n headers: Object.fromEntries(Object.entries(request.headers).map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])),\n body: request.body as Record<string, string> | undefined\n }\n}\n\nfunction sendOAuth(reply: FastifyReply, oauthRes: OAuthResponse) {\n for (const [key, value] of Object.entries(oauthRes.headers)) { reply.header(key, value) }\n return reply.status(oauthRes.status).send(oauthRes.body)\n}\n\nfunction mountOAuthRoutes(instance: FastifyInstance, auth: AuthConfig): Set<string> {\n const provider = auth.provider!\n // The provider builds its upstream redirect_uri as `${resourceUrl}${callbackPath}`,\n // so the callback route must match the configured callbackPath, not a hardcoded one.\n const callbackPath = auth.callbackPath ?? '/auth/callback'\n\n const paths = new Set([\n '/.well-known/oauth-authorization-server',\n '/authorize',\n callbackPath,\n '/token',\n '/register'\n ])\n\n instance.get('/.well-known/oauth-authorization-server', async (_req, reply) => {\n return sendOAuth(reply, provider.metadata())\n })\n instance.get('/authorize', async (req, reply) => {\n return sendOAuth(reply, await provider.authorize(toOAuthReq(req)))\n })\n instance.get(callbackPath, async (req, reply) => {\n return sendOAuth(reply, await provider.callback(toOAuthReq(req)))\n })\n instance.post('/token', async (req, reply) => {\n return sendOAuth(reply, await provider.token(toOAuthReq(req)))\n })\n instance.post('/register', async (req, reply) => {\n return sendOAuth(reply, await provider.register(toOAuthReq(req)))\n })\n\n return paths\n}\n\nfunction mountAuthMiddleware(instance: FastifyInstance, auth: AuthConfig, oauthPaths: Set<string>, context: SilkweaveContext) {\n instance.decorateRequest('__silkweave_auth', undefined)\n instance.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {\n if (request.url.startsWith('/.well-known/') || oauthPaths.has(request.url.split('?')[0])) { return }\n const result = await validateToken(request.headers.authorization, auth, context.fork({ request }))\n if (result.error) {\n for (const [key, value] of Object.entries(result.error.headers)) {\n reply.header(key, value)\n }\n return reply.status(result.error.statusCode).send(result.error.body)\n }\n if (result.auth) {\n (request as FastifyRequest & { __silkweave_auth?: AuthInfo }).__silkweave_auth = result.auth\n }\n })\n}\n\ntype StreamFormat = 'sse' | 'ndjson'\n\nfunction pickStreamFormat(acceptHeader: string | undefined): StreamFormat | null {\n if (!acceptHeader) { return null }\n if (acceptHeader.includes('text/event-stream')) { return 'sse' }\n if (acceptHeader.includes('application/x-ndjson') || acceptHeader.includes('application/ndjson')) { return 'ndjson' }\n return null\n}\n\nfunction encodeChunk(format: StreamFormat, chunk: unknown): string {\n const payload = JSON.stringify(chunk)\n return format === 'sse' ? `data: ${payload}\\n\\n` : `${payload}\\n`\n}\n\nfunction encodeStreamError(format: StreamFormat, error: unknown): string {\n const payload = JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n name: error instanceof Error ? error.name : 'Error'\n })\n return format === 'sse' ? `event: error\\ndata: ${payload}\\n\\n` : `${payload}\\n`\n}\n\nasync function streamAction(\n reply: FastifyReply,\n format: StreamFormat,\n action: Action,\n input: object,\n context: SilkweaveContext\n): Promise<void> {\n reply.raw.setHeader('Content-Type', format === 'sse' ? 'text/event-stream' : 'application/x-ndjson')\n reply.raw.setHeader('Cache-Control', 'no-cache, no-transform')\n reply.raw.setHeader('Connection', 'keep-alive')\n reply.raw.flushHeaders?.()\n reply.hijack()\n const raw = reply.raw\n const iter = (action.run as ActionStreamRun<object, unknown>)(input, context)\n // On client disconnect the next write() returns false and a plain\n // `once(raw, 'drain')` would park forever - the generator would never resume,\n // its finally/cleanup would never run, and response/context stay pinned. Track\n // 'close' and race the drain against it so we bail and tear the generator down.\n const gone = { value: raw.destroyed || raw.writableEnded }\n const onClose = () => { gone.value = true }\n raw.on('close', onClose)\n const closed = once(raw, 'close')\n try {\n for await (const chunk of iter) {\n if (gone.value) { break }\n if (!raw.write(encodeChunk(format, chunk))) {\n await Promise.race([once(raw, 'drain'), closed])\n if (gone.value) { break }\n }\n }\n if (!gone.value && format === 'sse') { raw.write('event: done\\ndata: {}\\n\\n') }\n } catch (error) {\n if (!gone.value) { raw.write(encodeStreamError(format, error)) }\n } finally {\n raw.off('close', onClose)\n // Ask the generator to run its finally/cleanup (release DB handles etc).\n await iter.return?.().catch(() => { /* generator cleanup best-effort */ })\n if (!raw.writableEnded) { raw.end() }\n }\n}\n\nfunction createActionLogger(instance: FastifyInstance): Logger {\n return {\n ...buildLogLevels((level, data) => {\n const pinoLevel = PINO_LEVEL_MAP[level] ?? 'info'\n instance.log[pinoLevel](data)\n }),\n progress: ({ progress, total, message }) => { instance.log.trace({ progress, total }, message) }\n }\n}\n\ninterface ObjectSchema {\n type: 'object'\n properties: Record<string, unknown>\n required: string[]\n}\n\n/**\n * Split an action's input JSON Schema into Fastify `params`/`querystring`/`body`\n * schemas based on its `path` placeholders and `queryParams`. Fastify's own AJV\n * validation, type coercion, and default-filling then apply per source, and the\n * three are merged back into a single input by `resolveActionInput` at runtime.\n */\nfunction splitInputSchema(action: Action, method: HttpMethod): {\n params?: ObjectSchema\n querystring?: ObjectSchema\n body?: ObjectSchema\n} {\n const json = z.toJSONSchema(action.input) as { properties?: Record<string, unknown>; required?: string[] }\n const properties = json.properties ?? {}\n const required = new Set(json.required ?? [])\n const pathParams = new Set(pathParamNames(action.path))\n const queryKeys = new Set((action.queryParams ?? []).map(String))\n const hasBody = methodHasBody(method)\n\n const params: ObjectSchema = { type: 'object', properties: {}, required: [] }\n const querystring: ObjectSchema = { type: 'object', properties: {}, required: [] }\n const body: ObjectSchema = { type: 'object', properties: {}, required: [] }\n\n for (const [key, prop] of Object.entries(properties)) {\n if (pathParams.has(key)) {\n params.properties[key] = prop\n params.required.push(key)\n } else if (!hasBody || queryKeys.has(key)) {\n querystring.properties[key] = prop\n if (required.has(key)) { querystring.required.push(key) }\n } else {\n body.properties[key] = prop\n if (required.has(key)) { body.required.push(key) }\n }\n }\n\n return {\n params: Object.keys(params.properties).length ? params : undefined,\n querystring: Object.keys(querystring.properties).length ? querystring : undefined,\n body: hasBody && Object.keys(body.properties).length ? body : undefined\n }\n}\n\nexport const fastify: AdapterFactory<FastifyAdapterOptions> = ({ host, port, auth, cors: corsConfig, ...fastifyOptions }) => {\n const instance = fastifyInstance(fastifyOptions)\n return (options, baseContext) => {\n const context = baseContext.fork({ adapter: 'fastify' })\n return {\n context,\n start: async (actions) => {\n if (corsConfig !== false) {\n const userConfig = corsConfig === true || corsConfig === undefined ? {} : corsConfig\n await instance.register(import('@fastify/cors'), { origin: '*', ...userConfig })\n }\n\n await instance.register(import('@fastify/swagger'), {\n openapi: {\n info: {\n title: options.name,\n description: options.description,\n version: options.version\n }\n }\n })\n await instance.register(import('@scalar/fastify-api-reference'), { routePrefix: '/' })\n\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n instance.get('/.well-known/oauth-protected-resource', () => {\n return generateProtectedResourceMetadata(auth.resourceUrl!, auth.authorizationServers!, auth.requiredScopes)\n })\n }\n\n const oauthPaths = auth?.provider ? mountOAuthRoutes(instance, auth) : new Set<string>()\n\n if (auth) {\n mountAuthMiddleware(instance, auth, oauthPaths, context)\n }\n\n instance.setErrorHandler((error, _request, reply) => {\n if (error instanceof SilkweaveError) {\n return reply.status(error.statusCode).send({ error: error.code, message: error.message })\n }\n if (error instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: error.issues })\n }\n // Fastify's schema (AJV) validation failures for body/querystring/params.\n const validation = (error as { validation?: unknown }).validation\n if (validation) {\n return reply.status(400).send({ error: 'validation_error', issues: validation })\n }\n instance.log.error(error)\n return reply.status(500).send({ error: 'internal', message: 'Internal server error' })\n })\n\n const logger = createActionLogger(instance)\n\n for (const action of actions) {\n validateActionRouting(action)\n const method = actionMethod(action)\n const url = action.path ? `/${action.path.replace(/^\\//, '')}` : `/${action.name}`\n const { params, querystring, body } = splitInputSchema(action, method)\n const streaming = isStreamingAction(action)\n instance.route({\n method,\n url,\n schema: {\n description: action.description,\n ...(params ? { params } : {}),\n ...(querystring ? { querystring } : {}),\n ...(body ? { body } : {}),\n response: {\n 200: { description: 'Successful response' }\n }\n },\n handler: async (request, reply) => {\n const authInfo = auth ? (request as FastifyRequest & { __silkweave_auth?: AuthInfo }).__silkweave_auth : undefined\n const actionContext = context.fork({ logger, request, ...(authInfo ? { auth: authInfo } : {}) })\n // Fastify's AJV only validates the JSON-Schema projection, which\n // cannot express Zod refinements/transforms. Parse the merged input\n // so .refine()/.email()/.transform() are enforced here as they are\n // over MCP/tRPC/CLI (a ZodError becomes a 400 via setErrorHandler).\n const input = action.input.parse(resolveActionInput(action, {\n params: request.params as Record<string, string | undefined>,\n query: request.query as Record<string, unknown>,\n body: request.body\n }))\n if (streaming) {\n const format = pickStreamFormat(request.headers.accept)\n if (format) {\n await streamAction(reply, format, action, input, actionContext)\n return reply\n }\n return runStreamingAction(action, input, actionContext)\n }\n return action.run(input, actionContext)\n }\n })\n }\n await instance.listen({ host, port })\n },\n stop: async () => { await instance.close() }\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silkweave/fastify",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Silkweave Fastify REST Adapter",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.silkweave.dev",
@@ -31,8 +31,8 @@
31
31
  "@scalar/fastify-api-reference": "^1.49.0",
32
32
  "fastify": "^5.8.2",
33
33
  "zod": "^3.25.0",
34
- "@silkweave/auth": "3.1.0",
35
- "@silkweave/core": "3.1.0"
34
+ "@silkweave/auth": "3.2.1",
35
+ "@silkweave/core": "3.2.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@eslint/js": "^10.0.1",