Système de Corps & Parsing
Unireq fournit un système composable pour gérer les corps de requête et le parsing des réponses.
Sérialiseurs de corps (body.*)
body.* sérialise la charge utile et pose Content-Type automatiquement. Combinez-les avec vos validateurs pour garantir un payload conforme avant de partir sur le réseau.
typescript
import { body } from '@unireq/http';
body.json({ email: 'jane@example.com' });
body.text('plain text', 'text/plain; charset=utf-8');
body.form({ q: 'unireq', page: 2 });
body.binary(fileBuffer, 'application/pdf');
body.multipart(
{ name: 'file', part: body.binary(fileBuffer, 'application/pdf'), filename: 'quote.pdf' },
{ name: 'meta', part: body.json({ customerId: 42 }) },
);Parseurs de réponse (parse.*)
Installez un parser par requête (ou globalement) pour négocier le format reçu.
typescript
import { parse } from '@unireq/http';
parse.json();
parse.text();
parse.blob();
parse.stream();
parse.raw();- Chaque parser pose
Acceptautomatiquement et alimente les policies suivantes (validate, métriques, etc.). parse.stream()expose unReadableStream, tandis queparse.raw()laisse le corps intouché.
Marshalling côté requêtes ("produce")
Valibot/Zod peuvent valider les entrées avant la sérialisation. Il suffit d'envelopper v.parse dans un petit helper pour « produire » le corps final.
typescript
import * as v from 'valibot';
import { body } from '@unireq/http';
const CreateUserInput = v.object({
email: v.pipe(v.string(), v.email()),
name: v.string(),
marketingOptIn: v.optional(v.boolean(), false),
});
const produceJson = <TSchema extends v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>>(schema: TSchema) =>
(input: v.Input<TSchema>) => body.json(v.parse(schema, input));
await api.post('/users', produceJson(CreateUserInput)({ email: 'jane@example.com', name: 'Jane' }));- Il n'existe pas de
v.producenatif :v.parserenvoie déjà la forme canonique du schéma, il suffit donc de l'entourer pour générer unbody.jsoncohérent. - Profitez-en pour normaliser (arrondis, slugs, dates ISO) juste avant la sérialisation.
Unmarshalling côté réponses
Chaînez validate() après parse.* pour garantir que les réponses correspondent à votre contrat.
typescript
import { client, validate } from '@unireq/core';
import { http, parse } from '@unireq/http';
import { valibotAdapter } from '../../examples/validation-adapters.js';
import * as v from 'valibot';
const UserResponse = v.object({
id: v.number(),
email: v.pipe(v.string(), v.email()),
name: v.string(),
});
const api = client(
http('https://jsonplaceholder.typicode.com'),
parse.json(),
validate(UserResponse, valibotAdapter()),
);
const user = await api.get('/users/1');validate()reçoit déjà le corps parsé ; retournez ce que vous voulez (objet, classe) etresponse.dataprendra cette valeur.- Changez de librairie en remplaçant l'adaptateur (
Zod,ArkType, etc.).
Aller-retour complet
typescript
const CreateUserOutput = v.object({
id: v.number(),
createdAt: v.string(),
});
const api = client(
http('https://api.example.com'),
parse.json(),
validate(CreateUserOutput, valibotAdapter()),
);
export async function createUser(input: v.Input<typeof CreateUserInput>) {
return api.post('/users', produceJson(CreateUserInput)(input));
}- La couche externe (« produce ») garantit un payload propre ; la couche interne (« parse ») sécurise la réponse.
- Pour les flux (NDJSON/SSE), combinez
parse.stream()avec une policy maison qui valide chaque événement à la volée.