@mostajs/numbering
Générateur de références séquentielles formatées (
2026-05-31-001,PF-2026-05-31-007) — gabarits à tokens, remise à zéro périodique (jour/mois/an), compteur atomique via store pluggable. DB-agnostique.
Auteur : Dr Hamid MADANI drmdh@msn.com · Licence : AGPL-3.0-or-later
Primitive transverse de l'écosystème @mostajs/* (factures, commandes, proformats, bons, tickets). À distinguer des identifiants techniques (UUID/ULID) : ici, une référence métier lisible et séquentielle, pas une clé primaire. Consommée par @mostajs/crm (n° de commande, réf proformat).
Installation
npm i @mostajs/numberingLe cœur n'a aucune dépendance. L'atomicité multi-process arrive en v0.1 via OrmCounterStore (composant @mostajs/repository/orm).
Exemple
import { createNumbering } from "@mostajs/numbering";
const num = createNumbering();
num.define({ name: "order", format: "YYYY-MM-DD-NNN", resetEvery: "day", scope: "accountId" });
num.define({ name: "proforma", format: "PF-YYYY-MM-DD-XXX", resetEvery: "day" });
const d = new Date(2026, 4, 31); // 2026-05-31
await num.next("order", { date: d, scope: { accountId: "acc42" } }); // "2026-05-31-001"
await num.next("order", { date: d, scope: { accountId: "acc42" } }); // "2026-05-31-002"
await num.next("proforma", { date: d }); // "PF-2026-05-31-001"
// Jour suivant → le compteur repart à "001". Autre accountId → compteur isolé.Gabarit
| Token | Sens |
|---|---|
YYYY / YY |
année (4 / 2 chiffres) |
MM / DD |
mois / jour (2 chiffres) |
suite de N ou X |
compteur zéro-paddé à la largeur de la suite |
| tout le reste | littéral (PF-, -, …) |
Remise à zéro
resetEvery: "day" | "month" | "year" | "never". Le reset est implicite : la clé de compteur est name|scope|période ; changer de période fait repartir le compteur à 1.
Atomicité & store
Le compteur vit dans un CounterStore (increment / peek). Défaut : MemoryCounterStore (mono-process, tests). En production multi-instance : OrmCounterStore (v0.1), dont increment est atomique via @mostajs/orm.
API
| Élément | Signature |
|---|---|
createNumbering(opts?) |
{ store?, now? } → Numbering |
num.define(def) |
SequenceDef → this |
num.next(name, ctx?) |
→ Promise<string> (incrémente) |
num.peek(name, ctx?) |
→ Promise<string> (n'incrémente pas) |
SequenceDef = { name, format, scope?, resetEvery? } · NumberingContext = { date?, scope? }.
Statut
v0.0.1 — cœur implémenté et testé (gabarit + reset + MemoryCounterStore). Feuille de route : docs/03-PLAN-DEV-NUMBERING.md (0.1 OrmCounterStore atomique, 0.2 mode réservation anti-trous, 1.0 = 14 livrables). Étude : docs/01-ETUDE-ETAT-ART-NUMBERING-07062026.md.