Server Actions
Patrimo utilise Server Actions comme API principale, et non REST. Les deux endpoints REST existants sont /api/auth/* (NextAuth) et /api/health.
Pourquoi pas REST
- Couplage naturel avec Next.js App Router : une Server Action est appelée directement depuis un composant React sans duplication de types (Zod côté serveur + fetch typé côté client).
- Revalidation automatique :
revalidatePath()invalide le cache RSC en retour d'action, sans client state manager. - Sécurité par défaut : les actions ne sont pas exposées sur des URLs publiques ; chaque appel embarque un token anti-CSRF géré par Next.js.
- Mono-utilisateur : pas besoin d'API versionnée pour un intranet personnel.
Voir la décision complète dans l'intro API.
Localisation
src/app/actions/
├── accounts.ts
├── analytics.ts
├── budget.ts
├── dashboard.ts
├── import.ts
├── settings.ts
└── users.ts
Chaque fichier commence par la directive :
'use server';
Convention d'une action
'use server';
import { z } from 'zod';
import { auth } from '@/lib/auth';
import { prisma } from '@/lib/db';
import { revalidatePath } from 'next/cache';
const CreateAccountSchema = z.object({
name: z.string().min(1),
type: z.enum(['CHECKING', 'SAVINGS', /* … */]),
currency: z.string().length(3),
});
/**
* Crée un compte pour l'utilisateur connecté.
*
* @auth requise
* @returns Le compte créé
* @throws UNAUTHORIZED si la session est absente
* @throws VALIDATION_ERROR si le payload est invalide
*/
export async function createAccount(input: z.infer<typeof CreateAccountSchema>) {
// 1. Auth guard
const session = await auth();
if (!session?.user) throw new Error('UNAUTHORIZED');
// 2. Validation Zod
const data = CreateAccountSchema.parse(input);
// 3. Mutation Prisma
const account = await prisma.account.create({ data });
// 4. Revalidation RSC
revalidatePath('/accounts');
return account;
}
Règles
- Auth guard en premier :
await auth()avant toute lecture/écriture - Ownership check : pour les entités utilisateur, vérifier que
entity.userId === session.user.id(même si mono-user aujourd'hui, pour survivre à une future migration multi-user) - Validation Zod sur tous les inputs — pas de
any - JSDoc obligatoire : description,
@auth,@returns,@throws. Le scriptdocs:generate-apien extrait les signatures. - Revalidation explicite via
revalidatePath()ourevalidateTag()après mutation - Erreurs typées : lever des erreurs métier (
UNAUTHORIZED,NOT_FOUND,VALIDATION_ERROR,CONFLICT) — voir catalogue d'erreurs
Génération automatique de la doc
Le script npm run docs:generate-api extrait les signatures (via ts-morph) dans docs-site/docs/api/server-actions/_generated/<module>.mdx. Les pages manuelles (accounts.md, transactions.md, etc.) importent ces snippets et ajoutent pré-conditions, exemples et erreurs métier à la main.
Ne jamais éditer _generated/*.mdx manuellement — régénérer.