Some checks failed
CI / build-lint-test (pull_request) Failing after 29s
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>
43 lines
4 KiB
Markdown
43 lines
4 KiB
Markdown
# Architecture
|
|
|
|
## Objectif
|
|
|
|
`lightweight-sdk` est un monorepo pnpm destiné à héberger, au fil du temps, des packages TypeScript réutilisables développés par l'auteur pour ses projets personnels. Chaque package est publié indépendamment sur le registre npm privé hébergé sur l'instance Forgejo personnelle (`git.dev.kyuno.fr`), sous le scope `@lightweight-sdk`.
|
|
|
|
## Organisation des packages
|
|
|
|
Les packages sont répartis en trois catégories sous `packages/`, qui reflètent la distinction Frontend/Backend du [CLAUDE.md](../CLAUDE.md) du projet :
|
|
|
|
- **`client/`** — packages destinés au navigateur (DOM, composants UI). Peuvent dépendre de `lib: DOM` dans leur `tsconfig.json`.
|
|
- **`common/`** — code isomorphe partagé entre `client` et `server` (types, utilitaires purs, constantes). Convention : ne doit dépendre d'aucune API exclusivement DOM ou exclusivement Node, pour rester portable des deux côtés.
|
|
- **`server/`** — packages Node/backend. Chaque package doit être structuré comme un service modulaire autonome exposant sa propre API (règle "Architecture Backend" du CLAUDE.md).
|
|
|
|
Le nom npm d'un package ne reprend pas le préfixe de catégorie (`@lightweight-sdk/web-component`, pas `@lightweight-sdk/client-web-component`) — la catégorie est une convention d'organisation du dépôt, pas une convention de nommage public.
|
|
|
|
Un nouveau package se crée avec `pnpm create-package <client|common|server> <nom>` (voir `scripts/create-package.mjs`).
|
|
|
|
## Choix d'outillage
|
|
|
|
| Aspect | Choix | Pourquoi |
|
|
|---|---|---|
|
|
| Gestionnaire de packages | pnpm workspaces + `catalog:` | Centralise les versions des devDependencies partagées dans `pnpm-workspace.yaml` |
|
|
| Orchestrateur de build | Aucun (pas de Turborepo/Nx) | Un seul package réel au démarrage ; à reconsidérer si le temps de build devient un problème |
|
|
| Build | `tsc -b` (project references), pas de bundler | Les packages sont consommés via pnpm par d'autres projets Node/TS de l'auteur ; pas besoin de bundle |
|
|
| Modules | **CommonJS**, résolution `Node10` | Décision explicite : pas d'extension `.js` requise dans les imports relatifs, et le code migré depuis l'ancien repo `web-component` compile sans modification |
|
|
| Lint + format | [Biome.js](https://biomejs.dev/) | Imposé par le CLAUDE.md du projet |
|
|
| Documentation de code | [TypeDoc](https://typedoc.org/) en mode validation | Génère la doc API et fait échouer la CI si un export n'a pas de TSDoc (voir `conventions.md`) |
|
|
| Tests | [Vitest](https://vitest.dev/) | ESM natif, bon support monorepo |
|
|
| Versioning/publish | [Changesets](https://github.com/changesets/changesets) | Gère des versions indépendantes par package + changelogs, comprend nativement `workspace:*` |
|
|
| Node cible | 24 (Active LTS) en CI, `engines: ">=22"` | Node 20 est end-of-life depuis avril 2026 |
|
|
|
|
## Décorateurs et `useDefineForClassFields`
|
|
|
|
`tsconfig.base.json` force `"useDefineForClassFields": false`, bien que la cible soit `ES2022` (où ce flag vaut `true` par défaut). Sans ça, un champ de classe déclaré sans initialiseur (`logger!: LoggerService;`) est réinitialisé à `undefined` **sur l'instance** au moment de la construction, ce qui masque silencieusement tout accesseur posé sur le prototype par un décorateur de propriété (`@Service` de `@lightweight-sdk/service-registry`, `@LinkToDom` de `web-component`). C'est une interaction connue entre `useDefineForClassFields` et les décorateurs legacy (`experimentalDecorators`) — désactiver ce flag restaure la sémantique classique où un champ sans initialiseur n'émet aucun code, laissant l'accesseur du prototype pleinement fonctionner.
|
|
|
|
## Dépendances entre packages
|
|
|
|
Les dépendances internes entre packages du monorepo utilisent le protocole `workspace:*` (résolu localement par pnpm, jamais via le registre distant). Le registre npm privé n'est utilisé que pour la publication et pour la consommation depuis des projets *externes* à ce monorepo.
|
|
|
|
## Registre npm privé
|
|
|
|
`https://git.dev.kyuno.fr/api/packages/kyuno/npm/` — voir `ci-cd.md` pour le détail de la publication et de l'authentification.
|