@efebia/fastify-zod-reply

中文文档
1.6.0发布于 2026/11/10MITTypeScriptESM + CJS构建来源已验证近 30 天下载 3395

Fastify 5 plugin providing type-safe HTTP reply helpers and Zod v4 schema validation for routes, with auto-generated OpenAPI schemas and SSE support.

原始使用文档
文档目录16 节
  1. Install
  2. Usage
  3. 1. Register the plugin
  4. 2. Define a route with routeV4
  5. 3. Reply helpers
  6. SSE (Server-Sent Events)
  7. Custom validation errors
  8. API
  9. routeV4(schema, handler, options?)
  10. createRouteV4(options?)
  11. sseRouteV4(schema, handler, options?)
  12. createSSERouteV4(options?)
  13. buildHTTPErrorObject(statusCode, message)
  14. FastifyZodReplyError
  15. RouteTag / RouteSecurity
  16. License

@efebia/fastify-zod-reply

Fastify 5 plugin providing type-safe HTTP reply helpers and Zod v4 schema validation for routes, with auto-generated OpenAPI schemas and SSE support.

Install

npm install @efebia/fastify-zod-reply

Usage

1. Register the plugin

import Fastify from 'fastify';
import fastifyZodReply from '@efebia/fastify-zod-reply';

const fastify = Fastify();
await fastify.register(fastifyZodReply);

2. Define a route with routeV4

import { z } from 'zod';
import { routeV4 } from '@efebia/fastify-zod-reply';

fastify.get('/users/:id', routeV4(
  {
    Params: z.object({ id: z.string() }),
    Reply: z.object({
      200: z.object({ id: z.string(), name: z.string() }),
      404: z.object({ message: z.string() }),
    }),
  },
  async (request, reply) => {
    const user = await findUser(request.params.id);
    if (!user) return reply.notFound('User not found');
    return reply.ok(user);
  }
));

routeV4 automatically:

  • Validates Body, Params, Query, and Headers via Zod before the handler runs
  • Validates and serializes the response against the Reply schema
  • Generates the JSON Schema for Fastify's OpenAPI integration

3. Reply helpers

The plugin decorates FastifyReply with semantic methods:

reply.ok({ id: '1', name: 'Alice' })   // 200
reply.created({ id: '2' })              // 201
reply.accepted()                        // 202
reply.noContent()                       // 204

reply.badRequest('Validation failed')   // 400 — throws FastifyError
reply.unauthorized()                    // 401
reply.forbidden()                       // 403
reply.notFound('User not found')        // 404
reply.notAcceptable()                   // 406
reply.conflict()                        // 409
reply.internalServerError()             // 500

Passing a string to error methods throws a FastifyError with that message. Passing an object sends it as JSON.

SSE (Server-Sent Events)

Use sseRouteV4 for streaming endpoints:

import { sseRouteV4 } from '@efebia/fastify-zod-reply';

fastify.get('/events', sseRouteV4(
  {
    Reply: z.object({
      SSE: z.object({ data: z.object({ count: z.number() }) }),
    }),
  },
  async (request, reply) => {
    async function* generate() {
      for (let i = 0; i < 10; i++) {
        yield { data: { count: i } };
      }
    }
    return reply.sse({ stream: generate() });
  }
));

The SSE key in the Reply schema maps to the 200 status code with text/event-stream content type. request.abortController is automatically wired to the socket close event.

Custom validation errors

When Body, Params or Query fail Zod validation, routeV4 and sseRouteV4 reply 400 with { "message": "Error at <source>-><path>-><message>" } (one line per issue). To send something else, provide a validationErrorFormatter that receives the raw Zod issues and the source:

import {
  createRouteV4,
  type ValidationErrorFormatter,
} from '@efebia/fastify-zod-reply';

const formatter: ValidationErrorFormatter = (issues, source) => ({
  statusCode: 400,
  body: {
    code: 'VALIDATION_ERROR',
    message: 'Invalid request data',
    errors: issues.map((issue) => ({
      source,
      path: issue.path.join('.'),
      rule: issue.code === 'invalid_type' ? 'type' : 'invalid',
      code: issue.code,
      message: issue.message,
    })),
  },
});

// plugin-wide default
await fastify.register(fastifyZodReply, { validationErrorFormatter: formatter });
// or per factory
const routeV4 = createRouteV4({ validationErrorFormatter: formatter });
// or per route
fastify.post('/x', routeV4(schema, handler, { validationErrorFormatter: formatter }));
  • Signature: (issues: ValidationIssue[], source: 'body' | 'query' | 'params' | 'headers') => { statusCode?: number; body: unknown }. statusCode defaults to 400.
  • Precedence: route option, then createRouteV4/createSSERouteV4 option, then plugin option, then the built-in text.
  • The formatter is called once per failing source; the first failing source in body, params, query order wins.
  • A string body is sent verbatim, anything else as JSON with application/json. Custom bodies bypass the route's 400 reply schema, so they are not stripped or rejected by it.
  • defaultValidationErrorFormatter is exported and reproduces the built-in output.
  • 'headers' is part of the source type but not emitted today: headers are only checked by Fastify's JSON-schema validation, not by the Zod pre-handler.
  • Only request validation is affected. Reply validation (500) and SSE stream-item errors keep their text format.

API

routeV4(schema, handler, options?)

Pre-built route factory with strict: false.

createRouteV4(options?)

Factory for creating a custom routeV4 with shared defaults.

import { createRouteV4 } from '@efebia/fastify-zod-reply';

const routeV4 = createRouteV4({ strict: true });

Options (RouteV4Options):

OptionTypeDefaultDescription
strictboolean | { body, query, params, headers }falseStrip unknown fields from request inputs

Schema fields (BaseZodV4Schema):

FieldTypeDescription
Bodyz.ZodTypeAnyRequest body schema
Paramsz.ZodTypeAnyRoute params schema
Queryz.ZodTypeAnyQuery string schema
Headersz.ZodTypeAnyHeaders schema
Replyz.ZodObjectResponse schema keyed by HTTP status code
Tags(keyof RouteTag)[]OpenAPI tags
SecurityRouteSecurity[]OpenAPI security schemes
SummarystringOpenAPI summary
DescriptionstringOpenAPI description
NotesstringAdditional notes

sseRouteV4(schema, handler, options?)

Pre-built SSE route factory. The Reply schema must include an SSE key.

createSSERouteV4(options?)

Factory for creating a custom sseRouteV4. Accepts SSERouteV4Options:

OptionTypeDescription
strictboolean | objectSame as routeV4
sse.keepAliveIntervalnumberInterval (ms) for keep-alive pings
sse.onError(error) => voidGlobal error handler for the stream
sse.validateStreambooleanValidate each SSE event against the schema

buildHTTPErrorObject(statusCode, message)

Builds a plain HTTP error object.

FastifyZodReplyError

Error class thrown when response serialization fails.

RouteTag / RouteSecurity

Empty interfaces — extend via module augmentation to add your own OpenAPI tags and security schemes:

declare module '@efebia/fastify-zod-reply' {
  interface RouteTag {
    users: never;
    orders: never;
  }
  interface RouteSecurity {
    bearerAuth: never;
  }
}

License

MIT

版本与发布记录

@efebia/fastify-zod-reply 共发布 22 个版本,首次发布于 2025/04/08;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.6.0latest2026/11/103 天前
1.5.02026/03/108 个月前
1.4.32026/02/248 个月前
1.4.22026/02/208 个月前
1.4.12026/01/1210 个月前
1.4.02025/09/221.1 年前

关于 @efebia/fastify-zod-reply 的常见问题

@efebia/fastify-zod-reply 是什么?

Fastify 5 plugin providing type-safe HTTP reply helpers and Zod v4 schema validation for routes, with auto-generated OpenAPI schemas and SSE support.

如何安装 @efebia/fastify-zod-reply?

在项目目录运行 npm install @efebia/fastify-zod-reply,或使用 pnpm add / yarn add / bun add。

@efebia/fastify-zod-reply 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@efebia/fastify-zod-reply 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@efebia/fastify-zod-reply 可以商用吗?

@efebia/fastify-zod-reply 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@efebia/fastify-zod-reply 的下载量有多少?

根据 npm 官方下载统计,@efebia/fastify-zod-reply 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,395 次,日均约 113 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@efebia/fastify-zod-reply 还在维护吗?

最新版本 1.6.0 发布于 2026/11/10(3 天前);至今共发布 22 个版本,其中过去 12 个月发布了 5 个;首次发布于 2025/04/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。