Next.js Supabase V3 (#463)

Version 3 of the kit:
- Radix UI replaced with Base UI (using the Shadcn UI patterns)
- next-intl replaces react-i18next
- enhanceAction deprecated; usage moved to next-safe-action
- main layout now wrapped with [locale] path segment
- Teams only mode
- Layout updates
- Zod v4
- Next.js 16.2
- Typescript 6
- All other dependencies updated
- Removed deprecated Edge CSRF
- Dynamic Github Action runner
This commit is contained in:
Giancarlo Buomprisco
2026-03-24 13:40:38 +08:00
committed by GitHub
parent 4912e402a3
commit 7ebff31475
840 changed files with 71395 additions and 20095 deletions

View File

@@ -1,5 +1,4 @@
import 'server-only';
import { redirect } from 'next/navigation';
import { ZodType, z } from 'zod';
@@ -12,6 +11,7 @@ import { JWTUserData } from '@kit/supabase/types';
/**
* @name enhanceAction
* @description Enhance an action with captcha, schema and auth checks
* @deprecated Use [authActionClient](safe-action-client.ts) instead
*/
export function enhanceAction<
Args,
@@ -20,19 +20,22 @@ export function enhanceAction<
auth?: boolean;
captcha?: boolean;
schema?: z.ZodType<
Config['captcha'] extends true ? Args & { captchaToken: string } : Args,
z.ZodTypeDef
Config['captcha'] extends true ? Args & { captchaToken: string } : Args
>;
},
>(
fn: (
params: Config['schema'] extends ZodType ? z.infer<Config['schema']> : Args,
params: Config['schema'] extends ZodType
? z.output<Config['schema']>
: Args,
user: Config['auth'] extends false ? undefined : JWTUserData,
) => Response | Promise<Response>,
config: Config,
) {
return async (
params: Config['schema'] extends ZodType ? z.infer<Config['schema']> : Args,
params: Config['schema'] extends ZodType
? z.output<Config['schema']>
: Args,
) => {
type UserParam = Config['auth'] extends false ? undefined : JWTUserData;
@@ -80,6 +83,11 @@ export function enhanceAction<
user = auth.data as UserParam;
}
return fn(data, user);
return fn(
data as Config['schema'] extends ZodType
? z.output<Config['schema']>
: Args,
user,
);
};
}

View File

@@ -0,0 +1,55 @@
import 'server-only';
import { redirect } from 'next/navigation';
import { createSafeActionClient } from 'next-safe-action';
import { verifyCaptchaToken } from '@kit/auth/captcha/server';
import { requireUser } from '@kit/supabase/require-user';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
const baseClient = createSafeActionClient({
handleServerError: (error) => error.message,
});
/**
* @name publicActionClient
* @description Safe action client for public actions that don't require authentication.
*/
export const publicActionClient = baseClient;
/**
* @name authActionClient
* @description Safe action client for authenticated actions. Adds user context.
*/
export const authActionClient = baseClient.use(async ({ next }) => {
const auth = await requireUser(getSupabaseServerClient());
if (!auth.data) {
redirect(auth.redirectTo);
}
return next({ ctx: { user: auth.data } });
});
/**
* @name captchaActionClient
* @description Safe action client for actions that require CAPTCHA and authentication.
*/
export const captchaActionClient = baseClient.use(
async ({ next, clientInput }) => {
const input = clientInput as Record<string, unknown>;
const token =
typeof input?.captchaToken === 'string' ? input.captchaToken : '';
await verifyCaptchaToken(token);
const auth = await requireUser(getSupabaseServerClient());
if (!auth.data) {
redirect(auth.redirectTo);
}
return next({ ctx: { user: auth.data } });
},
);

View File

@@ -1,9 +1,8 @@
import 'server-only';
import { redirect } from 'next/navigation';
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import * as z from 'zod';
import { verifyCaptchaToken } from '@kit/auth/captcha/server';
import { requireUser } from '@kit/supabase/require-user';
@@ -22,7 +21,7 @@ interface HandlerParams<
> {
request: NextRequest;
user: RequireAuth extends false ? undefined : JWTUserData;
body: Schema extends z.ZodType ? z.infer<Schema> : undefined;
body: Schema extends z.ZodType ? z.output<Schema> : undefined;
params: Record<string, string>;
}
@@ -48,7 +47,7 @@ interface HandlerParams<
*/
export const enhanceRouteHandler = <
Body,
Params extends Config<z.ZodType<Body, z.ZodTypeDef>>,
Params extends Config<z.ZodType<Body>>,
>(
// Route handler function
handler: