feat(docs): use parameterized OpenAPI server URL

Replace the static `https://sofa.example.com/api/v1` server entry with a variable-based URL (`{protocol}://{host}:{port}/api/v1`) so the spec works against any instance out of the box. Also move the output path from `docs/openapi.json` to `docs/public/openapi.json` so the file is served as a static asset by the docs site.
This commit is contained in:
jake committed 2026-03-15 14:40:33 -04:00
1 parent d885fc524b
commit 4ce285f721
58 files changed
+95 -60

No files matched your search

+5 -2
View File
@@ -1,4 +1,7 @@
import { OpenAPIGenerator } from "@orpc/openapi"; import {
OpenAPIGenerator,
type OpenAPIGeneratorGenerateOptions,
} from "@orpc/openapi";
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4"; import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
import { import {
BackupSchema, BackupSchema,
@@ -214,7 +217,7 @@ export function normalizeOpenApiSpec<T extends OpenApiSpec>(spec: T): T {
export async function generateOpenApiSpec(options: { export async function generateOpenApiSpec(options: {
title: string; title: string;
version: string; version: string;
servers: Array<{ url: string }>; servers: OpenAPIGeneratorGenerateOptions["servers"];
sessionCookieName: string; sessionCookieName: string;
tags?: Array<{ name: string; description?: string }>; tags?: Array<{ name: string; description?: string }>;
}): Promise<OpenApiSpec> { }): Promise<OpenApiSpec> {
@@ -14,4 +14,4 @@ _openapi:
Delete the current user's profile avatar, reverting to the default. Delete the current user's profile avatar, reverting to the default.
<APIPage document={"./openapi.json"} operations={[{"path":"/account/avatar","method":"delete"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/account/avatar","method":"delete"}]} />
@@ -14,4 +14,4 @@ _openapi:
Change the current user's display name. Change the current user's display name.
<APIPage document={"./openapi.json"} operations={[{"path":"/account/name","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/account/name","method":"put"}]} />
@@ -16,4 +16,4 @@ _openapi:
Upload a new profile avatar image. Accepts JPEG, PNG, WebP, or GIF up to 2 MB. Upload a new profile avatar image. Accepts JPEG, PNG, WebP, or GIF up to 2 MB.
<APIPage document={"./openapi.json"} operations={[{"path":"/account/avatar","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/account/avatar","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Create a new manual database backup. The backup is tagged as a manual backup. Create a new manual database backup. The backup is tagged as a manual backup.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Permanently delete a database backup file by filename. Permanently delete a database backup file by filename.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups/{filename}","method":"delete"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups/{filename}","method":"delete"}]} />
@@ -14,4 +14,4 @@ _openapi:
Fetch all database backups with their sizes and creation times. Fetch all database backups with their sizes and creation times.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Upload a database backup file and restore it. A pre-restore backup is automatically created before overwriting the current database. Upload a database backup file and restore it. A pre-restore backup is automatically created before overwriting the current database.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups/restore","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups/restore","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Fetch the current automated backup schedule configuration. Fetch the current automated backup schedule configuration.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups/schedule","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups/schedule","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Update the automated backup schedule. Only provided fields are changed; omitted fields keep their current values. Update the automated backup schedule. Only provided fields are changed; omitted fields keep their current values.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/backups/schedule","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/backups/schedule","method":"put"}]} />
@@ -16,4 +16,4 @@ _openapi:
Delete all cached TMDB images from disk. Images will be re-downloaded on demand. Delete all cached TMDB images from disk. Images will be re-downloaded on demand.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/cache/purge-images","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/cache/purge-images","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Delete un-enriched stub titles not in any user's library and clean up orphaned person records. Delete un-enriched stub titles not in any user's library and clean up orphaned person records.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/cache/purge-metadata","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/cache/purge-metadata","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Check whether new user registration is currently open or closed. Check whether new user registration is currently open or closed.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/registration","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/registration","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch whether anonymous telemetry is enabled and when the last report was sent. Fetch whether anonymous telemetry is enabled and when the last report was sent.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/telemetry","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/telemetry","method":"get"}]} />
@@ -14,4 +14,4 @@ _openapi:
Open or close new user registration. Open or close new user registration.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/registration","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/registration","method":"put"}]} />
@@ -14,4 +14,4 @@ _openapi:
Enable or disable anonymous telemetry reporting. Enable or disable anonymous telemetry reporting.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/telemetry","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/telemetry","method":"put"}]} />
@@ -14,4 +14,4 @@ _openapi:
Enable or disable automatic update checks against the public API. Enable or disable automatic update checks against the public API.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/update-check","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/update-check","method":"put"}]} />
@@ -16,4 +16,4 @@ _openapi:
Manually trigger a background cron job by name. The job runs asynchronously. Manually trigger a background cron job by name. The job runs asynchronously.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/jobs/trigger","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/jobs/trigger","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch whether automatic update checks are enabled, and the latest cached check result if available. Fetch whether automatic update checks are enabled, and the latest cached check result if available.
<APIPage document={"./openapi.json"} operations={[{"path":"/admin/update-check","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/update-check","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch TV shows the user is currently watching, with the next unwatched episode and progress for each. Fetch TV shows the user is currently watching, with the next unwatched episode and progress for each.
<APIPage document={"./openapi.json"} operations={[{"path":"/dashboard/continue-watching","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/dashboard/continue-watching","method":"get"}]} />
@@ -14,4 +14,4 @@ _openapi:
Fetch all titles in the user's library with their tracking statuses. Fetch all titles in the user's library with their tracking statuses.
<APIPage document={"./openapi.json"} operations={[{"path":"/dashboard/library","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/dashboard/library","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch personalized title recommendations based on the user's library and watch history. Fetch personalized title recommendations based on the user's library and watch history.
<APIPage document={"./openapi.json"} operations={[{"path":"/dashboard/recommendations","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/dashboard/recommendations","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch summary counts for the current user: movies watched this month, episodes this week, library size, and completed titles. Fetch summary counts for the current user: movies watched this month, episodes this week, library size, and completed titles.
<APIPage document={"./openapi.json"} operations={[{"path":"/dashboard/stats","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/dashboard/stats","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch the user's watch counts grouped by time period. Useful for rendering activity charts. Fetch the user's watch counts grouped by time period. Useful for rendering activity charts.
<APIPage document={"./openapi.json"} operations={[{"path":"/dashboard/watch-history","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/dashboard/watch-history","method":"get"}]} />
+1 -1
View File
@@ -16,4 +16,4 @@ _openapi:
Browse movies or TV shows filtered by genre, sorted by popularity. Returns user statuses and episode progress. Browse movies or TV shows filtered by genre, sorted by popularity. Returns user statuses and episode progress.
<APIPage document={"./openapi.json"} operations={[{"path":"/discover","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/discover","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Record watch events for multiple episodes at once. Useful for marking a range of episodes as watched. Record watch events for multiple episodes at once. Useful for marking a range of episodes as watched.
<APIPage document={"./openapi.json"} operations={[{"path":"/episodes/batch-watch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/episodes/batch-watch","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Remove the watch record for a single TV episode. Remove the watch record for a single TV episode.
<APIPage document={"./openapi.json"} operations={[{"path":"/episodes/{id}/unwatch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/episodes/{id}/unwatch","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Record a watch event for a single TV episode. Record a watch event for a single TV episode.
<APIPage document={"./openapi.json"} operations={[{"path":"/episodes/{id}/watch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/episodes/{id}/watch","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch the list of TMDB genres for movies or TV shows. Used to populate genre filters for discovery. Fetch the list of TMDB genres for movies or TV shows. Used to populate genre filters for discovery.
<APIPage document={"./openapi.json"} operations={[{"path":"/explore/genres","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/explore/genres","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch currently popular movies or TV shows from TMDB with the user's tracking statuses. Fetch currently popular movies or TV shows from TMDB with the user's tracking statuses.
<APIPage document={"./openapi.json"} operations={[{"path":"/explore/popular","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/explore/popular","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch today's trending movies and/or TV shows from TMDB, including a featured hero title and the user's statuses. Fetch today's trending movies and/or TV shows from TMDB, including a featured hero title and the user's statuses.
<APIPage document={"./openapi.json"} operations={[{"path":"/explore/trending","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/explore/trending","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Create a new media server integration or update an existing one. Generates a unique webhook token for the provider. Create a new media server integration or update an existing one. Generates a unique webhook token for the provider.
<APIPage document={"./openapi.json"} operations={[{"path":"/integrations","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/integrations","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Remove a media server integration and all its event history. Remove a media server integration and all its event history.
<APIPage document={"./openapi.json"} operations={[{"path":"/integrations/{provider}","method":"delete"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/integrations/{provider}","method":"delete"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch all configured media server integrations for the current user, including recent webhook/sync events for each. Fetch all configured media server integrations for the current user, including recent webhook/sync events for each.
<APIPage document={"./openapi.json"} operations={[{"path":"/integrations","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/integrations","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Generate a new webhook token for an integration. The old token is immediately invalidated. Generate a new webhook token for an integration. The old token is immediately invalidated.
<APIPage document={"./openapi.json"} operations={[{"path":"/integrations/{provider}/regenerate-token","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/integrations/{provider}/regenerate-token","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch a person's profile and filmography. Imports from TMDB on first access if not yet cached locally. Fetch a person's profile and filmography. Imports from TMDB on first access if not yet cached locally.
<APIPage document={"./openapi.json"} operations={[{"path":"/people/{id}","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/people/{id}","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Look up or import a person by their TMDB ID. Returns the internal ID for use with other endpoints. Look up or import a person by their TMDB ID. Returns the internal ID for use with other endpoints.
<APIPage document={"./openapi.json"} operations={[{"path":"/people/resolve","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/people/resolve","method":"post"}]} />
+1 -1
View File
@@ -16,4 +16,4 @@ _openapi:
Full-text search across movies, TV shows, and people via TMDB. Optionally filter by media type. Full-text search across movies, TV shows, and people via TMDB. Optionally filter by media type.
<APIPage document={"./openapi.json"} operations={[{"path":"/search","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/search","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Remove all watch records for episodes in a season in a single operation. Remove all watch records for episodes in a season in a single operation.
<APIPage document={"./openapi.json"} operations={[{"path":"/seasons/{id}/unwatch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/seasons/{id}/unwatch","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Mark all episodes in a season as watched in a single operation. Mark all episodes in a season as watched in a single operation.
<APIPage document={"./openapi.json"} operations={[{"path":"/seasons/{id}/watch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/seasons/{id}/watch","method":"post"}]} />
@@ -17,4 +17,4 @@ _openapi:
Fetch the authentication configuration including OIDC availability, password login status, and registration state. Does not require authentication. Fetch the authentication configuration including OIDC availability, password login status, and registration state. Does not require authentication.
<APIPage document={"./openapi.json"} operations={[{"path":"/system/auth-config","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/system/auth-config","method":"get"}]} />
@@ -17,4 +17,4 @@ _openapi:
Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment. Does not require authentication. Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment. Does not require authentication.
<APIPage document={"./openapi.json"} operations={[{"path":"/system/health","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/system/health","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch public information about this Sofa instance. Does not require authentication. Used by the login screen to display instance details. Fetch public information about this Sofa instance. Does not require authentication. Used by the login screen to display instance details.
<APIPage document={"./openapi.json"} operations={[{"path":"/system/public-info","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/system/public-info","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Quick check of whether TMDB is configured. Does not require authentication. Quick check of whether TMDB is configured. Does not require authentication.
<APIPage document={"./openapi.json"} operations={[{"path":"/system/status","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/system/status","method":"get"}]} />
@@ -17,4 +17,4 @@ _openapi:
Fetch full title metadata including seasons, cast, and streaming availability. Imports from TMDB on first access if not yet cached locally. Fetch full title metadata including seasons, cast, and streaming availability. Imports from TMDB on first access if not yet cached locally.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch full season and episode data from TMDB for a TV show. Required before tracking individual episodes. Fetch full season and episode data from TMDB for a TV show. Required before tracking individual episodes.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/hydrate-seasons","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/hydrate-seasons","method":"post"}]} />
@@ -17,4 +17,4 @@ _openapi:
Import a title by TMDB ID and add it to the user's watchlist in one step. If the title already exists in the user's library, returns alreadyAdded: true. Import a title by TMDB ID and add it to the user's watchlist in one step. If the title already exists in the user's library, returns alreadyAdded: true.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/quick-add","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/quick-add","method":"post"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch similar titles based on locally cached recommendation data, along with the user's statuses for each. Fetch similar titles based on locally cached recommendation data, along with the user's statuses for each.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/recommendations","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/recommendations","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Look up or import a title by its TMDB ID and media type. Returns the internal ID for use with other endpoints. Look up or import a title by its TMDB ID and media type. Returns the internal ID for use with other endpoints.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/resolve","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/resolve","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Set a 0-5 star rating for a title. Use 0 to clear the rating. Set a 0-5 star rating for a title. Use 0 to clear the rating.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/rating","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/rating","method":"put"}]} />
@@ -16,4 +16,4 @@ _openapi:
Set the user's tracking status for a title. Use null to remove the title from the library entirely. Set the user's tracking status for a title. Use null to remove the title from the library entirely.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/status","method":"put"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/status","method":"put"}]} />
@@ -16,4 +16,4 @@ _openapi:
Fetch the current user's tracking status, rating, and watched episode IDs for a title. Fetch the current user's tracking status, rating, and watched episode IDs for a title.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/user-info","method":"get"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/user-info","method":"get"}]} />
@@ -16,4 +16,4 @@ _openapi:
Mark every episode of a TV show as watched. Requires seasons to be hydrated first. Mark every episode of a TV show as watched. Requires seasons to be hydrated first.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/watch-all","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/watch-all","method":"post"}]} />
@@ -14,4 +14,4 @@ _openapi:
Log a watch event for a movie. Automatically sets status to completed. Log a watch event for a movie. Automatically sets status to completed.
<APIPage document={"./openapi.json"} operations={[{"path":"/titles/{id}/watch","method":"post"}]} /> <APIPage document={"./public/openapi.json"} operations={[{"path":"/titles/{id}/watch","method":"post"}]} />
+2 -1
View File
@@ -10,6 +10,7 @@
"mobile-app", "mobile-app",
"telemetry", "telemetry",
"---API Reference---", "---API Reference---",
"...api" "...api",
"external:[openapi.json](/openapi.json)"
] ]
} }
+16 -1
View File
@@ -5,7 +5,22 @@
}, },
"servers": [ "servers": [
{ {
"url": "https://sofa.example.com/api/v1" "url": "{protocol}://{host}:{port}/api/v1",
"variables": {
"protocol": {
"default": "http",
"enum": [
"http",
"https"
]
},
"host": {
"default": "localhost"
},
"port": {
"default": "3000"
}
}
} }
], ],
"tags": [ "tags": [
+1 -1
View File
@@ -1,5 +1,5 @@
import { createOpenAPI } from "fumadocs-openapi/server"; import { createOpenAPI } from "fumadocs-openapi/server";
export const openapi = createOpenAPI({ export const openapi = createOpenAPI({
input: ["./openapi.json"], input: ["./public/openapi.json"],
}); });
+18 -2
View File
@@ -7,7 +7,23 @@ import {
const spec = await generateOpenApiSpec({ const spec = await generateOpenApiSpec({
title: "Sofa API", title: "Sofa API",
version: packageJson.version || "1.0.0", version: packageJson.version || "1.0.0",
servers: [{ url: "https://sofa.example.com/api/v1" }], servers: [
{
url: "{protocol}://{host}:{port}/api/v1",
variables: {
protocol: {
default: "http",
enum: ["http", "https"],
},
host: {
default: "localhost",
},
port: {
default: "3000",
},
},
},
],
sessionCookieName: "better-auth.session_token", sessionCookieName: "better-auth.session_token",
tags: [...openApiTags], tags: [...openApiTags],
}); });
@@ -55,5 +71,5 @@ for (const pathItem of Object.values(spec.paths ?? {})) {
} }
} }
await Bun.write("docs/openapi.json", JSON.stringify(spec, null, 2)); await Bun.write("docs/public/openapi.json", JSON.stringify(spec, null, 2));
console.log("OpenAPI spec written to docs/openapi.json"); console.log("OpenAPI spec written to docs/openapi.json");