unserved
Framework serveur TypeScript autour de H3, TypeORM et WebSocket: routes typées, parsers explicites, client inféré.
Le contrat est dans le nom de route
J'ai construit unserved autour d'un pari: une API TypeScript reste plus maintenable quand le contrat est explicite au même endroit que le handler.
Une route déclare son nom, puis ses parsers: body, query, formData, paramètres. Le handler reçoit un contexte typé avec event , données parsées et AbortSignal . Le serveur ne devine pas le contrat depuis un fichier séparé ; il l'exécute.
createHttpRoute({ name: "GET /users/:id", parseParameters: parameters => ({ id: asNumber(parameters.id) }),}, ({ parameters }) => { return getUser(parameters.id)})Modules, routes, repositories
J'ai organisé le serveur autour de modules. Chaque module peut déclarer ses routes, entities TypeORM, erreurs et dépendances. L'application initialise la DataSource , injecte les repositories et enregistre les routes dans H3. Les routes WebSocket passent par crossws .
Cette structure retire une partie du bricolage habituel dans les petits serveurs TypeScript: où vit la route, où est le repository, qui initialise la database, comment retrouver un autre module. Les choix sont répétitifs, donc ils deviennent des conventions.
module -> route parser -> H3 handler -> TypeORM repository -> typed clientLe client suit le serveur
Le package client expose createClient<T>() . Avec le type d'application, request("GET /api/user/:id", ...) infère les routes disponibles et les données attendues. Le package Nuxt ajoute un useClient() global basé sur l'URL courante.
Ce n'est pas un framework pour maximiser la liberté locale. C'est un framework pour éviter le drift entre handler, client, tests et usage frontend.
Ce que la contrainte achète
unserved montre un autre mode de travail: prendre une douleur de backend TypeScript, réduire les chemins possibles et accepter une convention forte quand elle enlève de la maintenance.
- Les parsers rendent les frontières d'entrée visibles.
- Les modules donnent un endroit clair aux entities, repositories et routes.
- Le client typé réduit les divergences entre API et frontend.
- Les tests autour des handlers, WebSocket, abort signals et transformers gardent le framework vérifiable.