L'exemple complet : le chat

Lecture guidée du dossier exemple/ dans l'ordre de composition. Chaque extrait est lu dans le fichier source réel. Tous les fichiers sont consultables, annotés, dans les sources.

Télécharger le chat complet (chat_fwtozza.zip) : npm install && node index.js, puis http://localhost:3005. · Faire tourner le chat dans le navigateur · Graphe des messages et scénarios

exemple/ — arborescence, avec le miroir public/ index.jscomposition serveur : broker, canal, composants, audit package.json"type": "module", dépendance ws fw/framework serveur — générique, jamais régénéré engine.jsshim : export * from "../public/fw/engine.js" broker.jsbroker serveur (route id et session) channel.catalog.jsconnection_event channels/websocket_channel.jsmoitié serveur du canal catalogs/catalog.jsunion serveur : framework + SHARED components/ gestion_connexion.jsauth, présence, allowMessage gestion_messages.jsfil, mention d'écriture, historique outils.jsdépôt mémoire, hachage, présence public/racine web — miroir de la structure serveur index.htmlcomposition client fw/ engine.js · broker.js · channel.catalog.js · channels/websocket_channel.js catalogs/ websocket.catalog.js · client.catalog.js · catalog.jsun fichier par canal + union components/ ecran_connexion.js · ecran_fil.js css/style.css
Violet : le framework, qu'on ne touche jamais. Ocre : composants serveur. Bleu : composants client. Les catalogues de canal vivent sous public/ et le serveur vient les y chercher : une seule source.

1. Le catalogue du canal : websocket.catalog.js

Sept contrats partagés et l'autorisation de transit. Quatre messages montent (client → serveur), trois descendent. Deux ont deux formes, avec oneOf : acces_reponse (accord ou refus) et message_poste (un message ou l'historique).

Puis les deux unions. Côté client, un garde-fou compare les jeux en forme canonique avant d'étaler, parce que le spread ne fusionne pas :

Côté serveur, le fichier est généré, et il étale en plus CHANNEL_CONTRACTS du framework :

2. La composition serveur : index.js

Le broker sur le catalogue d'union, le WebSocketServer ouvert ici puis passé au canal par deps, un seul dépôt partagé par les deux composants, l'audit en fin de montage, et l'arrêt propre.

3. gestion_connexion : auth et présence

Le composant d'authentification du canal. Il reçoit connection_event et, au connected comme au resumed, rattache la session : il y range le tableau partagé des connectés et pose la porte allowMessage, de façon synchrone. Sans pseudo en session, seuls acces_demande et deconnexion_demande passent.

À la demande d'accès, il crée ou vérifie l'utilisateur, écrit le pseudo dans session.data, répond ciblé sur la session demandeuse, et diffuse la présence à tous les connectés.

La présence est un utilitaire pur : presence_changee ciblé par un tableau d'id.

4. gestion_messages : le fil

Trois réceptions : message_demande, presence_signalee, et acces_reponse dont il ne traite que l'accord pour servir l'historique au nouvel arrivant. Le composant lit l'identité dans message.session.data, jamais dans le payload.

5. La composition client : index.html

Le socket est créé par la page, la ressource ouverte et pas son URL, avec une fabrique de reconnexion et le sessionStorage pour le jeton. Le canal ne s'inscrit qu'après le handshake : on attend ready() avant de monter les écrans.

6. ecran_connexion

Un seul composant pour tout l'écran : champs, validation locale (les mêmes bornes que le contrat), émission de acces_demande avec un ref tiré pour l'occasion, gestion de sa propre visibilité à la réponse.

7. ecran_fil

La liste des connectés et le fil restent ensemble : ils lisent le même presence_changee. Les lignes « a rejoint / a quitté » sont déduites de deux présences successives. L'historique s'insère à la date, sans doublon grâce aux ref.

La mention d'écriture est signalée au premier caractère puis au plus une fois par seconde :

8. Le canal WebSocket, les deux moitiés

Côté client, le canal reçoit un socket déjà créé et s'inscrit en miroir croisé de CHANNEL après le handshake. Côté serveur, il reçoit le WebSocketServer, tient le magasin de sessions, vérifie la compatibilité des contrats, pose id et session, consulte allowMessage. La référence détaille les règles ; la source annotée les pointe ligne par ligne.