Write a workaround for Integrating Better Auth's Open API to Hono Open API in the docs #535

Closed
opened 2026-03-13 07:51:39 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @a-man-called-q on GitHub (Jan 8, 2025).

Is this suited for github?

  • Yes, this is suited for github

As mentioned in #670 there are people who's having difficulties integrating Better Auth's Open API with Hono Open API solution(s).

As far as I know, this is not really a concern of Better Auth or at least it's too much for an effort to integrate it due to the implementation in hono:

app.on(["POST", "GET"], "/api/auth/**", (c) => {
	return auth.handler(c.req.raw);
});

I will post in the hono-openapi repo but it's best that we have a workaround mentioned in the docs until there are better solutions.

Describe the solution you'd like

Write a workaround in the docs based on this content:


There is no straight integration with hono-openapi nor zod-openapi at the moment. However, there's a workaround that you can do using openapi-merge :

import { auth } from "@/routes/api/auth/lib.js";  // import your Better Auth implementation (usually `auth.ts`)
import { apiReference } from "@scalar/hono-api-reference"; // import your UI preference, here we're using scalar
import type { Swagger } from "atlassian-openapi"; // import type because we need it for type casting in order for `openapi-merge` complains
import { openAPISpecs } from "hono-openapi"; // import hono-openapi for Hono's non-"Better Auth Open API schema"
import { isErrorResult, merge } from "openapi-merge"; 
import { server } from "./server.js"; // import your Hono main route/server.

// Generate non Better Auth Open API Schema
server.get(
  "/open-api",
  openAPISpecs(server, {
    documentation: {
      openapi: "3.1.0",
      info: { title: "foo", version: "1" },
      servers: [{ url: "http://localhost:3000", description: "local api" }],
    },
  })
);

// Merge both Better Auth and non Better Auth Open API Schema
server.get("/open-api/reference", async (c) => {
  const nonAuthRef = await fetch("http://localhost:3000/open-api").then(
    (res) => res.body
  );
  let result = "";

  if (nonAuthRef) {
    const reader = nonAuthRef.getReader();
    const decoder = new TextDecoder();

    let done = false;
    while (!done) {
      const { value, done: isDone } = await reader.read();
      if (value) {
        result += decoder.decode(value, { stream: true });
      }
      done = isDone;
    }

    console.log("Full stream content:", result);
  }

  const authRef = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3;

  const mergeResult = merge([
    {
      oas: JSON.parse(result),
    },
    {
      oas: authRef,
      pathModification: {
        prepend: "/api/auth",
      },
    },
  ]);

  if (isErrorResult(mergeResult)) return c.body(JSON.stringify(c.error));

  return c.body(JSON.stringify(mergeResult.output), 200);
});

// Open API UI
server.get(
  "/docs",
  apiReference({
    pageTitle: "Hono API Reference",
    spec: {
      url: "/open-api/reference",
    },
  })
);

Most of the code in the example are aligned with hono-openapi guide, however in order to merge both schema we have to add one more end-point and use merge for merging the Open API Schema and isErrorResult for error handling.

// Merge both Better Auth and non Better Auth Open API Schema
server.get("/api/open-api/reference", async (c) => {
  const nonAuthRef = await fetch("http://localhost:3000/open-api/default").then(
    (res) => res.body
  );
  let result = "";

  if (nonAuthRef) {
    const reader = nonAuthRef.getReader();
    const decoder = new TextDecoder();

    let done = false;
    while (!done) {
      const { value, done: isDone } = await reader.read();
      if (value) {
        result += decoder.decode(value, { stream: true });
      }
      done = isDone;
    }

    console.log("Full stream content:", result);
  }

  const authRef = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3;

  const mergeResult = merge([
    {
      oas: JSON.parse(result),
    },
    {
      oas: authRef,
      pathModification: {
        prepend: "/api/auth",
      },
    },
  ]);

  if (isErrorResult(mergeResult)) return c.body(JSON.stringify(c.error));

  return c.body(JSON.stringify(mergeResult.output), 200);
});

Describe alternatives you've considered

None, as explained in the problem description.

Additional context

image

Originally created by @a-man-called-q on GitHub (Jan 8, 2025). ### Is this suited for github? - [X] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. As mentioned in #670 there are people who's having difficulties integrating Better Auth's Open API with Hono Open API solution(s). As far as I know, this is not really a concern of Better Auth or at least it's too much for an effort to integrate it due to the implementation in hono: ``` app.on(["POST", "GET"], "/api/auth/**", (c) => { return auth.handler(c.req.raw); }); ``` I will post in the [`hono-openapi` repo](https://github.com/rhinobase/hono-openapi) but it's best that we have a workaround mentioned in the docs until there are better solutions. ### Describe the solution you'd like Write a workaround in the docs based on this content: ---- There is no straight integration with [`hono-openapi`](https://hono.dev/examples/hono-openapi) nor [`zod-openapi`](https://hono.dev/examples/zod-openapi) at the moment. However, there's a workaround that you can do using [`openapi-merge`](https://www.npmjs.com/package/openapi-merge) : ```typescript import { auth } from "@/routes/api/auth/lib.js"; // import your Better Auth implementation (usually `auth.ts`) import { apiReference } from "@scalar/hono-api-reference"; // import your UI preference, here we're using scalar import type { Swagger } from "atlassian-openapi"; // import type because we need it for type casting in order for `openapi-merge` complains import { openAPISpecs } from "hono-openapi"; // import hono-openapi for Hono's non-"Better Auth Open API schema" import { isErrorResult, merge } from "openapi-merge"; import { server } from "./server.js"; // import your Hono main route/server. // Generate non Better Auth Open API Schema server.get( "/open-api", openAPISpecs(server, { documentation: { openapi: "3.1.0", info: { title: "foo", version: "1" }, servers: [{ url: "http://localhost:3000", description: "local api" }], }, }) ); // Merge both Better Auth and non Better Auth Open API Schema server.get("/open-api/reference", async (c) => { const nonAuthRef = await fetch("http://localhost:3000/open-api").then( (res) => res.body ); let result = ""; if (nonAuthRef) { const reader = nonAuthRef.getReader(); const decoder = new TextDecoder(); let done = false; while (!done) { const { value, done: isDone } = await reader.read(); if (value) { result += decoder.decode(value, { stream: true }); } done = isDone; } console.log("Full stream content:", result); } const authRef = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3; const mergeResult = merge([ { oas: JSON.parse(result), }, { oas: authRef, pathModification: { prepend: "/api/auth", }, }, ]); if (isErrorResult(mergeResult)) return c.body(JSON.stringify(c.error)); return c.body(JSON.stringify(mergeResult.output), 200); }); // Open API UI server.get( "/docs", apiReference({ pageTitle: "Hono API Reference", spec: { url: "/open-api/reference", }, }) ); ``` Most of the code in the example are aligned with `hono-openapi` guide, however in order to merge both schema we have to add one more end-point and use `merge` for merging the Open API Schema and `isErrorResult` for error handling. ```typescript // Merge both Better Auth and non Better Auth Open API Schema server.get("/api/open-api/reference", async (c) => { const nonAuthRef = await fetch("http://localhost:3000/open-api/default").then( (res) => res.body ); let result = ""; if (nonAuthRef) { const reader = nonAuthRef.getReader(); const decoder = new TextDecoder(); let done = false; while (!done) { const { value, done: isDone } = await reader.read(); if (value) { result += decoder.decode(value, { stream: true }); } done = isDone; } console.log("Full stream content:", result); } const authRef = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3; const mergeResult = merge([ { oas: JSON.parse(result), }, { oas: authRef, pathModification: { prepend: "/api/auth", }, }, ]); if (isErrorResult(mergeResult)) return c.body(JSON.stringify(c.error)); return c.body(JSON.stringify(mergeResult.output), 200); }); ``` --- ### Describe alternatives you've considered None, as explained in the problem description. ### Additional context ![image](https://github.com/user-attachments/assets/5b7c6934-51cc-418f-be79-77185b315ed9)
Author
Owner

@krzkz94 commented on GitHub (Mar 4, 2025):

Hey, came across a similar issue, I think I found a better way of doing it with hono-openapi's built-in functions, avoiding the fetch call (which would've required a hardcoded url, no likey

// Generate and serve unified OpenAPI JSON file
app.get("/docs/openapi.json", async (c) => {
  const honoSpecs = await generateSpecs(app, {
    documentation: {
      info: {
        title: 'xxx API',
        version: '1.0.0',
        description: 'xx API Documentation',
      },
      servers: [
        { url: 'http://localhost:8787', description: 'Local Server' },
      ],
    },
  });

  const authSchema = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3;

  const mergeResult = merge([
    {
      oas: honoSpecs,
    },
    {
      oas: authSchema,
      pathModification: {
        prepend: "/api/auth",
      },
    },
  ]);

  if (isErrorResult(mergeResult)) {
    return c.json({ error: mergeResult.message }, 500);
  }

  return c.json(mergeResult.output);
});
@krzkz94 commented on GitHub (Mar 4, 2025): Hey, came across a similar issue, I think I found a better way of doing it with hono-openapi's built-in functions, avoiding the fetch call (which would've required a hardcoded url, no likey ``` // Generate and serve unified OpenAPI JSON file app.get("/docs/openapi.json", async (c) => { const honoSpecs = await generateSpecs(app, { documentation: { info: { title: 'xxx API', version: '1.0.0', description: 'xx API Documentation', }, servers: [ { url: 'http://localhost:8787', description: 'Local Server' }, ], }, }); const authSchema = (await auth.api.generateOpenAPISchema()) as Swagger.SwaggerV3; const mergeResult = merge([ { oas: honoSpecs, }, { oas: authSchema, pathModification: { prepend: "/api/auth", }, }, ]); if (isErrorResult(mergeResult)) { return c.json({ error: mergeResult.message }, 500); } return c.json(mergeResult.output); }); ```
Author
Owner

@dosubot[bot] commented on GitHub (Jun 15, 2025):

Hi, @a-man-called-q. I'm Dosu, and I'm helping the better-auth team manage their backlog. I'm marking this issue as stale.

Issue Summary:

  • You raised challenges with integrating Better Auth's Open API with Hono Open API.
  • Suggested using openapi-merge in the documentation as a workaround.
  • krzkz94 provided an alternative using hono-openapi's built-in functions.
  • The community positively received this solution, indicating its effectiveness.

Next Steps:

  • Please confirm if this issue is still relevant to the latest version of the better-auth repository by commenting here.
  • If no updates are provided, the issue will be automatically closed in 7 days.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Jun 15, 2025): Hi, @a-man-called-q. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog. I'm marking this issue as stale. **Issue Summary:** - You raised challenges with integrating Better Auth's Open API with Hono Open API. - Suggested using `openapi-merge` in the documentation as a workaround. - krzkz94 provided an alternative using hono-openapi's built-in functions. - The community positively received this solution, indicating its effectiveness. **Next Steps:** - Please confirm if this issue is still relevant to the latest version of the better-auth repository by commenting here. - If no updates are provided, the issue will be automatically closed in 7 days. Thank you for your understanding and contribution!
Author
Owner

@emersonlaurentino commented on GitHub (Jun 21, 2025):

A simple way to solve this is using sources by Scalar:

app.get(
  "/docs",
  Scalar({
    pageTitle: title,
    sources: [
      { url: "/api/open-api", title: "Api" },
      { url: "/api/auth/open-api/generate-schema", title: "Auth" },
    ],
  })
);

/auth/open-api/generate-schema is generated by the openAPI better-auth plugin.

2fe1be0e5f/packages/better-auth/src/plugins/open-api/index.ts (L64)

https://github.com/user-attachments/assets/77be1147-0c66-46ca-8f28-ee1304bac66d

@emersonlaurentino commented on GitHub (Jun 21, 2025): A simple way to solve this is using `sources` by Scalar: ```ts app.get( "/docs", Scalar({ pageTitle: title, sources: [ { url: "/api/open-api", title: "Api" }, { url: "/api/auth/open-api/generate-schema", title: "Auth" }, ], }) ); ``` `/auth/open-api/generate-schema` is generated by the `openAPI` better-auth plugin. https://github.com/better-auth/better-auth/blob/2fe1be0e5f023be77b07206dd960f9fd38abba8c/packages/better-auth/src/plugins/open-api/index.ts#L64 https://github.com/user-attachments/assets/77be1147-0c66-46ca-8f28-ee1304bac66d
Author
Owner

@niklashansson commented on GitHub (Jun 29, 2025):

@emersonlaurentino Thanks a lot for this!

@niklashansson commented on GitHub (Jun 29, 2025): @emersonlaurentino Thanks a lot for this!
Author
Owner

@dosubot[bot] commented on GitHub (Sep 28, 2025):

Hi, @a-man-called-q. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You requested a documentation workaround for integrating Better Auth's Open API with Hono Open API using openapi-merge.
  • Community members shared improved methods: hono-openapi's built-in schema merging functions and Scalar's sources option.
  • These solutions avoid hardcoded URLs and have strong community support.
  • The issue was marked stale previously pending confirmation of relevance.
  • The problem has been effectively resolved through these community contributions.

Next Steps:

  • Please confirm if this issue is still relevant to the latest version of better-auth by commenting below.
  • If no response is received, I will automatically close the issue in 7 days.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Sep 28, 2025): Hi, @a-man-called-q. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You requested a documentation workaround for integrating Better Auth's Open API with Hono Open API using openapi-merge. - Community members shared improved methods: hono-openapi's built-in schema merging functions and Scalar's `sources` option. - These solutions avoid hardcoded URLs and have strong community support. - The issue was marked stale previously pending confirmation of relevance. - The problem has been effectively resolved through these community contributions. **Next Steps:** - Please confirm if this issue is still relevant to the latest version of better-auth by commenting below. - If no response is received, I will automatically close the issue in 7 days. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#535