Aller au contenu
Documentation en français

Traduction de la page originale en anglais. En cas de divergence, la version anglaise fait foi.

Clients typés

DaloyJS propose deux façons d’appeler votre API avec une sûreté de typage complète. Utilisez celle qui convient à votre consommateur.

1. Client typé en processus (sans génération de code)

Pour les consommateurs TypeScript du même monorepo (tests, outils internes, server actions Next.js) :

ts
import { createInProcessClient } from "@daloyjs/core/client";
import { app } from "./app.js";

const client = createInProcessClient(app);

const r = await client.getBookById({ params: { id: "1" } });
//    ^? { status: 200; body: { id: string; title: string } }
//      | { status: 404; body: ProblemJson }

if (r.status === 200) {
  console.log(r.body.title); // string, entièrement typé
}

Le client est indexé par operationId, renvoie une union discriminée de {status, body, headers} et infère tout à partir de la définition de route elle-même. Aucune étape de build.

Paramètres de chemin

Les paramètres de chemin sont substitués segment entier par segment entier : :id ne correspond donc jamais à l’intérieur de :idx, et chaque valeur est encodée en pourcentage dans son propre segment. Depuis la 1.3.7, une méthode générée lève une TypeError, avant l’envoi de toute requête, lorsqu’un paramètre est manquant, vide, . ou ... L’analyse d’URL résoudrait un segment point (même sous la forme %2E%2E) et redirigerait silencieusement l’appel, par exemple en transformant DELETE /orgs/:org/members/.. en DELETE /orgs/:org. Les routes joker (*path, ou un * seul nommé wildcard) acceptent une valeur séparée par des / ; chaque segment est encodé et vérifié de la même façon.

ts
// app.get("/files/*path", { operationId: "getFile", ... })
await client.getFile({ params: { path: "docs/guide.md" } }); // GET /files/docs/guide.md

await client.getBookById({ params: { id: ".." } });
// TypeError: Invalid path parameter "id" for /books/:id: empty and "."/".." segments are not allowed

2. SDK Hey API (multilangage, multidépôt, au build)

Pour les consommateurs situés hors du monorepo ou écrits dans d’autres langages, générez un SDK fetch entièrement typé avec @hey-api/openapi-ts.

Chaîne de génération de code
  1. 01Routesapp.route(...)
  2. 02generateOpenAPI@daloyjs/core/openapi
  3. 03openapi.jsonspécification OpenAPI 3.1 sur disque
  4. 04openapi-tsgénérateur Hey API
  5. 05SDK typésdk.gen.ts · types.gen.ts
  6. 06Consommateurappels fetch entièrement typés
pnpm gen exécute toute la chaîne : extraire la spécification de vos routes, puis laisser Hey API la transformer en SDK fetch typé. Relancez-la à chaque modification de route et le client reste en phase avec le contrat.
bash
pnpm add -D @hey-api/openapi-ts prettier
ts
// openapi-ts.config.ts
import { defineConfig } from "@hey-api/openapi-ts";

export default defineConfig({
  input: "./generated/openapi.json",
  output: { path: "./generated/client", postProcess: ["prettier"] },
  plugins: ["@hey-api/client-fetch", "@hey-api/typescript", "@hey-api/sdk"],
});
json
// package.json
"scripts": {
  "gen:openapi": "node scripts/dump-openapi.ts",
  "gen:client":  "openapi-ts",
  "gen":         "pnpm gen:openapi && pnpm gen:client"
}
bash
pnpm gen
# écrit :
#   generated/openapi.json
#   generated/client/{client.gen.ts, sdk.gen.ts, types.gen.ts, index.ts}

Utiliser le SDK généré

ts
import { client } from "./generated/client/client.gen.js";
import { getBookById } from "./generated/client/sdk.gen.js";

client.setConfig({ baseUrl: "https://api.example.com" });

const { data, error } = await getBookById({ path: { id: "1" } });
if (error) console.error(error);
else if (data) console.log(data.title);

Lequel choisir ?

Cas d’usageChoix
Appelant TypeScript dans le même dépôt (tests, outils internes)createInProcessClient
Application web / bundle mobile React Native dans un dépôt séparéSDK Hey API
Consommateur non TypeScript (Python, Swift, Kotlin)Document OpenAPI + son générateur préféré
SDK public pour des tiersSDK Hey API, publié comme paquet à part

Vous venez de ts-rest ?

ts-rest est une bibliothèque orientée contrat populaire qui fournit des types TypeScript de bout en bout sans génération de code en partageant un contrat (initContract) entre un serveur à base d’adaptateurs (Express, Fastify, NestJS, Next.js) et un client fetch (initClient). Si ce modèle vous plaît, DaloyJS vous semblera familier, à deux différences près.

D’abord, dans DaloyJS, la définition de route est le contrat : il n’y a pas d’objet de contrat séparé à garder synchronisé. Le createClient en processus présenté plus haut offre la même expérience sans génération de code, avec des types partagés, pour les appelants TypeScript du même dépôt.

Ensuite, la sûreté de typage de ts-rest est limitée à TypeScript et exige que le client importe le contrat. DaloyJS produit une spécification OpenAPI 3.1 de premier plan et un SDK Hey API à partir des mêmes routes : les consommateurs qui ne peuvent pas importer vos types (autres dépôts, autres langages, SDK publics) sont donc couverts aussi. Dans ts-rest, OpenAPI est un module complémentaire facultatif (@ts-rest/open-api). DaloyJS est aussi le serveur et le runtime lui-même, portable sur Node, Bun, Deno, Cloudflare et Vercel, plutôt qu’une couche de typage montée sur un framework séparé.

ts-restDaloyJS
Source du contratObjet initContract séparéLa définition de route elle-même
Client typé sans génération de codeOui (initClient, TypeScript uniquement)Oui (createClient, TypeScript uniquement)
Clients multilangages / multidépôtsModule OpenAPI (@ts-rest/open-api)OpenAPI 3.1 + SDK Hey API, de premier plan
ServeurAdaptateur sur Express / Fastify / NestJS / Next.jsIntégré, portable entre runtimes
Validation à l’exécutionStandard Schema (Zod / Valibot / ArkType)Standard Schema (Zod / Valibot / ArkType / TypeBox)
Sécurité par défautÀ vous de la fournirEn-têtes et limites de corps actifs par défaut ; CSRF et limitation de débit à une ligne près

Besoin d’un contrat plus volumineux pour valider la sortie de votre générateur ? Utilisez la grande démo REST factice (en anglais) comme cas de stress plutôt qu’une application de tutoriel minimale.

Dernière mise à jour :