Développement/Routes d’API

Routes d’API

Handlers d’API typés avec TanStack Start et gestion des erreurs.

Les routes d’API utilisent les handlers serveur de TanStack Router et handleApiError. Authentifiez la requête directement dans le handler, puis appelez Convex avec les helpers typés pour accéder aux données.

Modèle de route d’API

import { handleApiError } from "@/lib/api-middleware";
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/api/example")({
  server: {
    handlers: {
      GET: async ({ request }) => {
        try {
          return Response.json({ success: true });
        } catch (e) {
          return handleApiError(e);
        }
      },
    },
  },
});

Authentification

import { handleApiError } from "@/lib/api-middleware";
import { getRequiredUser } from "@/lib/auth/auth-user";
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/api/protected")({
  server: {
    handlers: {
      GET: async () => {
        try {
          const user = await getRequiredUser();
          return Response.json({ userId: user.id });
        } catch (e) {
          return handleApiError(e);
        }
      },
    },
  },
});

Appels Convex

import { handleApiError } from "@/lib/api-middleware";
import { getRequiredUser, isAdmin } from "@/lib/auth/auth-user";
import { fetchAuthQuery } from "@/lib/auth-server";
import { HttpError } from "@/lib/errors/http-error";
import { api } from "@convex/_generated/api";
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/api/admin/users")({
  server: {
    handlers: {
      GET: async () => {
        try {
          const user = await getRequiredUser();
          if (!isAdmin(user)) throw new HttpError("Accès refusé", 403);

          const users = await fetchAuthQuery(api.admin.queries.listUsers, {
            page: 1,
            pageSize: 20,
          });
          return Response.json(users);
        } catch (e) {
          return handleApiError(e);
        }
      },
    },
  },
});

Gestion des erreurs

Type d’erreurStatutComportement
HttpErrorPersonnaliséRenvoie le message avec le statut indiqué
ApplicationError400Renvoie le message d’erreur
ZodError422Renvoie le détail de validation
Erreur inconnue (dev)500Renvoie le message complet
Erreur inconnue (prod)500Renvoie « Erreur interne du serveur »
import { HttpError } from "@/lib/errors/http-error";
import { ApplicationError } from "@/lib/errors/application-error";

throw new HttpError("Ressource introuvable", 404);
throw new HttpError("Accès refusé", 403);
throw new ApplicationError("Opération non valide");