Skip to content

OpenAPI generator drops operations: methods clobbered per path, PATCH/DELETE ignored, :id not templated #154

Description

@isaacwasserman

Summary

The OpenAPI generator (src/openapi.ts) produces an inaccurate document for any router with more than one method on a path, or with non-GET/POST routes. Operations silently disappear.

Reproduction

import { createEndpoint, createRouter } from "better-call";
import { z } from "zod";

const createTicket = createEndpoint("/tickets",
  { method: "POST", body: z.object({ subject: z.string() }) }, async () => ({}));
const listTickets = createEndpoint("/tickets",
  { method: "GET" }, async () => ({}));
const updateTicket = createEndpoint("/tickets/:id",
  { method: "PATCH", body: z.object({ status: z.string() }) }, async () => ({}));

const router = createRouter({ createTicket, listTickets, updateTicket });
// GET the reference route and inspect paths…

Expected

/tickets        -> get, post
/tickets/{id}   -> patch

Actual

/tickets        -> get         # POST clobbered
/tickets/:id                   # PATCH dropped entirely; ":id" never templated

Root causes

  • Per-path overwrite. paths[value.path] = { get: … } / = { post: … } reassigns the whole path item, so whichever endpoint is processed last wins. A POST registered before a GET on the same path is lost.
  • Only GET and POST are handled. There is no branch for PATCH/PUT/DELETE, so those operations never appear.
  • :id is never templated and no path parameters are emitted.
  • Scalar request-body fields render emptygetRequestBody only recurses into ZodObject properties, so string/number fields yield properties: {}.
  • Module-level paths is shared across generator() calls, leaking state between documents.
  • Hardcoded auth. Every operation asserts bearerAuth and the document asserts a top-level apiKeyCookie, neither of which is defined in components.securitySchemes — and neither is correct for a service that authenticates differently.
  • getHTML emits invalid JS (unquoted theme/title/description interpolation into the Scalar config).

Environment

better-call 2.0.5.

Fix

PR #153 rewrites the generator to merge methods per path, emit all documented verbs, template path params, extract bodies/params via the library-agnostic ~standard.jsonSchema interface, and make security document-driven (auth-agnostic by default).

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions