w3cj/stoker(新しいタブで開きます)
主要言語: TypeScript
Utilities for hono and @hono/zod-openapi
- star 数
- 445
- watcher 数
- 5
- fork 数
- 38
- issue 数
- 8
- 最終更新
- 2025/08/05
主要言語: TypeScript
Utilities for hono and @hono/zod-openapi
stoke the flame 🤙🔥
Utilities for hono and @hono/zod-openapi.
To see real world usage of these utilities, checkout the hono-open-api-starter routes example
HTTP status code constants. Provides individual typed / documented exports. Use anywhere you need a status code instead of hard coding raw numbers.
Sourced from http-status-codes | RFC1945 (HTTP/1.0), RFC2616 (HTTP/1.1), RFC2518 (WebDAV), RFC6585 (Additional HTTP Status Codes), and RFC7538 (Permanent Redirect).
Why not use the
http-status-codespackage directly?http-status-codesexports enums which do not work well with the@hono/zod-openapitype system and the built inStatusCodetype fromhono/utils/http-status.
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; const app = new OpenAPIHono(); app.notFound((c) => { return c.json({ message: `Not Found - ${c.req.path}`, }, HttpStatusCodes.NOT_FOUND); }); app.onError((err, c) => { return c.json( { message: err.message, }, HttpStatusCodes.INTERNAL_SERVER_ERROR, ); }); app.openapi( createRoute({ path: "/", tags: ["Index"], description: "Index route", method: "get", responses: { [HttpStatusCodes.OK]: { content: { "application/json": { schema: z.object({ message: z.string(), }), }, }, description: "Index route", }, }, }), (c) => { return c.json({ message: "Hello World" }, HttpStatusCodes.OK); }, ); export default app;
HTTP status phrase constants.
import * as HttpStatusPhrases from "stoker/http-status-phrases"; console.log(HttpStatusPhrases.NOT_FOUND); // Not Found
A default 404 handler.
import { Hono } from "hono"; import notFound from "stoker/middlewares/not-found"; const app = new Hono(); app.notFound(notFound); export default app;
A default error handler.
import { Hono } from "hono"; import onError from "stoker/middlewares/on-error"; const app = new Hono(); app.onError(onError); export default app;
Serve an svg emoji as a favicon from /favicon.ico
import { Hono } from "hono"; import serveEmojiFavicon from "stoker/middlewares/serve-emoji-favicon"; const app = new Hono(); app.use(serveEmojiFavicon("🔥")); export default app;
A default error hook you can include in your OpenAPIHono instance. Includes the success status and ZodError
import { OpenAPIHono } from "@hono/zod-openapi"; import defaultHook from "stoker/openapi/default-hook"; /* Any validation errors will respond with status code 422 and body: { success: false, error: {}, // Full Zod Error } */ const app = new OpenAPIHono({ defaultHook, }); export default app;
Create a content / schema description with a type of application/json
import { z } from "@hono/zod-openapi"; import jsonContent from "stoker/openapi/helpers/json-content"; const schema = z.object({ message: z.string(), }); /* * Equivalent to: { content: { "application/json": { schema, }, }, description: "Retrieve the user", } */ const response = jsonContent( schema, "Retrieve the message" );
Useful for json body schema validators.
Create a content / schema description with a type of application/json and required set to true
import { z } from "@hono/zod-openapi"; import jsonContentRequired from "stoker/openapi/helpers/json-content-required"; const schema = z.object({ message: z.string(), }); /* * Equivalent to: { content: { "application/json": { schema, }, }, description: "Retrieve the user", required: true } */ const response = jsonContentRequired( schema, "Retrieve the message" );
Peer dependency of
@asteasolutions/zod-to-openapi
WARNING: Not recommended right now, type hints from @hono/zod-openapi are not correct when using this helper. If you don't absolutely need
oneOfin your specification, use zodor(anyOf) instead.
Create a json content / schema description where the schema can be oneOf multiple schemas. Useful when you have multiple possible validation response schemas.
import { z } from "@hono/zod-openapi"; import jsonContentOneOf from "stoker/openapi/helpers/json-content-one-of"; import createErrorSchema from "stoker/openapi/schemas/create-error-schema"; import IdParamsSchema from "stoker/openapi/schemas/id-params"; const bodySchema = z.object({ name: z.string(), }); /* * Equivalent to: { content: { "application/json": { schema: { oneOf: SchemaObject[] }, }, }, description: "Invalid Id params or Invalid Body" } */ const result = jsonContentOneOf( [createErrorSchema(IdParamsSchema), createErrorSchema(bodySchema)], "Invalid Id params or Invalid Body" );
Peer dependency of
@asteasolutions/zod-to-openapi
Used internally by stoker/openapi/helpers/json-content-one-of but exported here in case you need to access the generated schemas for other use cases.
import { z } from "@hono/zod-openapi"; import oneOf from "stoker/openapi/helpers/one-of"; import createErrorSchema from "stoker/openapi/schemas/create-error-schema"; import IdParamsSchema from "stoker/openapi/schemas/id-params"; const bodySchema = z.object({ name: z.string(), }); /* * Returns: SchemaObject[] */ const result = oneOf([createErrorSchema(IdParamsSchema), createErrorSchema(bodySchema)]);
Commonly used zod schemas for use when creating routes with @hono/zod-openapi
Validate id in path params as a number.
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import jsonContent from "stoker/openapi/helpers/json-content"; import IdParamsSchema from "stoker/openapi/schemas/id-params"; const app = new OpenAPIHono(); app.openapi( createRoute({ method: "get", path: "/users/{id}", request: { params: IdParamsSchema, }, responses: { [HttpStatusCodes.OK]: jsonContent( z.object({ id: z.number(), }), "Retrieve the user", ), }, }), (c) => { // id is a valid number const { id } = c.req.valid("param"); return c.json({ id, }, HttpStatusCodes.OK); }, ); export default app;
Validate slug in path params as a slug.
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import jsonContent from "stoker/openapi/helpers/json-content"; import SlugParamsSchema from "stoker/openapi/schemas/slug-params"; const app = new OpenAPIHono(); app.openapi( createRoute({ method: "get", path: "/posts/{slug}", request: { params: SlugParamsSchema, }, responses: { [HttpStatusCodes.OK]: jsonContent( z.object({ slug: z.string(), }), "Retrieve the post", ), }, }), (c) => { // slug is a valid slug const { slug } = c.req.valid("param"); return c.json({ slug, }, HttpStatusCodes.OK); }, ); export default app;
Validate id in path params as a uuid.
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import jsonContent from "stoker/openapi/helpers/json-content"; import IdUUIDParamsSchema from "stoker/openapi/schemas/id-uuid-params"; const app = new OpenAPIHono(); app.openapi( createRoute({ method: "get", path: "/users/{id}", request: { params: IdUUIDParamsSchema, }, responses: { [HttpStatusCodes.OK]: jsonContent( z.object({ id: z.uuid(), }), "Retrieve the user", ), }, }), (c) => { // id is a valid uuid const { id } = c.req.valid("param"); return c.json({ id, }, HttpStatusCodes.OK); }, ); export default app;
Validate a custom named path param using Zod string validators by calling the function getParamsSchema({ name, validator }).
Name defaults to id.
Validator defaults to uuid and supports type "uuid" | "nanoid" | "cuid" | "cuid2" | "ulid".
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import jsonContent from "stoker/openapi/helpers/json-content"; import getParamsSchema from "stoker/openapi/schemas/get-params-schema"; const app = new OpenAPIHono(); app.openapi( createRoute({ method: "get", path: "/users/{userId}", request: { params: getParamsSchema({ name: "userId", validator: "nanoid", }), }, responses: { [HttpStatusCodes.OK]: jsonContent( z.object({ userId: z.nanoid(), }), "Retrieve the user", ), }, }), (c) => { // userId is a valid nanoid const { userId } = c.req.valid("param"); return c.json({ userId, }, HttpStatusCodes.OK); }, ); export default app;
Create an object schema with a message string property. Useful for error messages.
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import * as HttpStatusPhrases from "stoker/http-status-phrases"; import jsonContent from "stoker/openapi/helpers/json-content"; import createMessageObjectSchema from "stoker/openapi/schemas/create-message-object"; import IdParamsSchema from "stoker/openapi/schemas/id-params"; const app = new OpenAPIHono(); app.openapi( createRoute({ method: "get", path: "/some-thing-that-might-not-be-found", responses: { [HttpStatusCodes.NOT_FOUND]: jsonContent( createMessageObjectSchema(HttpStatusPhrases.NOT_FOUND), HttpStatusPhrases.NOT_FOUND, ), }, }), (c) => { return c.json({ message: HttpStatusPhrases.NOT_FOUND, }, HttpStatusCodes.NOT_FOUND); }, ); export default app;
Create an example error schema with zod error / validation messages based on given schema.
import { createRoute, z } from "@hono/zod-openapi"; import * as HttpStatusCodes from "stoker/http-status-codes"; import jsonContent from "stoker/openapi/helpers/json-content"; import createErrorSchema from "stoker/openapi/schemas/create-error-schema"; const TaskSchema = z.object({ name: z.string(), completed: z.boolean().default(false), }); export const createTask = createRoute({ method: "post", path: "/task", request: { body: jsonContent(TaskSchema, "The Task"), }, responses: { // ... OK response here [HttpStatusCodes.UNPROCESSABLE_ENTITY]: jsonContent( // Creates example schema with validation messages for name / completed createErrorSchema(TaskSchema), "Invalid task", ), }, });
Project bootstrapped with antfu/starter-ts