xcraft-core-process
v1.8.3
Published
Xcraft better process spawner
Downloads
2,382
Readme
📘 xcraft-core-process
Aperçu
xcraft-core-process est une bibliothèque utilitaire de bas niveau de l'écosystème Xcraft qui encapsule les fonctions natives de Node.js (child_process.spawn, child_process.fork, child_process.exec) pour lancer des processus externes de manière robuste et instrumentée. Le module capture les flux stdout/stderr ligne par ligne, permet de les rediriger vers différentes stratégies de journalisation (loggers), d'en filtrer le niveau de gravité selon l'outil lancé (forwarders), et d'en extraire des informations spécifiques comme des barres de progression (parsers). Il constitue la brique de base utilisée par tous les modules Xcraft ayant besoin d'exécuter des outils externes (git, cmake, ninja, msbuild, wpkg, esign, etc.).
Sommaire
- Structure du module
- Fonctionnement global
- Exemples d'utilisation
- Interactions avec d'autres modules
- Configuration avancée
- Détails des sources
- Licence
Structure du module
Le module est organisé en quatre familles de composants qui collaborent lors de l'exécution d'un processus :
- Point d'entrée (
index.js) — factory exposantgetpid(),spawn()etfork(), ainsi que la logique interne de découpage des flux en lignes (parseLine) et de bufferisation (parse). lib/printbuffer.js— classe utilitairePrintBufferqui accumule les fragments de sortie tant qu'aucun saut de ligne n'est reçu.lib/loggers/*.js— stratégies de sortie : où et comment écrire les lignes produites par le processus (default,xlog,daemon,none).lib/forwarders/*.js— déterminent le niveau de sévérité (verb,info,warn,err,dbg) d'une ligne selon l'outil lancé (default,msbuild,wpkg).lib/parsers/*.js— analysent les lignes de sortie pour détecter des motifs spécifiques (progression, erreurs) et déterminent le résultat final (rc) transmis au callback de fin (default,cmake,git,msbuild,ninja,wpkg,esign,null).
Fonctionnement global
Lorsqu'un processus est lancé via spawn() ou fork(), le module :
- Instancie le
loggerdemandé (optionlogger), qui lui-même charge en interne leforwarderet leparsercorrespondants aux options fournies. - Démarre le processus enfant natif Node.js (
spawn/fork/execen secours). - Écoute les événements
datasurstdoutetstderr, découpe chaque paquet reçu en lignes complètes (parseLine), et bufferise les fragments incomplets viaPrintBuffer(une instance par flux). - Pour chaque ligne complète, appelle
logger.onStdout(line)oulogger.onStderr(line), qui décide — via leparser.exec()— si la ligne doit être supprimée (cas d'une barre de progression déjà traitée) ou transmise auforwarder.level()puis affichée/journalisée. - À la fermeture du processus (événement
closesi des flux existent, sinonexit) ou en cas d'erreur (error), le module vide les tampons résiduels (drain) puis appellelogger.onClose(code, callback), qui délègue àparser.rc()la construction du résultat final transmis aucallbackutilisateur.
Les callbacks optionnels callbackStdout et callbackStderr sont invoqués en parallèle du logger pour chaque ligne complète, indépendamment de la stratégie de log choisie.
Repli automatique sur exec
Si child_process.spawn échoue avec un code d'erreur UNKNOWN (certains installeurs échouent ainsi sous Windows pour des raisons indéterminées), spawn() retente automatiquement l'exécution via child_process.exec en concaténant l'exécutable et ses arguments dans une seule chaîne ("bin" arg1 arg2 ...). Dans ce mode de secours, le PID n'est pas disponible (getpid() renverra -1) et les flux ne sont pas traités ligne par ligne au fil de l'eau : la sortie complète est traitée d'un bloc une fois le processus terminé.
Exemples d'utilisation
Lancer un processus simple
const xProcess = require('xcraft-core-process')();
const proc = xProcess.spawn(
'ls',
['-la'],
{},
(err, code) => {
console.log(`Processus terminé avec le code ${code}`);
},
(line) => console.log(`STDOUT: ${line}`),
(line) => console.log(`STDERR: ${line}`)
);
console.log(`PID du processus : ${xProcess.getpid()}`);Suivre la progression d'un clone Git via le logger Xcraft
const xProcess = require('xcraft-core-process')({
logger: 'xlog',
forwarder: 'default',
parser: 'git',
});
xProcess.spawn(
'git',
['clone', 'https://github.com/user/repo'],
{encoding: 'utf8', resp: this.quest.resp},
(err, code) => {
if (err) {
console.error(`Erreur : ${err}`);
} else {
console.log('Clone terminé avec succès');
}
}
);Ici, le parser git détecte les lignes de progression (Compressing..., Receiving objects..., etc.) et appelle resp.log.progress(...) au lieu de les afficher brutalement, tandis que le logger xlog journalise le reste via l'API de logging Xcraft.
Gérer un cas d'erreur spécifique (wpkg)
const xProcess = require('xcraft-core-process')({
parser: 'wpkg',
});
xProcess.spawn(
'wpkg',
['--is-installed', 'mon-paquet'],
{encoding: 'utf8'},
(err, code) => {
if (code === 0) {
console.log('Le paquet est installé');
} else if (code === 1) {
console.log("Le paquet n'est pas installé");
} else if (code === 2) {
console.log('Le paquet est partiellement installé');
} else {
console.error(`Erreur : ${err}`);
}
}
);Le parser wpkg adapte l'interprétation du code de retour selon les arguments passés (--is-installed, --compare-versions) et selon la variable d'environnement PEON_DEBUG_PKG.
Interactions avec d'autres modules
xcraft-core-process est un module fondamental sans dépendance vers d'autres modules de l'écosystème Xcraft (sa seule dépendance externe est ansi-regex, utilisée par le forwarder wpkg pour nettoyer les codes couleur ANSI avant analyse). Il est en revanche utilisé en amont par de nombreux modules Xcraft — notamment ceux orchestrant des outils de build ou de packaging (compilation native, gestion de paquets wpkg, opérations Git, signature de binaires) — qui lui délèguent le lancement et l'instrumentation de leurs processus externes. Le logger xlog s'appuie sur l'objet resp (réponse de quête) fourni par les modules appelants pour journaliser via l'API de logging Xcraft et publier la progression, établissant ainsi le lien avec le système de quêtes du framework.
Configuration avancée
La factory exportée par index.js accepte un objet d'options qui pilote le comportement du module :
| Option | Description | Type | Valeur par défaut |
| ----------- | ------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------------------ |
| logger | Nom du logger à charger (lib/loggers/<logger>.js) | String | 'default' |
| forwarder | Nom du forwarder à charger (lib/forwarders/<forwarder>.js) | String | 'default' |
| parser | Nom du parser à charger (lib/parsers/<parser>.js) | String | 'default' |
| resp | Objet réponse de quête Xcraft, requis par le logger xlog et par les parsers affichant une progression | Object | undefined |
| encoding | Encodage utilisé pour décoder les flux stdout/stderr | String | Dépend de opts.encoding passé à spawn/fork |
Variables d'environnement
| Variable | Description | Exemple | Valeur par défaut |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------- |
| PEON_DEBUG_PKG | Bascule le forwarder et le parser wpkg en mode debug : les lignes normalement classées err passent en warn, et les erreurs de rc (hors --is-installed/--compare-versions) sont ignorées | 1 | Non défini |
Détails des sources
index.js
Point d'entrée du module. La fonction exportée est une factory qui, à partir des options fournies, retourne un objet exposant trois méthodes. En interne, elle charge dynamiquement le fichier logger correspondant à l'option logger et conserve le PID du dernier processus lancé dans une variable partagée entre les appels.
Les fonctions internes parseLine et parse gèrent respectivement le découpage d'un paquet de données en lignes complètes, et le branchement des événements du processus enfant (data, error, close/exit) vers le logger.
Méthodes publiques
getpid()— Retourne le PID du dernier processus lancé par cette instance de la factory, ou-1si aucun processus n'a été lancé ou si le dernier lancement est passé par le mode de secoursexec.spawn(bin, args, opts, callback, callbackStdout, callbackStderr)— Lance un exécutable viachild_process.spawn.binest le chemin de l'exécutable,argsun tableau d'arguments,optsles options transmises àspawn(l'attributencodingen est extrait avant l'appel).callback(err, code)est appelé à la fin du processus,callbackStdout/callbackStderrpour chaque ligne complète des flux respectifs. Sispawnéchoue avec le codeUNKNOWN, la fonction retente automatiquement viachild_process.execet retourne alorsnullau lieu de l'instance du processus.fork(bin, args, opts, callback, callbackStdout, callbackStderr)— Lance un module Node.js viachild_process.fork, avec la même signature de callbacks quespawn. Retourne toujours l'instance du processus enfant.
lib/printbuffer.js
Classe utilitaire PrintBuffer qui accumule les fragments de texte reçus tant qu'ils ne se terminent pas par un saut de ligne, afin d'éviter de traiter des lignes coupées en plusieurs paquets réseau/pipe.
Méthodes publiques
buf(line, outFunc, prepend, append)— Ajoutelineau tampon interne. Silinene se termine pas par\n, elle est simplement accumulée. Sinon,outFuncest appelée avec le tampon complet (préfixé parprependsi le tampon était vide, suffixé parappend), puis le tampon est réinitialisé.
Loggers (lib/loggers/)
Les loggers déterminent la destination finale des lignes de sortie et orchestrent le forwarder et le parser associés.
default.js— Charge le forwarder et le parser indiqués dans les options. Pour chaque ligne, interroge d'abord le parser (exec) ; si celui-ci ne l'a pas déjà traitée (ex. affichage d'une progression), écrit la ligne surprocess.stdoutouprocess.stderrselon le niveau retourné par le forwarder. À la fermeture, délègue àparser.rc().xlog.js— Variante utilisant l'API de logging Xcraft (opts.resp.log) au lieu d'écrire directement sur les flux natifs. Configure la verbosité du logger viaparser.getLevel()dès l'instanciation.daemon.js— Enrobe le loggerdefaulten préfixant chaque ligne avec(pid), utile pour distinguer les sorties de processus démons tournant en arrière-plan.none.js— Ignore complètement les lignes de sortie (onStdout/onStderrsont des no-op), tout en déléguant néanmoins la gestion du code de retour àparser.rc().
Forwarders (lib/forwarders/)
Les forwarders déterminent le niveau de sévérité (verb, info, warn, err, dbg) à associer à une ligne selon sa provenance (stdout/stderr) et son contenu.
default.js— Associe systématiquementstdoutau niveauverbetstderrau niveauwarn.msbuild.js— Analyse le contenu destdoutpour détecter les motifserror MSBxxxx/CSxxxx/CAxxxx(niveauerr) ouwarning ...(niveauwarn) ; toutstderrest classéwarn.wpkg.js— Nettoie les codes couleur ANSI (viaansi-regex) puis reconnaît le formatprog [module] Niveau:pour en extraire le niveau exact. Gère aussi des motifs spécifiques (^error,wpkg:debug,wpkg:info,wpkg:warning,(node) warning). Le niveau par défaut pour les lignes non reconnues dépend de la variablePEON_DEBUG_PKG(warnsi définie,errsinon).
Parsers (lib/parsers/)
Les parsers analysent les lignes de sortie pour en extraire des informations structurées (essentiellement des barres de progression) et transforment le code de retour du processus en résultat exploitable par le callback final.
default.js— Ne traite aucune ligne (execrenvoie toujoursfalse). Le code de retour non nul devient l'erreur'rc=<code>'.cmake.js— Détecte les motifs[NN%]et transmet la progression viaresp.log.progress('CMake building', ...).git.js— Détecte les motifs de progression Git (Compressing,Receiving,Resolving,Counting objects,Checking out files,Updating files, suivis d'un pourcentage) et les transmet viaresp.log.progress.ninja.js— Détecte les motifs[N/M]typiques de Ninja et les transmet viaresp.log.progress('Ninja building', ...).msbuild.js— Ne traite aucune ligne particulière ; retourne simplement une erreur générique'msbuild error'si le code de retour est non nul.esign.js— Détecte les motifs de progression[NN,N%] libelléet les transmet viaresp.log.progress.wpkg.js— Ignore certaines lignes attendues selon les arguments passés (--listfiles,--list-index-packages,--list-index-packages-json, ou les échecschmod/chown). Interprète le code de retour différemment selon le contexte : tolère les codes jusqu'à2pour--is-installed, ignore toujours l'erreur pour--compare-versions, et sinon ne signale une erreur que siPEON_DEBUG_PKGn'est pas défini.null.js— Ignore systématiquement toute ligne (execrenvoie toujourstrue, ce qui empêche tout affichage) et ne remonte jamais d'erreur aucallback, quel que soit le code de retour.
Tous les parsers exposent une méthode getLevel() utilisée par le logger xlog pour fixer la verbosité ; dans l'implémentation actuelle, tous retournent 0.
Licence
Ce module est distribué sous licence MIT.
Ce contenu a été généré par IA
