# @lightweight-sdk/service-registry Registre de services en singleton, avec enregistrement par décorateur et résolution directe. Package `common` : isomorphe, aucune dépendance DOM ou Node-only. ## Installation ```bash pnpm add @lightweight-sdk/service-registry ``` ## Usage ```ts import { RegisterService, Service, services } from '@lightweight-sdk/service-registry'; export const LOGGER_UID = 'logger'; @RegisterService(LOGGER_UID) class LoggerService { public log(message: string): void { console.log(message); } } // Injection déclarative sur une propriété class ReportGenerator { @Service(LOGGER_UID) private readonly logger!: LoggerService; public run(): void { this.logger.log('generating report'); } } // Résolution directe, n'importe où const logger = services.get(LOGGER_UID); logger.log('hello'); ``` ## Concepts - **`services`** — constante globale, instance prête à l'emploi du `ServiceRepository`. C'est le point d'entrée à utiliser partout : `services.get(uid)`, `services.has(uid)`, `services.register(uid, MaClasse)`. - **`ServiceRepository`** — la classe singleton derrière `services` (accès direct rarement nécessaire, exportée pour le typage et les tests). - **`@RegisterService(uid)`** — décorateur de classe. Instancie la classe décorée (constructeur sans argument obligatoire) et l'enregistre sous `uid`. **C'est au développeur de choisir `uid` et de garantir son unicité** — la registry refuse tout doublon. - **`@Service(uid)`** — décorateur de propriété. Injecte l'instance enregistrée sous `uid` dans le membre décoré. Pas de typage générique sur le décorateur : un décorateur de propriété ne peut pas changer le type du champ qu'il décore, donc c'est l'annotation du champ (`private readonly logger!: LoggerService;`) qui le type, comme d'habitude. La résolution est **paresseuse** (au premier accès à la propriété, pas à la décoration) : peu importe que la classe consommatrice soit évaluée avant ou après l'enregistrement du service. Après le premier accès, la propriété est remplacée par la valeur résolue (pas de nouvelle recherche ensuite). ## Contraintes - Une classe décorée par `@RegisterService(uid)` doit avoir un constructeur sans argument obligatoire — ses propres dépendances doivent elles-mêmes être injectées via `@Service` ou `services.get`, pas passées au constructeur. - `uid` doit être unique dans toute l'application — exporter une constante partagée (comme `LOGGER_UID` ci-dessus) entre le point d'enregistrement et les points d'injection évite les fautes de frappe. - `experimentalDecorators: true` doit être activé côté consommateur (déjà le cas dans ce monorepo via `tsconfig.base.json`). ## API - `services` — instance singleton prête à l'emploi (`get(uid)`, `has(uid)`, `register(uid, target)`). - `RegisterService(uid)` — décorateur de classe. - `Service(uid)` — décorateur de propriété. - `ServiceRepository` — la classe singleton (`getInstance()`, `register(uid, target)`, `get(uid)`, `has(uid)`). `resetForTesting()` est réservé aux tests. - `ServiceConstructor`, `ServiceUid` — types associés.