Le module xcraft-core-utils est une bibliothèque utilitaire centrale du framework Xcraft qui fournit un ensemble complet d'outils et de classes pour diverses opérations courantes. Il regroupe des utilitaires pour la manipulation de données, la cryptographie, la gestion de fichiers, les opérations asynchrones, la synchronisation, la mise en cache, les files d'attente de jobs, et bien plus encore.
- Structure du module
- Fonctionnement global
- Exemples d'utilisation
- Interactions avec d'autres modules
- Variables d'environnement
- Détails des sources
Le module expose une collection d'utilitaires organisés par domaine fonctionnel :
- Collecteurs et agrégateurs :
ArrayCollector,MapAggregator,EventDebouncer - Traitement par lots :
batch,Batcher,JobQueue - Cryptographie et hachage :
crypto,fileCrypto,hash - Manipulation de fichiers :
files,json,yaml,zippy - Utilitaires système :
os,modules,whereIs - Programmation :
js,reflect,propTypes - Réseau :
RestAPI - Concurrence :
locks,CursorPump - Cache et performance :
RankedCache - Manipulation de chaînes :
string,regex - Logging :
log
Ce module agit comme une boîte à outils centralisée pour l'écosystème Xcraft. Chaque utilitaire est conçu pour être autonome tout en s'intégrant parfaitement avec les autres composants du framework. Les utilitaires supportent les patterns asynchrones avec gigawatts et sont optimisés pour les performances dans un environnement distribué.
Le module ne contient pas d'acteurs Elf ou Goblin : il s'agit uniquement d'une librairie utilitaire importée par d'autres modules.
const {ArrayCollector} = require('xcraft-core-utils');
const collector = new ArrayCollector(resp, 100, async (entries, resp) => {
// Traitement des données collectées par clé
for (const [key, values] of Object.entries(entries)) {
console.log(`Clé: ${key}`, values);
}
});
collector.grab('entityA', [{id: 1}]);
collector.grab('entityA', [{id: 2}]);
collector.grab('entityB', [{id: 3}]);
// La fonction onCollect est déclenchée après 100ms maximumconst {JobQueue} = require('xcraft-core-utils');
const runner = function* (job, next) {
console.log(`Traitement du job ${job.id}`);
yield setTimeout(next, 1000);
};
const queue = new JobQueue('processing', runner, 3, {
priorityGroup: 'highPrio',
waitOn: ['lowPrio'],
});
queue.push({id: 'job-1', payload: 'example'});const {crypto, hash} = require('xcraft-core-utils');
// Génération de mots de passe sécurisés
const password = crypto.randomPassword(16);
// Entier aléatoire cryptographiquement sûr
const roll = crypto.randomInt(1, 6);
// Hachage déterministe d'un objet
const objectHash = hash.computeHash({user: 'john', role: 'admin'});const {RestAPI} = require('xcraft-core-utils');
class MyApi extends RestAPI {
constructor() {
super(30000, {Authorization: 'Bearer token'});
}
async getUsers() {
return this._get('https://api.example.com/users');
}
async streamResults() {
const stream = await this._getStream('https://api.example.com/stream');
if (stream.error) throw stream.error;
for await (const item of stream) {
console.log(item);
}
}
}const {locks} = require('xcraft-core-utils');
// Mutex simple
const mutex = new locks.Mutex();
yield mutex.lock();
try {
// Section critique
} finally {
mutex.unlock();
}
// Mutex par clé (GetMutex global)
yield locks.getMutex.lock('resource-id');
try {
// Accès exclusif à la ressource 'resource-id'
} finally {
locks.getMutex.unlock('resource-id');
}
// Exécution coalescente : seul le premier et le dernier appel concurrent s'exécutent
const executor = new locks.CoalescingExecutor();
await executor.run(async () => expensiveOperation());const {Batcher} = require('xcraft-core-utils');
const batcher = new Batcher(
async () => db.beginTransaction(),
async (count) => db.commit(),
500, // commit tous les 500 éléments
5000 // ou après 5s d'inactivité
);
await batcher.start();
for (const record of records) {
await db.insert(record);
const shouldContinue = await batcher.bump();
if (!shouldContinue) break;
}
await batcher.stop();const {RankedCache} = require('xcraft-core-utils');
const cache = new RankedCache(100); // max 100 entrées
cache.on('out', (item) => {
console.log('Élément évincé:', item.payload);
});
const item = cache.rank({id: 'style-1', css: '...'});
// Promouvoir un élément existant
cache.rank(item);- xcraft-core-log : Utilisé pour le logging dans
JobQueueet d'autres utilitaires - xcraft-core-fs : Intégré pour les opérations sur le système de fichiers dans
batchetmodules - xcraft-core-busclient : Utilisé par
JobQueuepour les notifications d'événements sur le bus Xcraft - xcraft-traverse : Utilisé pour la traversée d'objets complexes dans
hash,jsonetmodules - gigawatts : Support des générateurs et fonctions asynchrones dans les classes principales
| Variable | Description | Exemple | Valeur par défaut |
|---|---|---|---|
PATH |
Chemin système utilisé par whereIs pour localiser les exécutables |
/usr/bin:/bin |
Variable système |
APPDATA |
Répertoire de données d'application sur Windows (utilisé par os.getAppData()) |
C:\Users\User\AppData\Roaming |
Variable système |
Classe pour collecter des données par clés avec un mécanisme de throttling. Permet d'accumuler des données et de les traiter par lots à intervalles réguliers. Supporte les modes synchrone et asynchrone via le paramètre async du constructeur.
En mode synchrone, le callback onCollect est wrappé avec gigawatts pour supporter les générateurs. En mode asynchrone, il est appelé avec await directement.
grab(key, data)— Ajoute des données à la collection sous une clé spécifique (par concaténation) et déclenche le traitement throttlé.cancel()— Annule le traitement en attente (throttle en cours).
Module exportant une instance singleton avec des utilitaires pour les opérations asynchrones qui évitent de bloquer la boucle d'événements principale.
mapReduce(keyFunc, valueFunc, list)— Réduit un tableau en map avec itération asynchrone. Utile pour les très grandes collections où chaque item est traité via unePromise, libérant la boucle d'événements entre les itérations.
Fonction utilitaire pour exécuter une action sur tous les fichiers d'un répertoire de manière récursive.
run(filter, location, callbackAction)— Parcourt récursivement un répertoire et exécutecallbackActionsur les fichiers dont le nom correspond au filtre regex. Les sous-répertoires sont traités récursivement.
Gestionnaire de traitement par lots avec support de timeout et de seuils de déclenchement. Idéal pour optimiser les opérations coûteuses comme les transactions de base de données ou les écritures disque en regroupant les appels.
Le Batcher maintient une session entre start() et stop(). La méthode bump() incrémente le compteur et déclenche automatiquement un stop()/start() quand le seuil batch est atteint ou quand le timeout expire. La méthode pump() vérifie uniquement le timeout via un setImmediate.
start()— Démarre une nouvelle session : appellebegin()et arme le timer de timeout.bump()— Incrémente le compteur et déclenche un cycle commit/restart si le seuil ou le timeout est atteint. Retournefalsesi le batcher est en cours de destruction.pump()— Cède le contrôle viasetImmediatepuis déclenche un cycle si le timeout est atteint. Retournefalsesi destruction en cours.stop()— Termine la session courante en appelantcommit(count)avec le nombre d'éléments traités.dispose()— Marque le batcher pour destruction ; les prochains appels àbump()/pump()déclencheront l'arrêt.
Utilitaires cryptographiques pour le hachage, la génération de tokens et de mots de passe sécurisés. Utilise le module natif node:crypto pour garantir la qualité cryptographique des nombres aléatoires.
L'algorithme de génération d'entiers aléatoires (randomInt) utilise un rejet des valeurs hors plage pour garantir une distribution uniforme sans biais statistique.
md5(data)— Calcule le hash MD5 des données (retourne une chaîne hexadécimale).sha256(data)— Calcule le hash SHA256 des données (retourne une chaîne hexadécimale).genToken()— Génère un token UUID v4 sans tirets (32 caractères hexadécimaux).randomInt(min, max)— Génère un entier aléatoire cryptographiquement sûr dans[min, max]. Lève une erreur si la plage dépasse2^31 - 1.randomChar(chars)— Génère un caractère aléatoire à partir d'un ensemble (défaut : alphanumérique + symboles sans caractères ambigus).randomPassword(length=12, chars)— Génère un mot de passe aléatoire sécurisé de la longueur spécifiée.
Wrapper pour les curseurs de base de données permettant de pomper les données de manière asynchrone avec gigawatts. Le curseur doit implémenter une méthode next() qui rejette sa promesse en fin de données.
toArray()— Consomme intégralement le curseur et retourne toutes les lignes dans un tableau.pump()— Récupère le prochain élément du curseur (lève une exception en fin de curseur).
Classe pour débouncer l'envoi d'événements sur le bus Xcraft, évitant les envois trop fréquents pour un même topic. Un debouncer distinct est créé par topic à la première utilisation.
publish(topic, data)— Publie un événement avec debouncing automatique. Les appels répétés dans la fenêtrewait(défaut 1000ms) sont fusionnés, seul le dernier est envoyé.
Utilitaires cryptographiques pour les fichiers, utilisant des streams pour éviter de charger le fichier entier en mémoire.
fileChecksum(filePath, options)— Calcule la somme de contrôle d'un fichier.options.algorithm(défautsha1) etoptions.encoding(défauthex) sont configurables. Lève une erreur si le chemin ne désigne pas un fichier.
Utilitaires pour la détection de types de fichiers. Contient une base de données statique d'extensions couvrant audio, archives, images, documents, code source, vidéos, etc.
getFileFilter(filePath)— Retourne{name, extensions}basé sur l'extension du fichier. Retourne{name: '?', extensions: [ext]}si l'extension est inconnue.getMimeType(filePath)— Détecte le type MIME et le charset d'un fichier en utilisant libmagic (@npcz/magic). Retourne{mime, charset}. Préserve l'atime sur macOS et Linux.
Calcul de hash SHA256 déterministe pour des objets JavaScript complexes en traversant récursivement toutes les feuilles de l'arbre d'objets.
Seules les valeurs de type number, string et boolean contribuent au hash. Les chaînes vides sont remplacées par \0 pour les distinguer de null/undefined (qui sont ignorés).
computeHash(payload)— Calcule un hash SHA256 hexadécimal d'un objet JavaScript en traversant récursivement ses propriétés feuilles.
Système de files d'attente avancé avec support de priorités, limitations de parallélisme, gestion des dépendances entre groupes et mécanismes de retry. Les jobs sont stockés dans une Map (préservation d'ordre d'insertion). L'exécution réelle est déléguée au singleton runnerInstance.
Les notifications de débit sont émises sur l'événement <job-queue.sampled> via le bus Xcraft, avec throttling à 500ms.
push(job)— Ajoute un job à la file d'attente (le job doit avoir une propriétéid). Planifie une exécution viasetTimeout(..., 0).dispose()— Nettoie la file : émet l'événement<job-queue.disposed>et remet le compteur de samples à zéro.
Utilitaires légers pour l'introspection de fonctions JavaScript.
isFunction(fn)— Vérifie si l'argument est une fonction.isGenerator(fn)— Vérifie si l'argument est une fonction générateur (function*).isAsync(fn)— Vérifie si l'argument est une fonction async.
Utilitaires pour la manipulation de fichiers JSON et la transformation de structures de données.
fromFile(jsonFile)—⚠️ Déprécié : utiliserfse.readJSONSyncà la place.toFile(json, destFile)—⚠️ Déprécié : utiliserfse.writeJSONSyncà la place.dotKeysToObject(json)— Convertit les clés avec points en objets imbriqués. Exemple :{"foo.bar": true}devient{foo: {bar: true}}. Supporte les chemins imbriqués arbitrairement profonds et les tableaux.
Implémentations de primitives de synchronisation compatibles avec le pattern générateur gigawatts.
Mutex— Mutex simple. Méthodes :*lock(next)etunlock(). PropriétéisLocked.RecursiveMutex— Mutex récursif : un mêmeownerpeut verrouiller plusieurs fois sans deadlock.unlock(owner)doit être appelé autant de fois quelock(owner).Semaphore— Sémaphore avec valeur initiale configurable. Méthodes :*wait(next)etsignal().GetMutex(instance exportée commegetMutex) — Gestionnaire de mutex nommés : crée et détruit automatiquement les mutex par clé. Méthodes :*lock(key)etunlock(key).CoalescingExecutor— Exécuteur coalescent : si plusieurs appels concurrents arrivent, seuls le premier et le dernier s'exécutent (les intermédiaires sont abandonnés). Méthode :async run(work).
Utilitaires de formatage et de décoration pour les logs avec support des couleurs ANSI, de l'indentation adaptative et de la détection de logs imbriqués. Utilisé par xcraft-core-log.
decorate(mode, prefix, mod, log, maxWidth, stripBegin)— Formate un message de log avec alignement dynamique, retour à la ligne automatique selon la largeur du terminal, et détection des logs embarqués.graffiti(text, callback)— Génère du texte ASCII art avec la police Graffiti (viafiglet) et colorise les caractères_,/,\en vert/gris.getIndent()— Retourne la valeur d'indentation globale courante.computeIndent(prefix, mod)— Calcule le nombre d'espaces nécessaires pour aligner les messages et met à jour l'indentation globale si nécessaire.
Classe pour agréger des données dans une structure de map imbriquée avec throttling. Contrairement à ArrayCollector, MapAggregator écrase les valeurs existantes plutôt que de les concaténer.
put(keys, data)— Ajoutedatadans la map en suivant le cheminkeys(tableau ou chaîne avec points). Déclenche le throttle de libération.release()— Force la libération immédiate des données agrégées vers le callbackonCollect.
Utilitaires pour la gestion des modules et configurations d'applications Xcraft avec support des variantes de déploiement et des surcharges de configuration.
La fonction extractForEtc gère les surcharges @appId dans app.json pour fusionner les configurations multi-applications. Les valeurs -0 dans les JSON de configuration sont des marqueurs spéciaux pour revenir aux valeurs par défaut du config.js de chaque module.
mergeOverloads(obj, overloads)— Fusionneoverloadsdansobjen préservant les tableaux (non-fusion récursive des arrays).extractForEtc(appDir, appId, variantId)— Extrait et fusionne la configuration d'une application pourxcraft-core-etc, en appliquant les surcharges de variante et les configs@appId.loadAppConfig(appId, appDir, configJson, variantId)— Charge récursivement la configuration d'une application et de toutes ses hordes.extractConfigDeps(libDir, configJson)— Extrait les dépendances de modules déclarées dans les configs serveur.extractAllDeps(appId, libDir, configJson)— Résout récursivement toutes les dépendances Xcraft d'une application.extractAllJs(libDir, modules)— Retourne la liste de tous les fichiers.jsdes modules spécifiés (horsnode_modules,test,species).
Utilitaire pour les chemins de données d'application multi-plateformes.
getAppData()— Retourne%APPDATA%sur Windows,~/Library/Application Supportsur macOS,~/.local/sharesur Linux.
Générateurs de PropTypes React avec support des types étendus du système de design Xcraft (couleurs, espacements, glyphes, types Nabu, etc.).
Le type nabu valide que la prop est soit une chaîne, un nombre, soit un objet avec nabuId ou _type: 'translatableString'/'translatableMarkdown' (supportant aussi les Map/OrderedMap Immutable.js).
makePropTypes(props)— Génère un objetpropTypesReact à partir d'une définition de propriétés Xcraft. Applique.isRequiredsiprop.requiredest vrai.makeDefaultProps(props)— Génère un objetdefaultPropsReact à partir desdefaultValuede la définition.
Cache LRU (Least Recently Used) basé sur une liste doublement chaînée avec émission d'événements lors de l'éviction. Les éléments les moins récemment utilisés migrent vers la tête de liste et sont évincés en premier quand la limite est atteinte.
Un RankedCache avec limit <= 0 retourne toujours null sans stocker quoi que ce soit.
rank(item)— Ajoute un nouvel item (valeur brute ouLinkedList.Item) ou promeut un item existant d'un cran dans la liste. Émet'out'avec l'item évincé si la limite est atteinte.clear()— Vide entièrement le cache en émettant'out'pour chaque item.
Utilitaires de réflexion pour l'introspection de code JavaScript.
funcParams gère correctement les valeurs par défaut complexes (expressions imbriquées, chaînes avec parenthèses), les commentaires, et les fonctions fléchées avec ou sans parenthèses.
funcParams(func)— Extrait les noms des paramètres d'une fonction sous forme de tableau de chaînes, en supprimant les valeurs par défaut et les commentaires.parseOptions(args)— Parse une chaîne d'options CLI en tableau en gérant les espaces échappés, les guillemets simples et doubles, et les guillemets imbriqués.
Utilitaires pour la manipulation d'expressions régulières avec support des patterns Axon et Xcraft.
toRegexp(value)— Convertit une chaîne enRegExpancrée (^...$) ou retourne la valeur si c'est déjà unRegExp.toAxonRegExpStr(str)— Convertit une chaîne avec wildcards*en pattern regex pour le système de messagerie Axon.toXcraftRegExpStr(str)— Convertit une chaîne avec wildcards*et groupes(...)en pattern regex pour le bus Xcraft.
Client REST avancé basé sur got avec support des streams JSON, retry automatique sur HTTP 429 (avec respect du header Retry-After), et enrichissement des erreurs avec l'URL et le corps de la réponse.
Les méthodes de stream utilisent JSONStream.parse('*') pour émettre chaque élément d'un tableau JSON au fil de la réception. Les erreurs de stream sont capturées dans stream.error et doivent être testées explicitement après la consommation du stream.
_get(query)— Requête GET, retourne le body parsé._getWithHeaders(query)— Requête GET, retourne{body, headers}._post(query, payload, options={})— Requête POST avec payload JSON._delete(query)— Requête DELETE._patch(query, payload)— Requête PATCH avec payload JSON._putForm(query, formData)— Requête PUT avec données de formulaire (sans headercontent-type)._getStream(query, json=true)— Retourne un stream GET ; sijson=true, parse le JSON à la volée._postStream(query, payload, json=true)— Retourne un stream POST avec payload JSON._streamPostStream(query, stream, json=true)— Envoie un stream en corps de requête POST et retourne un stream de réponse.
Singleton global (via Symbol.for) qui orchestre l'exécution des JobQueue. Il gère le parallélisme, les groupes de priorité et les dépendances entre groupes. Son unicité est garantie même si le module est chargé plusieurs fois dans des contextes différents.
L'algorithme de priorité suspend les jobs d'une queue si un groupe listé dans waitOn est actuellement en cours d'exécution, avec retry configurable (maxAttempt, waitDelay).
Utilitaires légers de manipulation de chaînes.
camelcasify(str)— Convertit les segments séparés par des points en camelCase (ex:foo.bar→fooBar).capitalize(str)— Met la première lettre en majuscule et le reste en minuscules.jsify(str)— Convertit les tirets en camelCase (ex:foo-bar→fooBar).
Utilitaire pour localiser des exécutables dans le PATH système.
whereIs(bin)— Recherche un exécutable dans chaque répertoire duPATHet retourne le premier chemin complet trouvé, ounullsi absent.
Utilitaires pour la manipulation de fichiers YAML via js-yaml.
fromFile(yamlFile)— Charge et parse un fichier YAML, retourne l'objet JavaScript correspondant.toFile(data, yamlFile)— Sérialise un objet en YAML et l'écrit dans un fichier (largeur de ligne 999 pour limiter les retours à la ligne).
Utilitaire pour créer des archives ZIP à partir d'une liste de fichiers vers un stream de sortie Node.js, avec support du chiffrement par mot de passe.
Utilise @zip.js/zip.js avec conversion des streams Node.js en Web Streams API via Readable.toWeb et Writable.toWeb.
zippy(files, outputStream, options)— Crée une archive ZIP.filesest un tableau de chemins absolus.optionspeut contenirpassword(string) etzipCrypto(boolean) pour le chiffrement.
Ce module est distribué sous licence MIT.
Ce contenu a été généré par IA