Collectors
Un collector résout un paramètre de handler par son type à partir du contexte d'invocation. Les opérations qui déclarent ce paramètre reçoivent la valeur automatiquement.
import { Collector } from '@fougere/core';
import type { InvocationContext } from '@fougere/core';
import User from '../../user/entities/User.js';
/**
* Le middleware auth pose l'user de session sur ctx.state.user —
* ceci le fait remonter à tout handler qui déclare `user: User | null`.
*/
export default class CurrentUserCollector extends Collector(User) {
async collect(ctx: InvocationContext) {
return (ctx.state.user ?? null) as User | null;
}
}
Dès lors, dans n'importe quel handler de la Frond :
async mine(user: User | null): Promise<Post[]> { … }
async publish(id: string, user: User | null): Promise<Post> { … }
Règles de résolution
- Le match est par nom de type d'entité :
Collector(User)résout les paramètres typésUser | null(ouUser). La classe s'enregistre commeUserCollectorpar convention. - Épelez l'union. Le parser de signatures est AST-only :
user: User | nullmatche, un alias de type (user: CurrentUser) est invisible et ne lie rien. - Les collectors sont des classes injectables — déclarez des dépendances de constructeur comme d'habitude.
Le state et le gradient
ctx.state est l'état de requête construit par l'application consommatrice, par exemple à
partir de la session. Lors d'un appel distant, cet état est transmis avec l'invocation :
le collector reçoit le même ctx.state.user qu'en local.
Un collector ne franchit pas la frontière d'une Frond
Placez le collector dans chaque Frond qui le consomme. Ce qui arrive sinon mérite d'être dit précisément, parce que ce n'est ni « plus tard » ni « rien » :
- ce n'est pas au moment du split. La liaison est décidée au démarrage, dans un seul processus, à partir des collectors de la Frond elle-même ;
- le paramètre n'est pas vide. Un type que la Frond ne sait pas résoudre tombe dans la
quatrième règle de binding,
body. Le handler reçoit donc le corps de la requête là où il attend unUser.
Autrement dit, user: User | null déclaré dans une Frond qui n'a pas de UserCollector
reçoit ce que le client a envoyé. Un handler qui juge sur user.role juge sur une valeur
fournie par l'appelant.
Une version précédente de cette page disait que le collector était « perdu après une séparation de processus ». C'était faux deux fois, et la réalité est moins confortable.
Suite : Erreurs — les erreurs typées entre les couches.