Move inviteRequestSchema out of route.ts to satisfy Next 15 build

Next.js 15 enforces a strict allowlist of named exports from route.ts
files; "inviteRequestSchema" was rejected by the route-validator with
"is not a valid Route export field" during npm run build. Splitting the
schema into a sibling module (which is exempt from the allowlist) and
importing it from route.ts and the test. Renames the test file to
match its target module.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-28 11:29:54 +00:00
parent f26156ddb5
commit 7ced6c0818
3 changed files with 12 additions and 8 deletions

View file

@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { inviteRequestSchema } from "./route";
import { inviteRequestSchema } from "./inviteRequestSchema";
describe("inviteRequestSchema", () => {
it("accepts an invite request with just email and role (no name)", () => {

View file

@ -0,0 +1,10 @@
import { z } from "zod";
import { ROLE_OPTIONS } from "@/app/portfolio/[slug]/(portfolio)/settings/roles";
// Body schema for POST /api/portfolio/[portfolioId]/collaborators. Lives in
// its own file because Next.js 15 rejects non-handler named exports from
// route.ts. See route.test.ts for the contract tests.
export const inviteRequestSchema = z.object({
email: z.string().email(),
role: z.enum(ROLE_OPTIONS),
});

View file

@ -29,6 +29,7 @@ import {
denyIfNotAdmin,
resolvePortfolioPrivilege,
} from "@/app/lib/resolvePortfolioPrivilege";
import { inviteRequestSchema } from "./inviteRequestSchema";
// Get collaborators (users) that have access to the portfolio, plus the
// effective privilege of the requesting user (so the UI knows which actions
@ -192,13 +193,6 @@ export async function PUT(
}
}
// Body schema for the invite endpoint. Exported so the contract can be
// unit-tested directly — see route.test.ts.
export const inviteRequestSchema = z.object({
email: z.string().email(),
role: z.enum(ROLE_OPTIONS),
});
// POST: invite a user by email.
//
// Unified flow: in nearly every case we write a pending portfolio_invitations