From ce8e330c82bc0be9f299f3071a1e80daafc5f789 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Wed, 29 Apr 2026 23:29:42 +0200 Subject: [PATCH] fix(openapi): openapi document empty (#5579) Co-authored-by: Copilot --- .../src/app/[locale]/manage/tools/api/page.tsx | 2 +- .../general/_components/_first-day-of-week.tsx | 2 +- apps/nextjs/src/app/api/[...trpc]/route.ts | 5 +++-- apps/nextjs/src/app/api/openapi/route.ts | 2 +- packages/api/package.json | 3 ++- packages/api/src/index.ts | 3 +-- packages/api/src/open-api.ts | 15 +++++++++++++-- packages/validation/src/user.ts | 12 ++++-------- 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/manage/tools/api/page.tsx b/apps/nextjs/src/app/[locale]/manage/tools/api/page.tsx index e848c0fcf..f3fe3b825 100644 --- a/apps/nextjs/src/app/[locale]/manage/tools/api/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/tools/api/page.tsx @@ -2,7 +2,7 @@ import { headers } from "next/headers"; import { notFound } from "next/navigation"; import { Stack, Tabs, TabsList, TabsPanel, TabsTab } from "@mantine/core"; -import { openApiDocument } from "@homarr/api"; +import { openApiDocument } from "@homarr/api/open-api"; import { api } from "@homarr/api/server"; import { auth } from "@homarr/auth/next"; import { extractBaseUrlFromHeaders } from "@homarr/common"; diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_first-day-of-week.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_first-day-of-week.tsx index e2b1a859d..71bef0737 100644 --- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_first-day-of-week.tsx +++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_first-day-of-week.tsx @@ -30,7 +30,7 @@ export const FirstDayOfWeek = ({ user }: FirstDayOfWeekProps) => { }, onSuccess(_, variables) { form.setInitialValues({ - firstDayOfWeek: variables.firstDayOfWeek, + firstDayOfWeek: variables.firstDayOfWeek as DayOfWeek, }); showSuccessNotification({ message: t("user.action.changeFirstDayOfWeek.notification.success.message"), diff --git a/apps/nextjs/src/app/api/[...trpc]/route.ts b/apps/nextjs/src/app/api/[...trpc]/route.ts index 2980900a8..1ae1e5e92 100644 --- a/apps/nextjs/src/app/api/[...trpc]/route.ts +++ b/apps/nextjs/src/app/api/[...trpc]/route.ts @@ -2,7 +2,8 @@ import type { NextRequest } from "next/server"; import { userAgent } from "next/server"; import { createOpenApiFetchHandler } from "trpc-to-openapi"; -import { appRouter, createTRPCContext } from "@homarr/api"; +import { createTRPCContext } from "@homarr/api"; +import { openApiRouter } from "@homarr/api/open-api"; import { API_KEY_HEADER_NAME, getSessionFromApiKeyAsync } from "@homarr/auth/api-key"; import { ipAddressFromHeaders } from "@homarr/common/server"; import { createLogger } from "@homarr/core/infrastructure/logs"; @@ -30,7 +31,7 @@ const handlerAsync = async (req: NextRequest) => { return createOpenApiFetchHandler({ req, endpoint: "/", - router: appRouter, + router: openApiRouter, createContext: () => createTRPCContext({ session, headers: req.headers }), onError({ error, path, type }) { logger.error(new ErrorWithMetadata("tRPC Error occured", { path, type }, { cause: error })); diff --git a/apps/nextjs/src/app/api/openapi/route.ts b/apps/nextjs/src/app/api/openapi/route.ts index d4c514b68..26f26f9e7 100644 --- a/apps/nextjs/src/app/api/openapi/route.ts +++ b/apps/nextjs/src/app/api/openapi/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from "next/server"; -import { openApiDocument } from "@homarr/api"; +import { openApiDocument } from "@homarr/api/open-api"; import { extractBaseUrlFromHeaders } from "@homarr/common"; export function GET(request: Request) { diff --git a/packages/api/package.json b/packages/api/package.json index 04f7bae84..e90bc7278 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -9,7 +9,8 @@ "./client": "./src/client.ts", "./server": "./src/server.ts", "./websocket": "./src/websocket.ts", - "./shared": "./src/shared.ts" + "./shared": "./src/shared.ts", + "./open-api": "./src/open-api.ts" }, "main": "./index.ts", "types": "./index.ts", diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index d339d177f..1cbe6fdd7 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,6 +1,5 @@ import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server"; -import { openApiDocument } from "./open-api"; import type { AppRouter } from "./root"; import { appRouter } from "./root"; import { createCallerFactory, createTRPCContext } from "./trpc"; @@ -30,5 +29,5 @@ type RouterInputs = inferRouterInputs; **/ type RouterOutputs = inferRouterOutputs; -export { createTRPCContext, appRouter, createCaller, openApiDocument }; +export { createTRPCContext, appRouter, createCaller }; export type { AppRouter, RouterInputs, RouterOutputs }; diff --git a/packages/api/src/open-api.ts b/packages/api/src/open-api.ts index b4827871c..d789582df 100644 --- a/packages/api/src/open-api.ts +++ b/packages/api/src/open-api.ts @@ -2,10 +2,21 @@ import { generateOpenApiDocument } from "trpc-to-openapi"; import { API_KEY_HEADER_NAME } from "@homarr/auth/api-key"; -import { appRouter } from "./root"; +import { appRouter } from "./router/app"; +import { infoRouter } from "./router/info"; +import { inviteRouter } from "./router/invite"; +import { userRouter } from "./router/user"; +import { createTRPCRouter } from "./trpc"; + +export const openApiRouter = createTRPCRouter({ + appRouter, + infoRouter, + inviteRouter, + userRouter, +}); export const openApiDocument = (base: string) => - generateOpenApiDocument(appRouter, { + generateOpenApiDocument(openApiRouter, { title: "Homarr API documentation", version: "1.0.0", baseUrl: base, diff --git a/packages/validation/src/user.ts b/packages/validation/src/user.ts index 6baaf8150..4d5bd1e77 100644 --- a/packages/validation/src/user.ts +++ b/packages/validation/src/user.ts @@ -138,14 +138,10 @@ export const userChangeColorSchemeSchema = z.object({ export const userFirstDayOfWeekSchema = z.object({ firstDayOfWeek: z - .custom((value) => z.number().min(0).max(6).safeParse(value).success) - .meta({ - override: { - type: "integer", - minimum: 0, - maximum: 6, - }, - }), + .number() + .min(0) + .max(6) + .transform((value) => value as DayOfWeek), }); export const userPingIconsEnabledSchema = z.object({