Fiches de révision
Trois fiches recto-verso, à imprimer.
Fiche 1 : l'objet standard
Recto : le squelette
class X {
instanceName; broker; deps;
supports; support; verbose = false;
emits = [{ name: "a", version: 1 }];
receives = [{ name: "b", version: 1 }];
constructor(broker, instanceName, deps = {}) {
this.broker = broker;
this.instanceName = instanceName;
this.deps = deps;
this.supports = deps.support?.nodeType
? { main: deps.support } : (deps.support ?? {});
this.support = this.supports.main;
this.render(); // client seulement
this.broker.register(this, this.emits, this.receives);
}
handleMessage(message) {
if (message.b) { /* … */ this.broker.publish(this, { a: {…} }); }
}
destroy() {
this.broker.unregister(this, this.emits, this.receives);
for (const n of Object.values(this.supports)) n.replaceChildren();
}
}
Verso : les règles
- Signature unique, client et serveur.
- Ne connaît que le broker. Jamais un autre composant.
- Tout arrive par
deps: support, pool, socket, réglages. Jamaisprocess.env, jamaisconfig.js. - Ressource ouverte, pas URL. On ne ferme pas ce qu'on n'a pas ouvert.
- Abonné : pas de révision. Émetteur : la sienne, ou la courante.
destroy()toujours ;= nulljamais.publishdepuishandleMessage: mis en file, livré après.- Composants uniques : corréler par
ref, cibler parid. - À l'intérieur : programmation normale.
Fiche 2 : anatomie d'un contrat
Recto
nom_du_message: {
versions: {
1: {
revisions: {
0: { fields: { a: { type: "string", required: true } } },
1: { fields: { // snapshot complet
a: { type: "string", required: true },
b: { type: "number", required: true, default: 0 },
} },
},
},
2: {
upcastFrom: { rename: { "a": "x.a" }, defaults: { "x.c": 1 }, remove: [] },
revisions: { 0: { fields: {
x: { type: "object", required: true, fields: {
a: { type: "string", required: true },
c: { type: "number", required: true },
} },
b: { type: "number", required: true },
} } },
},
},
examples: { 1: { 0: [{ a: "x" }], 1: [{ a: "x", b: 2 }] }, 2: { 0: [{ x: { a: "x", c: 1 }, b: 2 }] } },
counterexamples: { 1: { 0: [{ reason: "a manquant", payload: {} }] } },
}
Verso
type | string · number · boolean · object · array |
required | présent dans cette révision |
pattern | regex, string seulement |
enum | valeurs admises, primitifs |
default | complétion à l'upcast, jamais validation |
fields | sous-champs, obligatoire sur object |
items | règle d'élément, obligatoire sur array |
oneOf | exactement un parmi N ; membres optionnels sans default |
upcastFrom | rename · defaults · remove ; chemins par . |
- Révision = ajout compatible, snapshot. Courante = la plus haute.
- Version = cassant, rare, upcaster déclaratif. Jamais de downcast.
- Un contrat validé ne se modifie jamais.
- Les abonnés d'abord, l'émetteur en dernier.
Fiche 3 : trajet d'un message
Recto : local
A.publish({ x: payload })- Le broker vérifie l'inscription de A sur
x(identité). - Validation contre la révision déclarée par A. Invalide : jeté, violations en console.
- Forme canonique (défauts), mise en file.
- Drain : pour chaque abonné de
x, upcast de version si besoin, copie privée,handleMessagesous try/catch. - Un
publishpendant 5 : mis en file, livré après. - Plus de 1000 livraisons en un drain : cycle, file jetée.
Verso : à travers un canal
- Côté client, le seul abonné de
xest le canal : il envoie la trame JSON. - Côté serveur, le canal pose
idetsession, upcaste depuis la révision du client, consulteallowMessage. - Il publie : le broker serveur valide à nouveau, livre aux composants serveur.
- Une réponse avec
idn'atteint que ces sessions ; sansid, tous. - Le canal retire
idetsessionavant d'envoyer. - Le canal client publie ; le broker client valide ; les écrans reçoivent.
Avant tout cela : handshake (compatibilité des catalogues, jeton de session), puis await canal.ready().
connection_event : connected → disconnected → resumed | expired.