Fetcher
Client HTTP typé avec gestion d'erreurs unifiée. Wrapper autour de fetch qui parse le JSON automatiquement et lève une ApiErrorstructurée en cas d'échec.
Appel GET typé. Le résultat est parsé en JSON automatiquement et retourné avec le type fourni.
import { fetcher } from "@ramses1er/cbk-toolkit/client";
type User = { id: string; name: string; email: string };
function getUsers(): Promise<User[]> {
return fetcher<User[]>("/api/users", { method: "GET" });
}Pour les mutations, passer le body sous forme de chaîne JSON. Le Content-Type est déjà défini par défaut.
import { fetcher } from "@ramses1er/cbk-toolkit/client";
type CreateUserPayload = {
fullname: string;
email: string;
roleId: string;
};
function createUser(payload: CreateUserPayload): Promise<{ success: true }> {
return fetcher<{ success: true }>("/api/users", {
method: "POST",
body: JSON.stringify(payload),
});
}
function updateUser(payload: UpdateUserPayload): Promise<{ success: true }> {
return fetcher<{ success: true }>("/api/users", {
method: "PATCH",
body: JSON.stringify(payload),
});
}
function deleteUser(id: string): Promise<{ success: true }> {
return fetcher<{ success: true }>("/api/users", {
method: "DELETE",
body: JSON.stringify({ id }),
});
}Si la réponse HTTP n’est pas un succès (status ≥ 400), le fetcher lève une ApiError avec les informations structurées du backend.
import { ApiError } from "@ramses1er/cbk-toolkit/client";
try {
const users = await fetcher<User[]>("/api/users");
} catch (error) {
if (error instanceof ApiError) {
console.log(error.message); // "Email déjà utilisé"
console.log(error.status); // 409
console.log(error.code); // "EMAIL_DUPLICATE"
console.log(error.data); // réponse brute
}
}message— message d’erreur (français par défaut)status— code HTTP (400, 404, 409, 500...)code— code métier optionnel (ex:EMAIL_DUPLICATE)data— corps complet de la réponse brute
Le pattern standard : une fonction API qui appelle fetcher, wrappée dans un hook React Query. Le hook expose .data, .error, .isPending directement au composant.
// api/get-users.ts — appelle le fetcher
import { fetcher } from "@ramses1er/cbk-toolkit/client";
export function getUsers(): Promise<User[]> {
return fetcher<User[]>("/api/users", { method: "GET" });
}// hooks/use-get-users.ts — React Query
import { useQuery } from "@tanstack/react-query";
import { ApiError } from "@ramses1er/cbk-toolkit/client";
import { getUsers } from "../api/get-users";
export function useGetUsers() {
return useQuery<User[], ApiError>({
queryFn: getUsers,
queryKey: ["users"],
});
}// Mutation avec invalidation du cache
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { ApiError } from "@ramses1er/cbk-toolkit/client";
import { createUser } from "../api/create-user";
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation<{ success: true }, ApiError, CreateUserPayload>({
mutationFn: createUser,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
}FetcherOptions étend RequestInit (headers, signal AbortController, etc.) avec une option supplémentaire :
import { fetcher } from "@ramses1er/cbk-toolkit/client";
// Désactiver le parsing JSON automatique
const blob = await fetcher<Blob>("/api/export", {
method: "GET",
skipJsonParsing: true,
});
// Passer des headers personnalisés
const data = await fetcher("/api/data", {
method: "POST",
body: JSON.stringify(payload),
headers: {
"X-Custom": "valeur",
},
});
// Annuler la requête avec AbortController
const controller = new AbortController();
const data = await fetcher("/api/data", {
signal: controller.signal,
});| Propriété | Type | Défaut | Description |
|---|---|---|---|
fetcher<T>(url, options?) | |||
| url | string | requis | URL de l’API |
| options | FetcherOptions | {} | Options de la requête |
FetcherOptions (étend RequestInit) | |||
| method | string | GET | Méthode HTTP |
| body | BodyInit | — | Corps de la requête (passer JSON.stringify) |
| headers | HeadersInit | { "Content-Type": "application/json" } | Headers supplémentaires (fusion) |
| skipJsonParsing | boolean | false | Désactive le parsing JSON automatique |
| signal | AbortSignal | — | Signal AbortController pour annulation |
ApiError (étend Error) | |||
| message | string | requis | Message d’erreur |
| status | number | requis | Code HTTP (400, 404, 409, etc.) |
| code | string | undefined | — | Code erreur métier optionnel |
| data | unknown | — | Corps brut de la réponse |
credentials: "include"— envoie les cookies automatiquement (auth)Content-Type: application/json— header par défaut (fusionnable)- Parsing JSON automatique si le
content-typeestapplication/json ApiError.messagepar défaut :"Une erreur est survenue"(français)