@mostajs/statemachine
v0.0.1
Published
Pure finite state machine — config transitions (from[]→to + permission + injected guard) and immutable executed-transition history (via injected AuditSink). The STATE primitive of the State·Rule·Trigger triptych, assembled by @mostajs/workflow.
Downloads
66
Maintainers
Readme
@mostajs/statemachine
Machine à états finie pure — transitions de configuration (
from[]→to+ permission + garde injectée) et historique immuable des transitions exécutées (viaAuditSinkinjecté). La brique STATE du triptyque State · Rule · Trigger (modèle Drupal Workflow).
Auteur : Dr Hamid MADANI [email protected] · Licence : AGPL-3.0-or-later
Primitive de l'écosystème @mostajs/*. Reste pure : la garde (→ @mostajs/rules), la permission (→ @mostajs/rbac) et le journal (→ @mostajs/audit) sont injectés. La stack @mostajs/workflow les assemble.
Installation
npm i @mostajs/statemachineLe cœur n'a aucune dépendance. Les adaptateurs réels (@mostajs/audit, @mostajs/rbac) arrivent en v0.1.
Exemple (cycle de commande)
import { defineMachine } from "@mostajs/statemachine";
const m = defineMachine({
states: [
{ id: "nouvelle", initial: true },
{ id: "en_cours" },
{ id: "validee" },
{ id: "terminee", terminal: true },
{ id: "annulee", terminal: true },
],
transitions: [
{ id: "start", from: ["nouvelle"], to: "en_cours" },
{ id: "valid", from: ["en_cours"], to: "validee", guard: (c) => c.data?.ok === true },
{ id: "finish", from: ["validee"], to: "terminee" },
{ id: "cancel", from: ["nouvelle", "en_cours", "validee"], to: "annulee", permission: "crm.order.transition.cancel" },
],
});
const ref = { entityType: "order", entityId: "42" };
await m.transition(ref, "nouvelle", "en_cours", { actorId: "u1", comment: "prise en charge" });
await m.canTransition("en_cours", "validee", { data: { ok: false } }); // { allowed:false, reason:"guard" }
await m.history(ref); // historique immuable (qui / quand / from→to / comment)Modèle (distinction Drupal config / exécution)
| Concept | Type |
|---|---|
| chemin autorisé | ConfigTransition { id, from: string[], to, permission?, guard? } |
| transition exécutée (immuable) | ExecutedTransition { entityType, entityId, fromState, toState, actorId?, timestamp, comment? } |
| journal append-only | AuditSink { record, list } |
Injections (composition)
| Capacité | Injection | Module cible |
|---|---|---|
| historique immuable | audit | @mostajs/audit |
| permission par transition | checkPermission | @mostajs/rbac |
| garde déclarative | guard (par transition) | @mostajs/rules |
| date | now | testabilité |
API
defineMachine(def, opts?) → Machine · m.availableTransitions(current, input?) · m.canTransition(from, to, input?) → { allowed, reason? } · m.transition(ref, from, to, input?) → ExecutedTransition · m.history(ref) · m.onPre/onPost. input = { actorId?, data?, comment? }.
Statut
v0.0.1 — cœur implémenté et testé (defineMachine, can/transition, gardes, MemoryAuditSink, hooks pre/post). Feuille de route : docs/03-PLAN-DEV-STATEMACHINE.md (0.1 adaptateurs audit/rbac, 1.0 = 14 livrables). Étude : docs/01-ETUDE-ETAT-ART-STATEMACHINE-07062026.md.
