@itzenata/efact-node
v1.1.0
Published
EFact Node.js SDK for JavaScript & TypeScript (ESM + CommonJS) - e-invoicing & DGI clearance for Morocco (facturation électronique). Official Itzenata client, generated from the EFact OpenAPI contract.
Readme
@itzenata/efact-node
SDK Node.js officiel EFact pour l'e-facturation au Maroc (mandat DGI).
EFact est une API de conformité (« le Stripe de la facturation électronique »). Ce SDK est une fine couche typée au-dessus de l'API REST EFact : authentification par clé, nouveaux essais, délais, et erreurs typées.
- ✅ TypeScript natif (types inclus)
- ✅ JavaScript & TypeScript - double build ESM (
import) et CommonJS (require) - ✅ Timeouts, retries avec back-off, erreurs typées
- ✅ Généré depuis le contrat OpenAPI - toujours aligné sur l'API
Installation
npm install @itzenata/efact-nodePrérequis : Node.js ≥ 18.
Démarrage rapide
import { EFact } from "@itzenata/efact-node";
// La clé secrète identifie ET authentifie votre organisation (modèle Stripe).
// Ne la committez jamais : chargez-la depuis l'environnement.
const efact = new EFact(process.env.EFACT_SECRET_KEY!);
const invoice = await efact.invoices.create({
invoiceNumber: "INV-2026-001",
invoiceDate: "2026-06-24",
currency: "MAD",
paymentMethod: "BANK_TRANSFER",
// Acheteur (optionnel) - format plat, aligné sur l'API.
buyerIce: "001234567890123", // 15 chiffres si fourni
buyerName: "Client SARL",
buyerAddress: "Casablanca",
lines: [
{
lineNumber: 1,
description: "Prestation de service",
quantity: 1,
unitPrice: 1000,
vatRate: 20,
},
],
});
console.log(invoice.id, invoice.status);JavaScript (sans TypeScript)
Le SDK fonctionne à l'identique en JavaScript pur - les exemples de ce README restent valables, il suffit de retirer les annotations de types. Les deux systèmes de modules sont supportés :
// ESM ("type": "module" ou fichier .mjs)
import { EFact } from "@itzenata/efact-node";
// CommonJS (require)
const { EFact } = require("@itzenata/efact-node");Même en JavaScript, votre éditeur bénéficie de l'autocomplétion et de la documentation grâce aux types embarqués.
Configuration
Aucune configuration n'est requise. new EFact(secretKey) cible la
production et gère l'authentification, l'URL, les délais et les nouveaux essais
pour vous.
Deux options facultatives permettent d'ajuster le comportement réseau (valeurs par défaut sûres) :
new EFact(secretKey, {
timeout: 30_000, // délai max par requête (ms) - défaut 30000
maxRetries: 2, // rejeux sur erreurs transitoires (méthodes sûres) - défaut 2
});Opérations sur les factures
| Méthode | Description |
| --- | --- |
| efact.invoices.create(input) | Crée une facture |
| efact.invoices.list(params?) | Liste paginée (filtre par statut optionnel) |
| efact.invoices.retrieve(id) | Récupère une facture |
| efact.invoices.retrieveStatus(id) | Statut de clairance DGI |
| efact.invoices.update(id, patch) | Met à jour une facture (PENDING uniquement) |
| efact.invoices.cancel(id) | Annule une facture (PENDING uniquement) |
L'organisation est résolue côté serveur à partir de la clé API : aucun
organizationId n'est transmis. La modification et l'annulation ne sont
possibles que tant que la facture est au statut PENDING.
// Lister (pagination + filtre optionnels)
const page = await efact.invoices.list({ page: 0, size: 20, status: "ACCEPTED" });
for (const inv of page.content) console.log(inv.invoiceNumber, inv.status);
// Suivre la clairance DGI
const status = await efact.invoices.retrieveStatus(invoice.id);
console.log(status.status, status.dgiReference);Gestion des erreurs
Toutes les erreurs héritent de EFactError. Les réponses non-OK de l'API
sont converties en erreurs typées portant code, httpStatus et errors[].
import {
EFact,
EFactApiError,
EFactAuthError,
EFactValidationError,
EFactNotFoundError,
EFactConflictError,
EFactConnectionError,
EFactTimeoutError,
} from "@itzenata/efact-node";
try {
await efact.invoices.create(input);
} catch (err) {
if (err instanceof EFactValidationError) {
console.error("Champs invalides :", err.errors);
} else if (err instanceof EFactAuthError) {
console.error("Clé API manquante ou invalide.");
} else if (err instanceof EFactConflictError) {
console.error("Facture non modifiable (statut ≠ PENDING).");
} else if (err instanceof EFactApiError) {
console.error(err.code, err.httpStatus, err.message);
} else if (err instanceof EFactTimeoutError) {
console.error("Délai dépassé.");
} else if (err instanceof EFactConnectionError) {
console.error("Échec réseau.");
}
}| Erreur | Cas |
| --- | --- |
| EFactConfigError | Mauvaise configuration (avant tout appel réseau) |
| EFactAuthError | 401/403 - clé manquante/invalide |
| EFactValidationError | 400/422 - champs invalides (errors[]) |
| EFactNotFoundError | 404 - introuvable (inclut cross-tenant) |
| EFactConflictError | 409 - facture non modifiable/annulable |
| EFactApiError | autre erreur API |
| EFactTimeoutError | délai dépassé |
| EFactConnectionError | échec réseau |
Les méthodes sûres (GET/PUT/DELETE) sont automatiquement rejouées sur
les erreurs transitoires (408, 425, 429, 5xx, coupures réseau) avec back-off
exponentiel et respect de Retry-After. POST (création) n'est jamais rejoué.
Sécurité
- La clé n'est attachée qu'en
Authorization: Bearer <clé>, jamais dans l'URL. efact.getConfig()ne renvoie qu'une version masquée de la clé.- Les messages d'erreur n'incluent jamais la clé ni le corps brut de la réponse.
