nextalys-node-helpers
v1.7.0
Published
Nextalys Node Helpers
Downloads
6,811
Readme
nextalys-node-helpers
Boîte à outils de helpers Node.js / TypeScript de Nextalys : intégrations cloud (Google Drive, Google Cloud, Firebase), communication (emails, SMS, Slack), fichiers & médias (PDF, images, archives, Excel/CSV/XML), réseau, cryptographie et plus.
Le package est écrit en TypeScript et publié compilé dans dist/ (les déclarations de types .d.ts sont incluses).
Historique des versions : CHANGELOG.md.
Sommaire
Installation
npm install nextalys-node-helpers
# ou
yarn add nextalys-node-helpersLa plupart des intégrations reposent sur des dépendances déjà incluses dans le package. Seul puppeteer est une peer dependency, à installer uniquement si vous utilisez la génération HTML→PDF :
npm install [email protected]Prérequis
- Node.js ≥ 18 (le package est typé avec
@types/node18). - TypeScript recommandé côté consommateur pour profiter des types fournis (utilisable aussi en JavaScript).
- Certaines familles nécessitent des credentials ou des binaires système (compte de service Google/Firebase, clés API SendGrid/Sendinblue/OpenAI, jeton INSEE, binaires
zip/gunzip/7z, Chromium pour Puppeteer…). Les prérequis spécifiques sont indiqués dans chaque section.
Vue d’ensemble
| Domaine | Description |
| --- | --- |
| 🧰 Utilitaires de base | Exécution de commandes shell, manipulation fichiers/dossiers, base64, HTML→texte, newsletters |
| 🌐 Client HTTP | Wrapper fetch : timeout/abort, auth Basic, TLS optionnel, téléchargement en streaming |
| 📧 Emails | Envoi multi-provider (SMTP, Sendinblue/Brevo, SendGrid) + compilation de templates MJML |
| 💬 SMS | Envoi de SMS et de campagnes via Sendinblue |
| 📁 Google Drive | Upload / list / copie / suppression / téléchargement via compte de service |
| ☁️ Google Cloud Vision et Storage | OCR Vision API (texte, tickets de caisse) + buckets et fichiers Cloud Storage |
| 🔥 Firebase | Auth, Firestore, Cloud Messaging (push), Realtime DB, Storage |
| 🔌 FTP, SFTP et SSH | Transferts FTP/SFTP multi-implémentations + exécution de commandes SSH |
| 🗜️ Archives | Création / extraction d’archives zip, gzip, 7z |
| 📄 PDF | HTML→PDF (Puppeteer), fusion/ajout de page (pdf-lib), signature PKCS#12 |
| 🖼️ Images et favicons | Redimensionnement / conversion (sharp, HEIC) et génération de favicons/.ico |
| 📊 Données tabulaires | Excel (exceljs), CSV, XML (fast-xml-parser), templates HTML (handlebars) |
| 🔔 Slack | Envoi de messages via l’API Web Slack ou un webhook entrant |
| 🤖 OpenAI | Chat completions (texte ou JSON) via le SDK openai |
| 🔐 Cryptographie | Chiffrement symétrique AES-256-CBC (module crypto natif) |
| 🛰️ Réseau et API Gouv | IP client derrière proxy + API INSEE Sirene (SIREN/SIRET) |
Imports
Le point d’entrée du package ne ré-exporte qu’une partie des modules. Selon le helper, l’import se fait donc de deux façons :
1. Depuis la racine du package (modules ré-exportés par le point d’entrée) :
import { NodeHelpers, FileHelpers, TextHelpers } from 'nextalys-node-helpers'; // Utilitaires de base
import { NextalysNodeHttpClient } from 'nextalys-node-helpers'; // Client HTTP
import { SmtpMailProvider, SendInBlueMailProvider } from 'nextalys-node-helpers'; // Emails
import { GDriveHelpers } from 'nextalys-node-helpers'; // Google Drive
import { ArchiveManager } from 'nextalys-node-helpers'; // Archives (façade)2. Depuis le sous-chemin compilé dist/ (tous les autres modules : SMS, Firebase, FTP/SSH, PDF, images, données tabulaires, Slack, OpenAI, crypto, réseau, Google Cloud…) :
import { SlackManager } from 'nextalys-node-helpers/dist/helpers/slack/slack-manager';
import { OpenAIHelpers } from 'nextalys-node-helpers/dist/helpers/openai/openai.helpers';Règle générale :
src/helpers/<...>.ts→nextalys-node-helpers/dist/helpers/<...>(sans l’extension). Le chemin d’import exact est rappelé dans chaque exemple ci-dessous.
Modules
Utilitaires de base
Fonctions utilitaires générales pour Node : exécution de commandes shell (exec/spawn), encodage/décodage base64, lecture des versions Node, manipulation de fichiers et de dossiers, conversion HTML vers texte brut, ainsi que des helpers partagés (adresses e-mail, réponses normalisées, envoi de newsletters via un provider).
Exports principaux
NodeHelpers: exécution et utilitaires système.static executeCommand(command: string, options?: ExecuteCommandOptions): Promise<NodeExecResponse>— lance une commande via le moteurexec(défaut) ouspawn.static getHttpContent(url: string): Promise<any>— récupère le corps texte d'une URL.static getNodeVersion(onlyDigit?: number): string | numberstatic base64Encode(str: string)/static base64Decode(b64Encoded: string)
ExecuteCommandOptions: options d'exécution (engine,cwd,env,maxBufferMB,autoSplitArgs,autoLogResponse,useAbortController, ...).FileHelpers: I/O fichiers/dossiers (toutes méthodes statiques).readFile(file, returnString = true, encoding?),writeFile(file, data),appendFile(file, data)copyFile(source, target),copyFolderRecursive(source, target, opts?)fileExists(file),isDirectory(file),getFileInfo(file),getFilesInFolder(directory, opts?),readDirectory(directoryPath, opts?)createDirectory(directory),removeFile(file),removeDirectoryRecursive(directory),renameFile(file, newFileName)base64Encode(filePath, encoding?),base64Decode(base64string, outputPath),base64DecodeToBuffer(base64string)getFileExtension,getMimeTypeFromExtension,getExtensionFromMimeType,getFileNameFromPath,getFileParentFolder,joinPaths(...paths)
TextHelpers.htmlToText(html, opts?)—opts:{ wordwrap?, ignoreHref?, ignoreImage?, preserveNewlines? }(wordwrap par défaut 80).- Helpers partagés :
EmailAddress,SendMailOrSmsResponse<T>(success,data?,error?),NewsletterHelperset ses types (BaseDataNewsletter,BaseNewsletterProvider).
Exemple
import { NodeHelpers, FileHelpers, TextHelpers } from 'nextalys-node-helpers';
async function main() {
// Exécuter une commande shell
const res = await NodeHelpers.executeCommand('node --version', { autoLogResponse: true });
console.log('exitCode:', res.exitCode, 'stdout:', res.stdOutput.trim());
// Version majeure de Node
const major = NodeHelpers.getNodeVersion(1); // ex: 18
// Encodage base64
const encoded = NodeHelpers.base64Encode('hello');
const decoded = NodeHelpers.base64Decode(encoded); // 'hello'
// Manipulation de fichiers
await FileHelpers.createDirectory('/tmp/out');
await FileHelpers.writeFile('/tmp/out/page.html', '<h1>Bonjour</h1><p>Monde</p>');
const html = (await FileHelpers.readFile('/tmp/out/page.html')) as string;
const text = TextHelpers.htmlToText(html, { wordwrap: 100 });
await FileHelpers.writeFile('/tmp/out/page.txt', text);
const mime = FileHelpers.getMimeTypeFromExtension('.txt'); // 'text/plain'
console.log({ major, decoded, mime });
}
main();Prérequis
- Dépendances runtime (déduites du code) :
node-fetch(NodeHelpers.getHttpContent),colors(logs deexecuteCommand),nextalys-js-helpers,fs-extra(FileHelpers),mime-types(helpers MIME),html-to-text(TextHelpers.htmlToText). - Aucune variable d'environnement ni fichier de credentials requis pour cette famille.
Source : src/helpers/
Client HTTP
Client HTTP maison pour Node.js : un wrapper autour de fetch (via node-fetch-native) qui étend NextalysHttpClient. Il gère l'authentification Basic, un timeout configurable avec annulation de requête (AbortController natif, ou implémentation de repli NxsAbortController), le contournement optionnel de la vérification TLS, et le téléchargement de fichiers en streaming.
Exports principaux
NextalysNodeHttpClient— classe principale, étendNextalysHttpClient.request<RequestType, ResponseType, CustomResponseType>(url, method, data?, jsonRequest?, headers?, textResponse = true, returnTextResponseEvenIfJson = false, ignoreTLSReject = false, timeoutInMs = null): effectue une requête ('get' | 'post' | 'put' | 'delete') et renvoie unePromise<NextalysHttpResponse>. Enget,dataest sérialisé en paramètres d'URL ; sinon utilisé comme corps (JSON sijsonRequest).downloadFile(url, output, verbose = false, timeout = null): télécharge l'URL en streaming vers le fichieroutput.
setOptions(options)/verbose— hérités :optionsaccepte{ useBasicAuth?, username?, password?, withCredentials? }.NxsAbortControlleretAbortSignal— implémentation de repli d'abort/timeout utilisée quandglobalThis.AbortControllerest indisponible (usage interne ; ces symboles ne sont pas ré-exportés par le point d'entrée du package).
La réponse est un NextalysHttpResponse exposant success: boolean, data, message: string, code: number | string et res (réponse fetch brute).
Exemple
import { NextalysNodeHttpClient } from 'nextalys-node-helpers';
async function main() {
const httpClient = new NextalysNodeHttpClient();
httpClient.verbose = true;
// Auth Basic optionnelle
httpClient.setOptions({ useBasicAuth: true, username: 'user', password: 'secret' });
// Requête GET JSON avec timeout de 5 s
const res = await httpClient.request<void, { id: number; title: string }>(
'https://jsonplaceholder.typicode.com/todos/1',
'get',
null,
true, // jsonRequest -> parse la réponse en JSON
undefined, // headers
true, // textResponse
false, // returnTextResponseEvenIfJson
false, // ignoreTLSReject
5000, // timeoutInMs
);
if (res.success) {
console.log('Titre :', res.data.title);
} else {
console.error('Echec HTTP', res.code, res.message);
}
// POST JSON
const created = await httpClient.request(
'https://jsonplaceholder.typicode.com/posts',
'post',
{ title: 'foo', body: 'bar', userId: 1 },
true,
);
console.log('Créé :', created.success, created.code);
// Téléchargement de fichier en streaming (timeout 10 s)
const dl = await httpClient.downloadFile(
'https://example.com/image.jpg',
'./image.jpg',
true,
10000,
);
console.log('Fichier :', dl.success ? dl.message : dl.message);
}
main();Prérequis
- Dépendance runtime
node-fetch-native(utilisée comme implémentation defetch). - Dépendance
nextalys-js-helpers: fournit la classe de baseNextalysHttpClientainsi que les typesNextalysHttpResponseetNextalysHttpClientOptions. - Avec
ignoreTLSReject = true, la variable d'environnementNODE_TLS_REJECT_UNAUTHORIZEDest mise à"0"le temps de la requête puis restaurée (désactive la vérification du certificat TLS — à n'utiliser qu'en environnement de confiance).
Source : src/helpers/http-client/
Emails
Abstraction d'envoi d'emails unifiée au-dessus de plusieurs providers (SMTP via nodemailer, Sendinblue/Brevo via sib-api-v3-sdk, SendGrid via @sendgrid/mail). Chaque provider hérite de la classe abstraite BaseMailProvider, qui valide et prépare les données du mail (vérification expéditeur/destinataires/sujet/corps, génération automatique du textBody depuis le HTML) et fournit la gestion des newsletters. Le helper MailTemplateHelpers compile des templates MJML en HTML.
Exports principaux
BaseMailProvider— classe abstraite :sendMail(data: EmailData): Promise<SendMailResponse>,checkAndPrepareMailData(data),sendNewsletter(data: EmailDataNewsletter),createNewsletter(...),getNewsletter(id),debug(...).SmtpMailProvider—new SmtpMailProvider(opts: SmtpMailProviderOptions).SendInBlueMailProvider—new SendInBlueMailProvider(opts: { sendInBlueApiKey: string }), supporte aussicreateOrUpdateContact,addContactToList,createNewsletter,sendExistingNewsletter.SendGridMailProvider—new SendGridMailProvider(opts: SendGridMailProviderOptions)(non ré-exporté par le point d'entrée, voir import via sous-chemindist/).MailTemplateHelpers.compileMjmlToHtml(opts)—static, compile une chaîne ou un fichier MJML vers HTML (non ré-exporté par le point d'entrée).- Types :
EmailData,EmailDataNewsletter,NxsEmailAttachment,SmtpMailProviderOptions,SendInBlueMailProviderOptions,InitMailProviderOptions,SendMailResponse<T>,GetDataResponse<T>,EmailProvider('SMTP' | 'SendInBlue' | 'SendGrid' | 'MailChimp').
Exemple
import {
SmtpMailProvider,
SendInBlueMailProvider,
EmailData,
SendMailResponse,
} from 'nextalys-node-helpers';
// SendGridMailProvider et MailTemplateHelpers ne sont pas ré-exportés par le point d'entrée :
import { SendGridMailProvider } from 'nextalys-node-helpers/dist/helpers/mail/providers/sendgrid-mail-provider';
import { MailTemplateHelpers } from 'nextalys-node-helpers/dist/helpers/mail/mail-template-helpers';
async function main() {
// 1. Compilation d'un template MJML -> HTML
const compiled = await MailTemplateHelpers.compileMjmlToHtml({
inputString: '<mjml><mj-body><mj-section><mj-column><mj-text>Bonjour</mj-text></mj-column></mj-section></mj-body></mjml>',
minify: true,
});
if (compiled.errors.length) {
console.error(compiled.errors);
return;
}
// 2. Données du mail (textBody généré automatiquement depuis htmlBody si absent)
const data: EmailData = {
from: { address: '[email protected]', name: 'Nextalys' },
to: [{ address: '[email protected]', name: 'Jean Dupont' }],
subject: 'Bienvenue',
htmlBody: compiled.html,
};
// 3a. Envoi via SMTP
const smtp = new SmtpMailProvider({
smtpServer: process.env.SMTP_HOST!,
smtpPort: Number(process.env.SMTP_PORT),
smtpUser: process.env.SMTP_USER,
smtpPassword: process.env.SMTP_PASSWORD,
secure: true,
});
const smtpResult: SendMailResponse = await smtp.sendMail(data);
console.log('SMTP success:', smtpResult.success);
// 3b. Envoi via Sendinblue/Brevo
const sib = new SendInBlueMailProvider({ sendInBlueApiKey: process.env.SENDINBLUE_API_KEY! });
const sibResult = await sib.sendMail(data);
console.log('Sendinblue success:', sibResult.success, sibResult.data);
// 3c. Envoi via SendGrid
const sendgrid = new SendGridMailProvider({ apiKey: process.env.SENDGRID_API_KEY! });
const sgResult = await sendgrid.sendMail(data);
console.log('SendGrid success:', sgResult.success);
}
main();Prérequis
- Peer/runtime :
nodemailer(SMTP),sib-api-v3-sdk(Sendinblue),@sendgrid/mail(SendGrid),mjml(templates),html-to-text(génération dutextBody). - Credentials selon le provider :
- SMTP :
smtpServer,smtpPort, etsmtpUser/smtpPassword(ex. viaSMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASSWORD). - Sendinblue/Brevo : clé API passée dans
sendInBlueApiKey(ex.SENDINBLUE_API_KEY). - SendGrid : clé API passée dans
apiKey(ex.SENDGRID_API_KEY).
- SMTP :
Source : src/helpers/mail/
SMS
Abstraction d'envoi de SMS et de campagnes SMS (newsletters) au-dessus de différents providers. La seule implémentation fournie cible Sendinblue via le SDK sib-api-v3-sdk. BaseSmsProvider définit le contrat commun (envoi, création/lancement de campagnes, gestion des listes de contacts) et SendInBlueSmsProvider le réalise.
Exports principaux
SendInBlueSmsProvider— provider concret Sendinblue. Constructeurnew SendInBlueSmsProvider(opts: SendInBlueMailProviderOptions)(l'option clé estsendInBlueApiKey).BaseSmsProvider— classe abstraite :sendSMS(data: SMSData): Promise<SendSmsResponse>,sendNewsletter(data: SMSDataNewsletter),sendNewsletterWithListId(data, listId),createNewsletter(data: BaseDataNewsletterForList),createNewsletterRecipientsList(...),sendExistingNewsletter(newsletterId: string),getNewsletter(id: string): Promise<GetDataResponse>,createNewsletterList(...),checkAndPrepareSmsData(...),debug(...).SMSData—{ to: EmailAddress[]; sender?: string; content: string }.SMSDataNewsletter extends SMSData— ajoutenewsLetterName?,sendOnCreate?,newsLetterListFolder?,tag?,params?,format?: 'json' | 'csv',sendWithFileUrl?,fileUrl?.SendSmsResponse<T = any>— réponse d'envoi (success: boolean,data?: T,error?).GetDataResponse<T = any>—{ success: boolean; data?: T; error?: any }.InitSMSProviderOptions—{ debug?: boolean }.SMSProvider— alias de type'SendInBlue'.
Exemple
import { SendInBlueSmsProvider } from 'nextalys-node-helpers/dist/helpers/sms/providers';
import { SMSData } from 'nextalys-node-helpers/dist/helpers/sms/types';
const smsProvider = new SendInBlueSmsProvider({
sendInBlueApiKey: process.env.SENDINBLUE_API_KEY!,
debug: true,
});
const data: SMSData = {
to: [{ address: '+33600000000', name: 'Jean Dupont' }],
sender: 'MonOffice',
content: 'Votre rendez-vous est confirmé.',
};
const response = await smsProvider.sendSMS(data);
if (response.success) {
console.log('SMS envoyé', response.data);
} else {
console.error('Échec envoi SMS', response.error);
}Prérequis
- Dépendance runtime
sib-api-v3-sdk(utilisée parSendInBlueSmsProvider). - Clé API Sendinblue fournie à l'instanciation via l'option
sendInBlueApiKey(ici lue depuis la variable d'environnementSENDINBLUE_API_KEY).
Source : src/helpers/sms/
Google Drive
Helpers pour piloter Google Drive via un compte de service (authentification JWT googleapis) : lister, uploader, copier, supprimer, télécharger des fichiers et gérer des dossiers. L'authentification est mutualisée par la classe de base BaseGoogleApi, qui accepte soit un couple client_email / private_key, soit un fichier de credentials JSON. Toutes les méthodes de GDriveHelpers sont statiques et appellent init en interne (pas d'instanciation nécessaire).
Exports principaux
GDriveHelpers— classe statique exposant notamment :init(opts: GoogleApiOptions)— initialise l'auth et renvoie le client Drive.listFiles(opts: GDriveListFilesOptions): Promise<GDriveListFilesResponse>— liste parfolder(nom),folderIdou tout.uploadToGoogleDrive(opts: GDriveUploadOptions): Promise<GDriveFileResponse>— upload d'unfile(ou d'unfoldercompressé en .7z).copyGDriveFile(opts: GdriveCopyFileOptions): Promise<GDriveFileResponse>— copie viafileId, avectargetParentId/newNameoptionnels.downloadFile(opts: GDriveGetFileOptions): Promise<void>— téléchargefileIdverstarget.getFileInfo(opts: GDriveGetFileOptions, additionalFields?: GdriveFileField[]): Promise<GDriveFileResponse>.deleteFile,deleteAllFilesInFolder,deleteFilesBeforeDate(opts: GDriveDeleteFileOptions).createFolder/createFolderIfNotExists/getFolderByName(opts: GDriveFolderOptions): Promise<GDriveFileResponse>.searchFilesByName(opts: GDriveSearchFileOptions),findFilesInFolderRecursive(opts: GDriveListFilesRecursiveOptions).getGDriveOptionsFromFilePath(filePath, errors?)/getGDriveOptionsFromArguments(argIndex?, errors?)— chargent les credentials depuis un fichier JSON / un argument CLI.
BaseGoogleApi— classe d'auth :init(opts, debugMode?),authorize(scopes: string[]),getCredentials(loadFullFile?),checkAndMergeOptions(opts).GoogleApiOptions—{ client_email?, private_key?, project_id?, credentialFile?, user?, loadFullFile? }, base de toutes les options.- Types/interfaces :
GDriveMimeType,GdriveFileField,GDriveUploadOptions,GDriveListFilesOptions,GdriveCopyFileOptions,GDriveGetFileOptions,GDriveDeleteFileOptions,GDriveFolderOptions,GDriveSearchFileOptions,GDriveFile,GDriveResponse,GDriveFileResponse,GDriveListFilesResponse,GDriveListFilesRecursiveOptions.
Exemple
import { GDriveHelpers } from 'nextalys-node-helpers';
async function main() {
const auth = {
client_email: '[email protected]',
private_key: process.env.GDRIVE_PRIVATE_KEY!, // clé privée du compte de service
};
// Créer (si besoin) un dossier puis uploader un fichier dedans
const folder = await GDriveHelpers.createFolderIfNotExists({
...auth,
folderName: 'exports',
});
const uploaded = await GDriveHelpers.uploadToGoogleDrive({
...auth,
file: '/tmp/rapport.pdf',
mimeType: 'application/pdf',
targetFolderId: folder.data.id,
targetName: 'rapport.pdf',
});
console.log('Fichier uploadé, id =', uploaded.data.id);
// Lister le contenu du dossier
const list = await GDriveHelpers.listFiles({ ...auth, folderId: folder.data.id });
for (const f of list.data.files) {
console.log(f.name, f.id, f.mimeType);
}
// Copier le fichier sous un nouveau nom
const copy = await GDriveHelpers.copyGDriveFile({
...auth,
fileId: uploaded.data.id,
newName: 'rapport-copie.pdf',
});
console.log('Copie id =', copy.data.id);
}
main().catch(console.error);Alternative : charger les credentials depuis un fichier JSON de compte de service.
import { GDriveHelpers } from 'nextalys-node-helpers';
const files = await GDriveHelpers.listFiles({
credentialFile: '/secrets/service-account.json',
folder: 'exports',
});
console.log(files.data.files);Prérequis
- Dépendance runtime
googleapis(chargée viarequire('googleapis')) etnextalys-js-helpers. - Un compte de service Google avec accès à Drive : fournir
client_email+private_key, ou uncredentialFile(chemin vers le JSON du compte de service). Le scope utilisé esthttps://www.googleapis.com/auth/drive. - Pour l'upload d'un dossier (
opts.folder),ArchiveManagercompresse en.7z: un binaire 7-Zip disponible est requis. L'upload d'un simple fichier (opts.file) n'en a pas besoin.
Source : src/helpers/gdrive/
Google Cloud Vision et Storage
Cette famille fournit deux classes statiques pour interagir avec Google Cloud : GoogleVisionApi pour l'OCR (détection de texte sur image/document via l'API Vision, plus une extraction spécialisée des données de tickets de caisse), et GCloudStorageHelpers pour gérer les buckets et fichiers sur Google Cloud Storage (upload, download, copie, suppression, listing). Les deux s'authentifient via un compte de service Google (client_email, private_key, project_id), soit passé directement, soit chargé depuis un fichier JSON via credentialFile.
Exports principaux
GoogleVisionApi— classe statique d'OCR.GoogleVisionApi.init(opts: GoogleApiOptions): initialise et retourne le clientImageAnnotatorClient.GoogleVisionApi.detextTextInImage(opts: DetectTextInFileOptions): Promise<GoogleTextDetectionResponse>: retourne le texte détecté structuré en blocs/paragraphes/mots.GoogleVisionApi.findDataForShopReceipt(opts): Promise<{ success; total?; date?; shop? }>: extrait montant total, date et enseigne d'un ticket de caisse (Lidl, Carrefour).
DetectTextInFileOptions—{ file: string; mode: 'documentTextDetection' | 'textDetection'; imageBuffer?: Buffer }(hérite deGoogleApiOptions).GoogleTextDetectionResponse—{ blocks: GoogleTextBlock[]; words: string[]; success: boolean }.GCloudStorageHelpers— classe statique de stockage objet.init(opts: GCloudStorageHelpersOptions): obligatoire avant tout appel (sinonError('init before')).getBuckets(),getBucket(bucketName),createBucket(bucketName, location?, storageClass?).listFiles(bucketName, opts?),getFileMeta(bucketName, fileName).uploadFile(bucketName, fileToUpload, targetFolder?, outputFilename?),downloadFile(bucketName, fileName, destFileName),copyFile(bucketName, srcFilename, destFileName),deleteFile(bucketName, fileName).
GCloudStorageHelpersOptions—GoogleApiOptions & { exceptionPropagation?: boolean }(sitrue, les erreurs sont relancées au lieu d'être placées dansresponse.error).- Réponses :
NxsGCloudResponse,NxsGetBucketResponse,NxsGetBucketsResponse,NxsListFilesResponse,NxsGetFileResponse,NxsGetFileMetaResponse.
Exemple
import { GoogleVisionApi } from 'nextalys-node-helpers/dist/helpers/google-vision-api/google-vision-api';
import { GCloudStorageHelpers } from 'nextalys-node-helpers/dist/helpers/gcloud-storage/gcloud-storage-helpers';
import { GoogleApiOptions } from 'nextalys-node-helpers';
// Credentials du compte de service (peuvent aussi être chargés via { credentialFile: '/chemin/sa.json' })
const opts: GoogleApiOptions = {
client_email: process.env.GCLOUD_CLIENT_EMAIL,
private_key: process.env.GCLOUD_PRIVATE_KEY,
project_id: process.env.GCLOUD_PROJECT_ID,
};
async function run() {
// 1) OCR : détection de texte sur une image locale
const result = await GoogleVisionApi.detextTextInImage({
...opts,
file: './test/sample1.jpeg',
mode: 'documentTextDetection',
});
if (result.success) {
console.log('Mots détectés :', result.words);
console.log('Nombre de blocs :', result.blocks.length);
}
// Extraction des données d'un ticket de caisse
const receipt = await GoogleVisionApi.findDataForShopReceipt({
...opts,
file: './test/sample2.jpeg',
mode: 'documentTextDetection',
});
if (receipt.success) {
console.log(`Enseigne=${receipt.shop} Total=${receipt.total} Date=${receipt.date}`);
}
// 2) Stockage : init obligatoire puis upload / listing
await GCloudStorageHelpers.init({ ...opts, exceptionPropagation: false });
const upload = await GCloudStorageHelpers.uploadFile(
'mon-bucket',
'./test/sample1.jpeg',
'receipts', // dossier cible (optionnel)
'ticket-001.jpeg', // nom de sortie (optionnel)
);
console.log('Upload réussi :', upload.success);
const list = await GCloudStorageHelpers.listFiles('mon-bucket', { prefix: 'receipts/' });
console.log('Fichiers :', list.files?.map(f => f.name));
await GCloudStorageHelpers.downloadFile('mon-bucket', 'receipts/ticket-001.jpeg', './out/ticket-001.jpeg');
}
run();Prérequis
- Dépendances runtime :
@google-cloud/vision(^2.3.0),@google-cloud/storage(^5.8.5),googleapis(42.0.0),nextalys-js-helpers(1.0.27). - Credentials d'un compte de service Google avec les droits Vision API et Storage :
client_email,private_key,project_id. Ils sont passés via les options, ou chargés depuis un fichier JSON en renseignantcredentialFile(leprivate_key/client_email/project_idsont alors lus dans ce fichier). - L'API Cloud Vision et l'API Cloud Storage doivent être activées sur le projet GCP.
GCloudStorageHelpers.init(...)doit être appelé avant toute autre méthode (lèveError('init before')sinon).
Source : src/helpers/
Firebase
Ensemble de managers statiques au-dessus de firebase-admin couvrant l'authentification, Firestore, Cloud Messaging (push), la Realtime Database et le Storage. Tous partagent une initialisation centralisée via FirebaseCommonManager : il suffit d'initialiser une fois (avec un compte de service), puis chaque manager réutilise l'app Firebase initialisée. Les managers Firestore, Messaging et Realtime DB exposent en plus une méthode init(opts) qui délègue simplement à l'initialisation commune (FirebaseAuthManager et FirebaseStorageManager, eux, n'en exposent pas).
Exports principaux
FirebaseCommonManager— initialisation et état partagés :static init(opts: FirebaseManagerOptions),static beforeQuery(),static deleteApp(), ainsi quefirebaseApp,initialized,initializing,options.FirebaseManagerOptions— options d'init :{ certFilePath?, certFileContent?, databaseURL?, debug?, logger?, storageBucket? }.AbstractLogger—{ log, error, warn }, injectable viaoptions.logger.FirebaseAuthManager—deleteUser(userId),getUser(userId),changeUserPassword(userId, newPassword).FirebaseFirestoreManager—updateDoc<T>(path, value: Partial<T>),setDoc<T>(path, value: T),removeDoc(path),getDocOnce<T>(path, idField?),getCollectionOnce<T>(path, whereData?, limit?, start?, idField?),getAllCollections(),backupFullDatabase(output?).FirebaseMessagingManager—sendPush<T>(tokens, notification, data?, opts?): Promise<SendPushResponse>,sendPushToEveryone<T>(notification, data?): Promise<string>.FirebaseRealtimeDbManager—updateRef,setRef,removeRef,getOnce<T>(path),getRef(path),backupFullDatabase(output?).FirebaseStorageManager—uploadFile(filePath, mimeType, destination, storageBucket?),listFolderFiles(folder, storageBucket?),deleteFile(file, storageBucket?),deleteFolder(folder, storageBucket?).- Types de messaging :
NotificationMessagePayload,NotificationMessageOptions,SendPushResponse,NxsMessagingDeviceResult,NxsFirebaseError.
Exemple
import { FirebaseCommonManager } from 'nextalys-node-helpers/dist/helpers/firebase/firebase-common-manager';
import { FirebaseFirestoreManager } from 'nextalys-node-helpers/dist/helpers/firebase/firebase-firestore-manager';
import { FirebaseAuthManager } from 'nextalys-node-helpers/dist/helpers/firebase/firebase-auth-manager';
import { FirebaseMessagingManager } from 'nextalys-node-helpers/dist/helpers/firebase/firebase-messaging-manager';
import { FirebaseStorageManager } from 'nextalys-node-helpers/dist/helpers/firebase/firebase-storage-manager';
interface User {
id?: string;
name: string;
pushToken: string;
}
async function main() {
// Initialisation unique (réutilisée par tous les managers)
await FirebaseCommonManager.init({
certFilePath: './service-account.json',
databaseURL: 'https://mon-projet.firebaseio.com',
storageBucket: 'mon-projet.appspot.com',
debug: true,
logger: console,
});
// Firestore
await FirebaseFirestoreManager.setDoc<User>('users/abc123', {
name: 'Alice',
pushToken: 'fcm-token-xxx',
});
const user = await FirebaseFirestoreManager.getDocOnce<User>('users/abc123', 'id');
const actifs = await FirebaseFirestoreManager.getCollectionOnce<User>(
'users',
{ field: 'name', operator: '==', value: 'Alice' },
10,
undefined,
'id',
);
// Auth
await FirebaseAuthManager.changeUserPassword('abc123', 'nouveauMotDePasse!');
// Push notification
if (user?.pushToken) {
const res = await FirebaseMessagingManager.sendPush(
[user.pushToken],
{ title: 'Bonjour', body: 'Vous avez un nouveau message', click_action: 'FCM_PLUGIN_ACTIVITY' },
{ screen: 'inbox' },
{ priority: 'high', dryRun: false },
);
console.log('Succès:', res.successCount, 'Échecs:', res.failureCount);
}
// Storage
await FirebaseStorageManager.uploadFile('./photo.jpg', 'image/jpeg', 'avatars/abc123.jpg');
await FirebaseCommonManager.deleteApp();
}
main();Prérequis
- Dépendance runtime
firebase-admin(^9.2.0). - Un compte de service Firebase : fournir soit
certFilePath(chemin vers le JSON du service account), soitcertFileContent(objet JSON déjà chargé). L'init échoue si aucun des deux n'est fourni. databaseURLobligatoire pour utiliserFirebaseRealtimeDbManager.storageBucketrecommandé dans les options pourFirebaseStorageManager(sinon le passer en argumentstorageBucketà chaque appel).nextalys-js-helpers(utilisé en interne par les managers Firestore et Realtime DB pourbackupFullDatabase).
Source : src/helpers/firebase/
FTP, SFTP et SSH
Manager FTP/SFTP statique (FtpManager) reposant sur un système d'implémentations interchangeables (simple, legacy, deploy, sftp, basic), chacune s'appuyant sur une bibliothèque native dédiée. Un SshManager statique complète la famille en permettant d'exécuter des commandes shell sur un hôte distant via SSH. Toutes les opérations FTP renvoient un FtpResponse<T> ({ success, data?, error? }) plutôt que de lever une exception.
Exports principaux
FtpManager— classe statique.init(providerType: FtpProvider, options: FtpOptions)instancie l'implémentation choisie ; puispublishFolder(source, dest, include?, exclude?, deleteRemote?),uploadFile(source, dest),downloadFolder(source, dest),downloadFile(source, dest),list(path?).FtpProvider—'simple' | 'legacy' | 'deploy' | 'sftp' | 'basic'.FtpOptions—{ host, port, user, password, secure?, secureOptions?, verbose?, sftp? }.FtpResponse<T>—{ success: boolean; data?: T; error?: any }.FtpFileInfo— métadonnées d'un fichier distant (name,type,size, ...).FtpClientBase— classe abstraite de base ; implémentations concrètes :FtpClientSftp,FtpClientBasic,FtpClientSimple,FtpClientDeploy,FtpClientLegacy.SshManager— classe statique.init(options: SshOptions)puisexecuteCommand(command: string, cwd: string, prefixCommand?: string).SshOptions—{ user, password, host }.
Note : selon l'implémentation, certaines méthodes ne sont pas disponibles (elles lèvent Method not implemented.). Par exemple publishFolder n'est implémentée que par le provider deploy, uploadFile/downloadFile/list par sftp, et downloadFolder par legacy.
Exemple
import { FtpManager } from 'nextalys-node-helpers/dist/helpers/ftp/ftp-manager';
import { SshManager } from 'nextalys-node-helpers/dist/helpers/ssh/ssh-manager';
// --- Transfert SFTP (provider 'sftp', basé sur ssh2-sftp-client) ---
FtpManager.init('sftp', {
host: 'sftp.example.com',
port: 22,
user: 'deploy',
password: process.env.SFTP_PASSWORD!,
});
const upload = await FtpManager.uploadFile('./build/app.zip', '/var/www/app.zip');
if (!upload.success) {
console.error('Échec upload SFTP', upload.error);
}
const listing = await FtpManager.list('/var/www');
if (listing.success) {
listing.data?.forEach(f => console.log(f.name));
}
// --- Déploiement complet d'un dossier (provider 'deploy', basé sur ftp-deploy) ---
FtpManager.init('deploy', {
host: 'ftp.example.com',
port: 21,
user: 'web',
password: process.env.FTP_PASSWORD!,
});
await FtpManager.publishFolder(
'./dist', // source locale
'/public_html', // destination distante
['*', '**/*'], // include
['**/*.map'], // exclude
false, // deleteRemote
);
// --- Exécution d'une commande distante via SSH ---
SshManager.init({
host: 'app.example.com',
user: 'root',
password: process.env.SSH_PASSWORD!,
});
await SshManager.executeCommand('npm run migrate', '/var/www/app', 'source ~/.bashrc');Prérequis
- Peer deps à installer selon le provider FTP utilisé :
basic-ftp(basic),ftp(simple),ftp-client(legacy),ftp-deploy(deploy),ssh2-sftp-client(sftp). node-sshrequis pourSshManager.- Aucune variable d'environnement n'est lue par le code : les identifiants (
host,user,password,port) sont passés explicitement àinit(). L'exemple ci-dessus utiliseprocess.env.*par simple convention de bonne pratique.
Source : src/helpers/ftp/
Archives
Création et extraction d'archives zip, gzip et 7z via une interface commune IArchiveManager. La façade statique ArchiveManager sélectionne l'implémentation à l'exécution (init) puis délègue toutes les opérations au gestionnaire choisi. Les backends Zip et GZip reposent sur les binaires système (zip, gunzip) appelés via NodeHelpers.executeCommand, tandis que le backend SevenZip utilise la librairie node-7z.
Exports principaux
ArchiveManager— façade statique (seul symbole de cette famille ré-exporté par la racine du package). À initialiser une fois avecArchiveManager.init('Zip' | 'SevenZip' | 'GZip').static createArchiveFromFolder(folder: string, output?: string, noZipParentFolder?: boolean): Promise<string>static createArchiveFromFolders(output: string, folders: string[], cwd?: string): Promise<string>static createArchiveFromFiles(output: string, files: string[]): Promise<string>static addFileToArchive(file: string, archive: string): Promise<string>static extractArchive(archive: string, output: string): Promise<void>static removeFileFromArchive(archive: string, fileToRemove: string): Promise<void>static init(managerType: 'Zip' | 'SevenZip' | 'GZip'): voidetstatic checkManager(): boolean
IArchiveManager— interface implémentée par chaque backend.ZipArchiveManager,GZipArchiveManager,SevenZipArchiveManager— implémentations concrètes (instanciables directement si besoin de contourner la façade).
Remarque sur les imports : la racine
'nextalys-node-helpers'ne ré-exporte que la classeArchiveManager. L'interfaceIArchiveManageret les trois classes de backend ne sont pas exposées par la racine ; pour les utiliser directement il faut les importer depuis les sous-chemins compilés, par exemple :import { ZipArchiveManager } from 'nextalys-node-helpers/dist/helpers/archive-manager/zip-archive-manager'; import { IArchiveManager } from 'nextalys-node-helpers/dist/helpers/archive-manager/archive-manager-interface';
Remarque sur le comportement : toutes les méthodes de la façade vérifient au préalable que
init()a été appelé (viacheckManager(), sinon log d'erreur et retournull). Certaines opérations ne sont pas implémentées selon le backend (ex.extractArchivepour Zip et SevenZip,removeFileFromArchive/addFileToArchive/createArchiveFromFolder/createArchiveFromFolders/createArchiveFromFilespour GZip) et renvoient alorsnull.
Exemple
import { ArchiveManager } from 'nextalys-node-helpers';
async function main() {
// 1. Choisir le backend (zip via binaire système)
ArchiveManager.init('Zip');
// 2. Créer une archive à partir d'un dossier
// output déduit automatiquement si non fourni : <parent>/<nomDossier>.zip
const archive = await ArchiveManager.createArchiveFromFolder(
'/data/rapports', // dossier à archiver
'/data/rapports.zip', // chemin de sortie (optionnel)
false // false => le dossier lui-même est conservé comme entrée racine dans l'archive
);
console.log('Archive créée :', archive);
// 3. Ajouter un fichier à une archive existante
await ArchiveManager.addFileToArchive('/data/annexe.pdf', '/data/rapports.zip');
// 4. Archiver plusieurs dossiers d'un coup
await ArchiveManager.createArchiveFromFolders(
'/data/lot.zip',
['/data/janvier', '/data/fevrier']
);
// 5. Retirer un fichier de l'archive
await ArchiveManager.removeFileFromArchive('/data/rapports.zip', 'annexe.pdf');
}
main();Prérequis
- Backend
Zip: binairezipdisponible dans lePATH(utilisé viazip -r,zip -ur,zip -d). - Backend
GZip: binairegunzipdisponible dans lePATH(seule la méthodeextractArchiveest implémentée, viagunzip -c <archive> > <output>). - Backend
SevenZip: dépendance npmnode-7z(^1.1.0) et binaire7z/7zaaccessible dans lePATH. - Aucune variable d'environnement ni fichier de credentials requis.
Source : src/helpers/archive-manager/
Famille d'utilitaires pour la production et le traitement de fichiers PDF : génération HTML→PDF via Puppeteer, manipulation (fusion, ajout de page) via pdf-lib, et signature électronique PKCS#12 via node-forge. Ces modules ne sont pas ré-exportés depuis le point d'entrée du package : importez-les depuis leurs sous-chemins compilés dist/.
Depuis la v1.1.0,
PDFHelpersréutilise un navigateur Chromium partagé (singleton) entre les appels (optionreuseBrowser, activée par défaut) au lieu d'en relancer un à chaque PDF. Pensez à appelerPDFHelpers.closeBrowser()à l'arrêt de l'application pour libérer le process. Le défaut dewaitUntilest désormais'load'(et non plus'networkidle0'). Ces évolutions sont rétro-compatibles — voir le CHANGELOG.
Exports principaux
PDFHelpers.HtmlToPDF(input, output, opts?, debug?)— convertit une URL, un fichier HTML (inputIsFile) ou une chaîne HTML (inputIsHtml) en PDF écrit suroutput.opts.formatvaut'a4'par défaut.PDFHelpers.HtmlToPdfFromTemplate(htmlTemplate, data, output, removeHtmlFile?, opts?, debug?)— remplit un template HTML avecdatapuis le rend en PDF ; renvoie{ success, error }.PDFHelpers.closeBrowser(): Promise<void>— ferme proprement le navigateur partagé. À appeler à l'arrêt de l'application (ex.onModuleDestroysous NestJS).GeneratePdfOptions— interface :inputIsUrl/inputIsFile/inputIsHtml,format: NxsPDFFormat(défaut'a4'),browserPdfOptions: PDFOptions,launchOptions: LaunchOptions,headless: boolean | 'shell',noSandbox,disableGpu(headless/noSandbox/disableGpuactifs par défaut ;'shell'utilisechrome-headless-shell, plus léger),reuseBrowser(réutilise le navigateur partagé ; défauttrue),waitUntil(événement de cycle de vie attendu au chargement ; défaut'load').NxsPDFFormat— type :'letter' | 'legal' | 'tabloid' | 'ledger' | 'a0' | … | 'a6'.PdfLibHelpers.mergePdf(pdfFiles: Buffer[]): Promise<Buffer>— fusionne plusieurs PDF en un seulBuffer.PdfLibHelpers.addPdfPage(pdfFile: string | Buffer, opts?: { output?: string }): Promise<Buffer>— ajoute une page vierge ; écrit le résultat siopts.outputest fourni.SignPdfHelpers.sign(pdfInput, p12Cert, additionalOptions?): Promise<Buffer | null>— signe un PDF (chemin ouBuffer) avec un certificat PKCS#12 ; options :passphrase,asn1StrictParsing,addPlaceholder.SignPdfError/SignPdfErrorType— erreur typée de la signature (TYPE_INPUT,TYPE_PARSE, …).
Exemple
import { PDFHelpers } from 'nextalys-node-helpers/dist/helpers/pdf/pdf-helpers';
import { PdfLibHelpers } from 'nextalys-node-helpers/dist/helpers/pdf-lib/pdf-lib.helpers';
import { SignPdfHelpers } from 'nextalys-node-helpers/dist/helpers/sign-pdf/sign-pdf.helpers';
import { promises as fs } from 'fs';
async function main() {
// 1. HTML -> PDF (chaine HTML brute)
await PDFHelpers.HtmlToPDF(
'<h1>Facture</h1><p>Montant : 1 200 EUR</p>',
'/tmp/facture.pdf',
{ inputIsHtml: true, format: 'a4' },
);
// 2. Fusion de plusieurs PDF
const [a, b] = await Promise.all([
fs.readFile('/tmp/facture.pdf'),
fs.readFile('/tmp/conditions.pdf'),
]);
const merged = await PdfLibHelpers.mergePdf([a, b]);
await fs.writeFile('/tmp/dossier.pdf', merged);
// 3. Signature PKCS#12 (avec ajout du placeholder de signature)
const signed = await SignPdfHelpers.sign(
'/tmp/dossier.pdf',
'/secure/certificat.p12',
{ passphrase: process.env.P12_PASSPHRASE, addPlaceholder: true },
);
if (signed) {
await fs.writeFile('/tmp/dossier-signe.pdf', signed);
}
}
main()
.catch(console.error)
// Le navigateur Chromium est partagé entre les appels : on le ferme au shutdown.
.finally(() => PDFHelpers.closeBrowser());Prérequis
puppeteer(peer dependency, version24.15.0) installé pourPDFHelpers; un environnement Chromium fonctionnel (les options--no-sandbox,--disable-gpuet--disable-dev-shm-usagesont ajoutées par défaut — cette dernière évite les crashs Chromium en conteneur).- Le navigateur Chromium étant réutilisé entre les appels, appelez
PDFHelpers.closeBrowser()à l'arrêt de l'application pour libérer le process (ou passezreuseBrowser: falsepour relancer un navigateur dédié à chaque appel). pdf-lib(^1.17.1) pourPdfLibHelpers.node-forge(^1.3.1) pourSignPdfHelpers.- Pour la signature : un certificat PKCS#12 (
.p12/.pfx) et sa passphrase (ex. viaP12_PASSPHRASE).
Source : src/helpers/pdf/
Images et favicons
Traitement d'images basé sur sharp : redimensionnement, conversion de format (png/jpeg/webp), récupération des métadonnées et conversion HEIC optionnelle via heic-convert. La génération de favicons produit plusieurs tailles PNG et un fichier favicon.ico (via to-ico).
Ces modules ne sont pas ré-exportés par le point d'entrée du package : importez-les depuis leurs sous-chemins compilés.
Exports principaux
ImageHelpers— classe statique de traitement d'images.ImageHelpers.resizeImage(input, options, output?)— redimensionne ; retourne unBuffersioptions.toBufferest vrai, sinon écrit dansoutput.ImageHelpers.convertImage(input, options)— convertit versoptions.outFormat('png' | 'jpeg' | 'webp' | 'jpg') et écrit dansoptions.output.ImageHelpers.getImageInfo(input)— retourne les métadonnées (width,height).
ResizeImageOptions—width?,height?,fit?,position?,toBuffer?,tryConvertHeic?, pluswebPOptions/jpegOptions/pngOptions.ConvertImageOptions—outFormat,output,quality?,tryConvertHeic?, plus les mêmes options par format.SharpImageGenerationResponse—{ format, width, height, channels, size }.FavIconGenerator.generateFavicons(originalFile, sizes)— génère un PNG par taille demandée dans un dossieroutput/(relatif au module), et unfavicon.icolorsque la largeur 32 est présente.
Exemple
import { ImageHelpers, ConvertImageOptions } from 'nextalys-node-helpers/dist/helpers/image-helpers/image.helpers';
import { FavIconGenerator } from 'nextalys-node-helpers/dist/helpers/favicon/favicon-generator';
async function main() {
// Redimensionnement vers un fichier
await ImageHelpers.resizeImage(
'./photo.jpg',
{ width: 800, height: 600, fit: 'cover' },
'./photo-800x600.jpg',
);
// Redimensionnement en mémoire (Buffer)
const buffer = await ImageHelpers.resizeImage('./photo.jpg', { width: 200, toBuffer: true });
// Conversion de format avec qualité
const convertOptions: ConvertImageOptions = {
outFormat: 'webp',
output: './photo.webp',
quality: 80,
};
await ImageHelpers.convertImage('./photo.jpg', convertOptions);
// Conversion HEIC -> JPEG (nécessite tryConvertHeic + un fichier .heic)
await ImageHelpers.convertImage('./photo.heic', {
outFormat: 'jpeg',
output: './photo.jpeg',
tryConvertHeic: true,
jpegOptions: { quality: 90 },
});
// Métadonnées
const info = await ImageHelpers.getImageInfo('./photo.jpg');
console.log(info.width, info.height);
// Génération de favicons (favicon.ico produit pour la taille 32)
await FavIconGenerator.generateFavicons('./logo.png', [
{ width: 16, height: 16 },
{ width: 32, height: 32 },
{ width: 180, height: 180 },
]);
}
main();Prérequis
sharp(0.31.3) — moteur de traitement d'images.heic-convert(2.1.0) — requis uniquement pour la conversion HEIC (optiontryConvertHeicsur un fichier.heic).to-ico(^1.1.5) — requis pour la génération dufavicon.ico.
Source : src/helpers/image-helpers/
Données tabulaires
Cette famille regroupe les helpers de lecture et d'écriture de formats tabulaires et documentaires : Excel via exceljs (ExcelHelpersExcelJs), CSV en flux avec détection d'encodage (CsvHelpers), XML via fast-xml-parser (XmlHelpers) et génération HTML par templates Handlebars (HtmlHelpers). Tous ces modules sont des sous-chemins compilés (non ré-exportés par le point d'entrée du package).
Exports principaux
ExcelHelpersExcelJs— étendExcelHelpersBrowserExcelJs. Méthodes d'instanceasync getExcelWorksheet(file: string, opts: GetExcelWorksheetOptions),async getExcelWorksheetContent(file: string, opts: GetExcelWorksheetContentOptions): Promise<any[][]>etasync generateExcel(options: NxsGenerateExcelOptions): Promise<string | Excel.Buffer>. Les options proviennent denextalys-js-helpers/dist/excel.CsvHelpers—static readFile(file: string, delimiter = ','): Promise<{ success: boolean; data: any[]; error?: any }>. Lit le fichier en flux, détecte l'encodage et parse nombres/booléens.XmlHelpers—static parseXmlString(xmlString: string): anyetstatic xmlFileToJsObject(xmlFile: string): Promise<any>.HtmlHelpers—static registerHandleBarsHelpers(helpers: HandleBarsHelperType[]),static registerHandlebarsHelper(name, handler),static fillHtml(htmlTemplate, data, outputHtmlFile, returnHtmlContent, debug?)etstatic fillHtmlFromHtmlTemplateString(...).HandleBarsHelperType— type des helpers Handlebars intégrés :'math' | 'formatDate' | 'formatPrice' | 'round' | 'ifEquals' | 'padNumber' | 'addMonthsToDate' | 'formatPriceWithDecimals'.
Exemple
import { ExcelHelpersExcelJs } from 'nextalys-node-helpers/dist/helpers/excel-helpers/impl/excel-helpers-exceljs';
import { CsvHelpers } from 'nextalys-node-helpers/dist/helpers/csv/csv-helpers';
import { XmlHelpers } from 'nextalys-node-helpers/dist/helpers/xml/xml.helpers';
import { HtmlHelpers } from 'nextalys-node-helpers/dist/helpers/html-helpers/html-helpers';
async function main() {
// Excel : lecture du contenu d'une feuille (matrice de cellules)
const excel = new ExcelHelpersExcelJs();
const content = await excel.getExcelWorksheetContent('./data/clients.xlsx', {
worksheetIndex: 0,
getCellFieldName: 'text',
onlyColumns: [1, 2, 3],
});
console.log('Lignes lues :', content.length);
// Excel : génération d'un classeur
await excel.generateExcel({
output: './out/export.xlsx',
worksheetName: 'Export',
data: [
['Nom', 'Montant'],
['Dupont', 1200],
],
});
// CSV : lecture avec détection d'encodage
const csv = await CsvHelpers.readFile('./data/import.csv', ';');
if (csv.success) {
console.log('Lignes CSV :', csv.data.length);
}
// XML : fichier vers objet JS
const obj = await XmlHelpers.xmlFileToJsObject('./data/facture.xml');
console.log(obj);
// HTML : enregistrement de helpers puis remplissage d'un template
HtmlHelpers.registerHandleBarsHelpers(['formatPrice', 'formatDate']);
const html = await HtmlHelpers.fillHtml(
'./templates/facture.hbs',
{ client: 'Dupont', total: 1200, date: new Date() },
'./out/facture.html',
true, // returnHtmlContent
);
console.log(html.length);
}
main();Prérequis
- Dépendances runtime :
exceljs,csv-reader,autodetect-decoder-stream,fast-xml-parser,handlebars. nextalys-js-helpers(classe de baseExcelHelpersBrowserExcelJset typesGetExcelWorksheetOptions,GetExcelWorksheetContentOptions,NxsGenerateExcelOptions).- Aucune variable d'environnement ni fichier de credentials requis.
Source : src/helpers/
Slack
Envoi de messages Slack via la classe statique SlackManager. Deux modes sont disponibles : l'API Web officielle (@slack/web-api) authentifiée par token, ou un webhook entrant Slack.
Exports principaux
SlackManager— classe avec uniquement des membres statiques.static init(token: string): void— initialise leWebClientinterne avec un token Slack. À appeler avantsendMessage.static sendMessage(message: string, channel: string, opts?: { channel?: string }): Promise<...>— poste un message texte dans un canal viachat.postMessage. Lève une erreur siinitn'a pas été appelé.static sendMessageWithWebhook(message: string, webhook: string, opts?: { username?: string; icon_emoji?: string; attachments?: { color: string; fields: { title: string; value: string; short: boolean }[] }[] }): Promise<...>— envoie un message via un webhook entrant Slack (aucune initialisation requise).
Exemple
import { SlackManager } from 'nextalys-node-helpers/dist/helpers/slack/slack-manager';
async function main() {
// Mode API Web : initialiser une seule fois avec le token de bot
SlackManager.init(process.env.SLACK_TOKEN as string);
await SlackManager.sendMessage('Déploiement terminé', '#general');
// Mode webhook entrant : pas d'init nécessaire
await SlackManager.sendMessageWithWebhook(
'Alerte production',
process.env.SLACK_WEBHOOK_URL as string,
{
username: 'CI Bot',
icon_emoji: ':rotating_light:',
attachments: [
{
color: '#ff0000',
fields: [
{ title: 'Service', value: 'api', short: true },
{ title: 'Statut', value: 'down', short: true },
],
},
],
},
);
}
main();Prérequis
- Dépendance runtime
@slack/web-api(utilisée parinit/sendMessage). - Un token Slack (Bot OAuth token), typiquement fourni via une variable d'environnement (ex.
SLACK_TOKEN), pour le mode API Web. - Une URL de webhook entrant Slack (ex.
SLACK_WEBHOOK_URL) poursendMessageWithWebhook.
Source : src/helpers/slack/
OpenAI
Helpers autour du SDK openai pour appeler l'API de chat completions. La classe statique OpenAIHelpers doit d'abord être initialisée avec une clé API, puis expose une méthode pour obtenir une complétion (texte brut ou objet JSON parsé).
Exports principaux
OpenAIHelpers: classe statique encapsulant un client OpenAI.OpenAIHelpers.init(apiKey: string): void— enregistre la clé API utilisée pour les appels.OpenAIHelpers.chatCompletion(input: string, json?: boolean, model?: ChatAPI.ChatModel)— envoieinputcomme messageuseret retourne{ success, message, error, jsonData? }. Sijsonvauttrue, leresponse_formatjson_objectest appliqué et la réponse est parsée dansjsonData. Le modèle par défaut est'gpt-4o'.
Exemple
import { OpenAIHelpers } from 'nextalys-node-helpers/dist/helpers/openai/openai.helpers';
async function main() {
OpenAIHelpers.init(process.env.OPENAI_API_KEY!);
// Complétion texte simple
const res = await OpenAIHelpers.chatCompletion('Dis bonjour en une phrase.');
if (res.success) {
console.log(res.message);
} else {
console.error(res.error);
}
// Complétion JSON avec un modèle spécifique
const jsonRes = await OpenAIHelpers.chatCompletion(
'Donne un objet JSON avec les champs nom et ville pour une personne fictive.',
true,
'gpt-4o-mini',
);
if (jsonRes.success) {
console.log(jsonRes.jsonData);
}
}
main();Prérequis
- Dépendance runtime :
openai(^4.53.1). - Une clé API OpenAI valide, fournie via
OpenAIHelpers.init(apiKey)(typiquement depuisprocess.env.OPENAI_API_KEY).
Source : src/helpers/openai/
Cryptographie
Chiffrement symétrique de chaînes de caractères basé sur le module natif crypto de Node.js (AES-256-CBC par défaut). La classe CryptoHelpers est entièrement statique : on l'initialise une fois avec une clé, puis on chiffre/déchiffre. Le format de sortie est iv:payload (hexadécimal), réutilisable tel quel pour le déchiffrement.
Exports principaux
CryptoHelpers— classe statique (pas d'instanciation).CryptoHelpers.init(opts?: { algorithm?: string; key?: string; iv?: string })— configure l'algorithme (défaut'aes-256-cbc') et la clé. Si non appelée, une initialisation par défaut (clé aléatoire) est effectuée automatiquement au premierencrypt/decrypt.CryptoHelpers.encrypt(str: string, key?: string)— renvoie un objet{ iv, encryptedPayload, key, encryptedString };encryptedString(au formativ:payload) est la valeur à conserver.CryptoHelpers.decrypt(textToDecrypt: string, key?: string): string— déchiffre une chaîne au formativ:payloadet renvoie le texte clair.
Note : avec l'algorithme par défaut aes-256-cbc, la clé doit faire 32 octets (par ex. une chaîne de 32 caractères ASCII).
Exemple
import { CryptoHelpers } from 'nextalys-node-helpers/dist/helpers/crypto/crypto-helpers';
// Initialisation avec une clé 32 octets (AES-256-CBC)
CryptoHelpers.init({ key: '84216be76b24a108185eda4cfdd14c51' });
// Chiffrement
const result = CryptoHelpers.encrypt('test12345');
console.log(result.encryptedString); // ex: "d9f34eac...:793202a8..."
// Déchiffrement (à partir de encryptedString au format "iv:payload")
const clair = CryptoHelpers.decrypt(result.encryptedString);
console.log(clair); // "test12345"Prérequis
- Aucune dépendance externe ni variable d'environnement : repose uniquement sur le module natif
cryptode Node.js. - La clé fournie à
init(ou àencrypt/decrypt) doit avoir une longueur compatible avec l'algorithme choisi (32 octets pouraes-256-cbc).
Source : src/helpers/crypto/
Réseau et API Gouv
Helpers réseau et accès à l'API entreprise du gouvernement français. NetworkHelpers détermine l'adresse IP réelle d'un client à partir d'une requête HTTP (gestion des en-têtes de proxys/load-balancers : x-forwarded-for, Cloudflare, AWS, etc.). GouvEntreprise interroge l'API INSEE Sirene (https://api.insee.fr/entreprises) pour récupérer unités légales et établissements à partir d'un SIREN.
Exports principaux
NetworkHelpers.getClientIp(req: any): string | null— extrait l'IP du client en parcourant les en-têtes connus (x-client-ip,x-forwarded-for,cf-connecting-ip,x-real-ip...) puisreq.connection/req.socket/req.requestContext.NetworkHelpers.isLocalRequest(req: any): boolean— vrai si l'IP résolue contient127.0.0.1.GouvEntreprise.init(jwtToken: string): void— enregistre le jeton Bearer utilisé par les appels suivants (à appeler avant tout).GouvEntreprise.getUnitesLegales(siren: string)—GET /sirene/V3/siren?q=siren:<siren>, renvoie uneNextalysHttpResponse<GetSirenResponse>.GouvEntreprise.getEtablissements(siren: string)—GET /sirene/V3/siret?q=siren:<siren>, renvoie uneNextalysHttpResponse<GetEtablissementsResponse>.- Interfaces de typage des réponses :
GetSirenResponse,GetEtablissementsResponse,UnitesLegale,Etablissement,EtablissementAdresse,Header...
Exemple
import { NetworkHelpers } from 'nextalys-node-helpers/dist/helpers/network-helpers/network-helpers';
import { GouvEntreprise } from 'nextalys-node-helpers/dist/helpers/gouv-entreprise/gouv-entreprise.helpers';
// Résolution de l'IP client (ex. dans un handler Express)
function handler(req: any) {
const ip = NetworkHelpers.getClientIp(req);
console.log('IP client :', ip);
if (NetworkHelpers.isLocalRequest(req)) {
console.log('Requête locale');
}
}
// Interrogation de l'API INSEE Sirene
async function lookupEntreprise() {
// Le jeton JWT INSEE doit être fourni avant tout appel
GouvEntreprise.init(process.env.INSEE_JWT_TOKEN!);
const siren = '130025265';
const unites = await GouvEntreprise.getUnitesLegales(siren);
if (unites.success) {
console.log('Unités légales :', unites.data?.unitesLegales);
} else {
console.error('Erreur API :', unites.code, unites.message);
}
const etabs = await GouvEntreprise.getEtablissements(siren);
if (etabs.success) {
console.log('Établissements :', etabs.data?.etablissements);
}
}Prérequis
- Un jeton JWT valide pour l'API INSEE Sirene (
api.insee.fr), passé àGouvEntreprise.init()(ex. viaprocess.env.INSEE_JWT_TOKEN) avant tout appel — sinon le headerAuthorization: Bearer undefinedest envoyé. is_js(dépendance runtime utilisée parNetworkHelpers).GouvEntrepriserepose surNextalysNodeHttpClient(et doncnode-fetch-native/nextalys-js-helpers).
Source : src/helpers/network-helpers/ et src/helpers/gouv-entreprise/
Scripts npm
| Script | Description |
| --- | --- |
| npm run build | Compile le TypeScript vers dist/ (via tsc). |
| npm test | Lance la suite de tests Jasmine (via ts-node). |
| npm run build-and-publish | Compile puis publie le package sur npm. |
Des scripts test-* (ex. npm run test-gdrive-list, npm run test-html-to-pdf) permettent d’exécuter manuellement certains helpers à partir des fichiers d’options du dossier test/.
Développement
git clone [email protected]:davidkessas-m-oi/node-helpers.git
cd node-helpers
npm install
npm run build
npm testContribution
Les contributions se font sur le dépôt GitHub : https://github.com/davidkessas-m-oi/node-helpers. Ouvrez une issue ou une pull request.
Licence
Distribué sous licence ISC © Nextalys.
