Files
supabase/apps/studio/start.ts
T
Alaister Young 64b809ffbf feat(studio): add self-hosted-only API 404 guard for the TanStack build
The Next pages-router build guards platform-only API routes via middleware
(proxy.ts, Next 16's renamed middleware convention). TanStack Start has no
middleware runtime, so that guard didn't run on the TanStack build at all.

Add an equivalent global request middleware on a TanStack start instance
(start.ts). On Vercel, /api/* and /_serverFn/* are rewritten to the
api/server.js function which runs createStartHandler, so requestMiddleware
executes server-side for every API request even though pages are a static
SPA shell. Extract the shared HOSTED_SUPPORTED_API_URLS allowlist into
lib/hosted-api-allowlist.ts so the Next and TanStack guards can't drift while
both frameworks run in parallel.
2026-06-19 11:47:48 +08:00

36 lines
1.5 KiB
TypeScript

import { createMiddleware, createStart } from '@tanstack/react-start'
import { BASE_PATH, IS_PLATFORM } from '@/lib/constants'
import { isHostedSupportedApiPath } from '@/lib/hosted-api-allowlist'
// Self-hosted-only API routes must 404 in platform (hosted) mode. Under the
// Next pages router this lives in middleware (proxy.ts), but TanStack Start
// has no middleware runtime, so the guard is migrated here as a global
// request middleware sharing the same allowlist (lib/hosted-api-allowlist.ts).
// On Vercel our `/api/*` (and `/_serverFn/*`) requests are rewritten to the
// api/server.js function which runs the Start handler, so createStartHandler
// runs this server-side for every API request — even though pages are served
// as a static SPA shell. The guard therefore covers all API routes from a
// single place.
const platformApiGuard = createMiddleware({ type: 'request' }).server(({ request, next }) => {
const { pathname } = new URL(request.url)
// Path relative to the configured basePath — mirrors Next's basePath-
// relative middleware matcher.
const relativePath =
BASE_PATH && pathname.startsWith(BASE_PATH) ? pathname.slice(BASE_PATH.length) : pathname
if (IS_PLATFORM && relativePath.startsWith('/api/') && !isHostedSupportedApiPath(relativePath)) {
return Response.json(
{ success: false, message: 'Endpoint not supported on hosted' },
{ status: 404 }
)
}
return next()
})
export const startInstance = createStart(() => ({
requestMiddleware: [platformApiGuard],
}))