stoker

repository·main·Indexed 19 days ago

https://github.com/w3cj/stoker

A collection of utility libraries for Hono and @hono/zod-openapi. It provides typed HTTP status code and phrase constants, pre-configured middlewares for error and 404 handling, an emoji favicon server, and various OpenAPI helpers for JSON content descriptions and path parameter validation (UUID, slug, numeric IDs).

Tokens
8.4K
Snippets
28
Records
31
Agent score
66%

What's inside stoker

  1. Use the default error hook in OpenAPIHono

    main

    You can include defaultHook from stoker/openapi/default-hook in your OpenAPIHono instance. This hook automatically handles validation errors by responding with a 422 Unprocessable Entity status code and a JSON body containing a success: false flag and the full ZodError object.

    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;
  2. Generate oneOf schema arrays with oneOf

    main

    The oneOf helper from stoker/openapi/helpers/one-of can be used to access the generated SchemaObject[] for use cases outside of standard content descriptions. It is a peer dependency of @asteasolutions/zod-to-openapi.

    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)]);
  3. Serve an emoji favicon with serve-emoji-favicon

    main

    The stoker/middlewares/serve-emoji-favicon middleware allows you to serve an SVG emoji as your application's favicon from the /favicon.ico path.

    import { Hono } from "hono";
    import serveEmojiFavicon from "stoker/middlewares/serve-emoji-favicon";
    
    const app = new Hono();
    
    app.use(serveEmojiFavicon("🔥"));
    
    export default app;
  4. Create required JSON content descriptions with jsonContentRequired

    main

    Use jsonContentRequired from stoker/openapi/helpers/json-content-required to create a content/schema description for application/json where the required field is set to true. This is particularly useful for JSON body schema validators.

    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 message",
    //   required: true
    // }
    const response = jsonContentRequired(
      schema,
      "Retrieve the message"
    );
  5. Create error schemas with createErrorSchema

    main

    Use createErrorSchema from stoker/openapi/schemas/create-error-schema to generate an OpenAPI error schema that includes Zod validation messages based on a provided schema. This is useful for documenting 422 Unprocessable Entity responses.

    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: {
        [HttpStatusCodes.UNPROCESSABLE_ENTITY]: jsonContent(
          createErrorSchema(TaskSchema),
          "Invalid task",
        ),
      },
    });
  6. Create oneOf JSON content descriptions with jsonContentOneOf

    main

    Use jsonContentOneOf from stoker/openapi/helpers/json-content-one-of to create a JSON content description where the schema can be one of multiple provided schemas. This is useful for multiple possible validation response schemas.

    Warning: This helper is not currently recommended because type hints from @hono/zod-openapi may be incorrect when using it. If you do not strictly need oneOf in your specification, it is recommended to use Zod's .or() (which generates anyOf) instead.

    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"
    );
  7. Implement the not-found middleware

    main

    The stoker/middlewares/not-found middleware provides a default 404 handler for Hono applications. It sets the status code to 404 and responds with a JSON object containing a message property that includes the path that was not found.

    import { Hono } from "hono";
    import notFound from "stoker/middlewares/not-found";
    
    const app = new Hono();
    
    app.notFound(notFound);
    
    export default app;
  8. Use stoker HTTP status code constants

    main

    Instead of hard-coding raw numbers, use stoker/http-status-codes for typed and documented HTTP status code constants. These are specifically designed to work seamlessly with the @hono/zod-openapi type system and Hono's built-in StatusCode type, avoiding the compatibility issues found when using the http-status-codes package directly.

    import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
    import * as HttpStatusCodes from "stoker/http-status-codes";
    
    const app = new OpenAPIHono();
    
    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);
      },
    );
  9. Create JSON content descriptions with jsonContent

    main

    Use jsonContent from stoker/openapi/helpers/json-content to create a content/schema description for OpenAPI responses with the application/json type. It takes a Zod schema and a description string as arguments.

    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 message",
    // }
    const response = jsonContent(
      schema,
      "Retrieve the message"
    );
  10. Create a message object schema with createMessageObjectSchema

    main

    Use createMessageObjectSchema from stoker/openapi/schemas/create-message-object to create a Zod object schema containing a single message string property. This is useful for standardizing error response bodies.

    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";
    
    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);
      },
    );
  11. Validate custom path parameters with getParamsSchema

    main

    Use getParamsSchema from stoker/openapi/schemas/get-params-schema to validate a custom-named path parameter using specific Zod string validators.

    • name: The name of the path parameter (defaults to id).
    • validator: The type of validator to use. Supported values are: "uuid" | "nanoid" | "cuid" | "cuid2" | "ulid". (Defaults to "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 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) => {
        const { userId } = c.req.valid("param");
        return c.json({ userId }, HttpStatusCodes.OK);
      },
    );
  12. Use stoker HTTP status phrase constants

    main

    Access standard HTTP status phrases (e.g., "Not Found") using stoker/http-status-phrases.

    import * as HttpStatusPhrases from "stoker/http-status-phrases";
    
    console.log(HttpStatusPhrases.NOT_FOUND); // Not Found