Agregateur d'API reverse-proxy avec enregistrement et decouverte de
services au runtime, deux points d'entree separes partageant un meme
protocole :
- ./client (DiscoveryClient) : enregistre un service et maintient un
heartbeat periodique (qui sert aussi de mecanisme de retry - un echec
est journalise et laisse au tick suivant, pas de logique separee).
stop() est best-effort et ne rejette jamais.
- ./aggregator (ServiceAggregator) : handlers Node natifs a monter dans
Express/Fastify/http brut (exemples des trois dans le README), zero
dependance framework. Routage par prefixe de nom de service, TTL avec
balayage periodique, secret partage compare en temps constant, proxy
HTTP fait main (node:http/https, streaming, filtrage hop-by-hop,
distinction 502/504).
Limites documentees dans le README plutot que corrigees : pas de
matching :param (v1, match exact), pas de secret par service, risque
SSRF-like assume vu le threat model homelab.
Resolution des sous-chemins via des stubs package.json (client/,
aggregator/) puisque le repo cible moduleResolution: Node10, pas de
champ exports moderne - pattern documente dans spec/architecture.md
pour de futurs packages server/ multi-points d'entree.
Bug trouve et corrige en cours de route : req.on('close') se declenche
des que le corps de la requete entrante est lu (immediat pour un GET
sans body), pas a la deconnexion reelle du client - detruisait ma
propre requete sortante juste apres l'avoir envoyee. Le bon signal est
res.on('close').
Correction connexe : create-package.mjs inserait la nouvelle ligne en
fin de fichier de spec/packages.md au lieu de l'inserer dans le
tableau - corrige pour les deux packages precedents au passage.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pnpm 12.4.2 n'ecrivait pas d'entree importers pour
packages/common/service-registry dans le lockfile, meme apres
suppression complete du lockfile et du cache d'etat pnpm puis
reinstallation (pnpm ls -r reconnaissait pourtant bien le package).
CI echouait avec --frozen-lockfile (erreur has no importers[...] entry),
alors que le pnpm install local sans --frozen-lockfile ne se
plaignait de rien.
Cause probable : ce package ne declarait aucune dependency ni
devDependency propre. Remede : declarer explicitement quelques
devDependencies (typescript, vitest, @types/node via catalog:), meme
deja hoistees depuis la racine. create-package.mjs generera desormais
ces devDependencies par defaut pour tout nouveau package, et le
troubleshooting est documente dans spec/ci-cd.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Registre de services en singleton avec injection par decorateurs :
- ServiceRepository : singleton central, uid genere automatiquement
(crypto.randomUUID) a l'enregistrement, une seule instance partagee
par service.
- @RegisterService() : decorateur de classe, instancie et enregistre
automatiquement la classe decoree (constructeur sans argument).
- @Service(target) : decorateur de propriete, injection paresseuse et
memoisee par reference de classe (resolution au premier acces, pas
a la decoration - insensible a l'ordre d'evaluation des modules).
Fix connexe dans tsconfig.base.json : useDefineForClassFields desactive
(target ES2022 l'active par defaut), sinon un champ de classe sans
initialiseur est reinitialise a undefined sur l'instance a la
construction et masque l'accesseur pose sur le prototype par un
decorateur de propriete - touche @Service ici et @LinkToDom dans
web-component. Documente dans spec/architecture.md.
Fix connexe dans scripts/create-package.mjs : execFileSync('pnpm', ...)
ne resout pas le shim .cmd de pnpm sous Windows sans shell: true
(trouve en re-testant le script sur ce package).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le trigger push sur les branches non-main faisait tourner ci.yml deux
fois sur le meme commit des qu'une PR est ouverte (une fois pour le
push, une fois pour la pull_request) : deux statuts distincts pour un
seul resultat logique, et une exposition doublee aux flakys du runner
(observe : Setup pnpm a echoue une fois avec l'erreur text file busy,
une race condition transitoire juste apres l'installation de Node par
le runner - le run pull_request sur le meme commit avait reussi).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Outillage complet : pnpm workspaces (catalog), Biome, TypeScript
(project references, CommonJS/Node10), Vitest, TypeDoc (validation
bloquante en CI), Changesets.
- Organisation des packages en catégories client/common/server.
- Migration de @lightweight-sdk/web-component (packages/client/) depuis
l'ancien repo lightweight-sdk-web-component : code source copié à
l'identique, aucune modification. package.json/tsconfig.json/README.md
adaptés autour. Exclu de la validation TypeDoc stricte et de quelques
règles Biome (formatage, noShadowRestrictedNames) puisque le code ne
peut pas être édité pour s'y conformer - détails dans spec/packages.md.
- Workflows Forgejo Actions (.forgejo/workflows/) : ci.yml (lint, build,
test, docs:check) et release.yml (publication sur le registre npm
privé via Changesets).
- Script pnpm create-package <client|common|server> <nom> pour scaffolder
les futurs packages.
- Documentation dans /spec (architecture, conventions, ci-cd, packages).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>