npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nextalys-node-helpers

v1.7.0

Published

Nextalys Node Helpers

Downloads

6,811

Readme

nextalys-node-helpers

npm version license

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-helpers

La 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/node 18).
  • 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/<...>.tsnextalys-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 moteur exec (défaut) ou spawn.
    • static getHttpContent(url: string): Promise<any> — récupère le corps texte d'une URL.
    • static getNodeVersion(onlyDigit?: number): string | number
    • static 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?), NewsletterHelpers et 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 de executeCommand), 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, étend NextalysHttpClient.
    • 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 une Promise<NextalysHttpResponse>. En get, data est sérialisé en paramètres d'URL ; sinon utilisé comme corps (JSON si jsonRequest).
    • downloadFile(url, output, verbose = false, timeout = null) : télécharge l'URL en streaming vers le fichier output.
  • setOptions(options) / verbose — hérités : options accepte { useBasicAuth?, username?, password?, withCredentials? }.
  • NxsAbortController et AbortSignal — implémentation de repli d'abort/timeout utilisée quand globalThis.AbortController est 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 de fetch).
  • Dépendance nextalys-js-helpers : fournit la classe de base NextalysHttpClient ainsi que les types NextalysHttpResponse et NextalysHttpClientOptions.
  • Avec ignoreTLSReject = true, la variable d'environnement NODE_TLS_REJECT_UNAUTHORIZED est 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(...).
  • SmtpMailProvidernew SmtpMailProvider(opts: SmtpMailProviderOptions).
  • SendInBlueMailProvidernew SendInBlueMailProvider(opts: { sendInBlueApiKey: string }), supporte aussi createOrUpdateContact, addContactToList, createNewsletter, sendExistingNewsletter.
  • SendGridMailProvidernew SendGridMailProvider(opts: SendGridMailProviderOptions) (non ré-exporté par le point d'entrée, voir import via sous-chemin dist/).
  • 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 du textBody).
  • Credentials selon le provider :
    • SMTP : smtpServer, smtpPort, et smtpUser / smtpPassword (ex. via SMTP_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).

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. Constructeur new SendInBlueSmsProvider(opts: SendInBlueMailProviderOptions) (l'option clé est sendInBlueApiKey).
  • 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 — ajoute newsLetterName?, 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 par SendInBlueSmsProvider).
  • Clé API Sendinblue fournie à l'instanciation via l'option sendInBlueApiKey (ici lue depuis la variable d'environnement SENDINBLUE_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 par folder (nom), folderId ou tout.
    • uploadToGoogleDrive(opts: GDriveUploadOptions): Promise<GDriveFileResponse> — upload d'un file (ou d'un folder compressé en .7z).
    • copyGDriveFile(opts: GdriveCopyFileOptions): Promise<GDriveFileResponse> — copie via fileId, avec targetParentId / newName optionnels.
    • downloadFile(opts: GDriveGetFileOptions): Promise<void> — télécharge fileId vers target.
    • 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 via require('googleapis')) et nextalys-js-helpers.
  • Un compte de service Google avec accès à Drive : fournir client_email + private_key, ou un credentialFile (chemin vers le JSON du compte de service). Le scope utilisé est https://www.googleapis.com/auth/drive.
  • Pour l'upload d'un dossier (opts.folder), ArchiveManager compresse 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 client ImageAnnotatorClient.
    • 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 de GoogleApiOptions).
  • GoogleTextDetectionResponse{ blocks: GoogleTextBlock[]; words: string[]; success: boolean }.
  • GCloudStorageHelpers — classe statique de stockage objet.
    • init(opts: GCloudStorageHelpersOptions) : obligatoire avant tout appel (sinon Error('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).
  • GCloudStorageHelpersOptionsGoogleApiOptions & { exceptionPropagation?: boolean } (si true, les erreurs sont relancées au lieu d'être placées dans response.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 renseignant credentialFile (le private_key/client_email/project_id sont 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ève Error('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 que firebaseApp, initialized, initializing, options.
  • FirebaseManagerOptions — options d'init : { certFilePath?, certFileContent?, databaseURL?, debug?, logger?, storageBucket? }.
  • AbstractLogger{ log, error, warn }, injectable via options.logger.
  • FirebaseAuthManagerdeleteUser(userId), getUser(userId), changeUserPassword(userId, newPassword).
  • FirebaseFirestoreManagerupdateDoc<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?).
  • FirebaseMessagingManagersendPush<T>(tokens, notification, data?, opts?): Promise<SendPushResponse>, sendPushToEveryone<T>(notification, data?): Promise<string>.
  • FirebaseRealtimeDbManagerupdateRef, setRef, removeRef, getOnce<T>(path), getRef(path), backupFullDatabase(output?).
  • FirebaseStorageManageruploadFile(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), soit certFileContent (objet JSON déjà chargé). L'init échoue si aucun des deux n'est fourni.
  • databaseURL obligatoire pour utiliser FirebaseRealtimeDbManager.
  • storageBucket recommandé dans les options pour FirebaseStorageManager (sinon le passer en argument storageBucket à chaque appel).
  • nextalys-js-helpers (utilisé en interne par les managers Firestore et Realtime DB pour backupFullDatabase).

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 ; puis publishFolder(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) puis executeCommand(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-ssh requis pour SshManager.
  • 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 utilise process.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 avec ArchiveManager.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'): void et static 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 classe ArchiveManager. L'interface IArchiveManager et 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é (via checkManager(), sinon log d'erreur et retour null). Certaines opérations ne sont pas implémentées selon le backend (ex. extractArchive pour Zip et SevenZip, removeFileFromArchive / addFileToArchive / createArchiveFromFolder / createArchiveFromFolders / createArchiveFromFiles pour GZip) et renvoient alors null.

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 : binaire zip disponible dans le PATH (utilisé via zip -r, zip -ur, zip -d).
  • Backend GZip : binaire gunzip disponible dans le PATH (seule la méthode extractArchive est implémentée, via gunzip -c <archive> > <output>).
  • Backend SevenZip : dépendance npm node-7z (^1.1.0) et binaire 7z/7za accessible dans le PATH.
  • Aucune variable d'environnement ni fichier de credentials requis.

Source : src/helpers/archive-manager/

PDF

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, PDFHelpers réutilise un navigateur Chromium partagé (singleton) entre les appels (option reuseBrowser, activée par défaut) au lieu d'en relancer un à chaque PDF. Pensez à appeler PDFHelpers.closeBrowser() à l'arrêt de l'application pour libérer le process. Le défaut de waitUntil est 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 sur output. opts.format vaut 'a4' par défaut.
  • PDFHelpers.HtmlToPdfFromTemplate(htmlTemplate, data, output, removeHtmlFile?, opts?, debug?) — remplit un template HTML avec data puis le rend en PDF ; renvoie { success, error }.
  • PDFHelpers.closeBrowser(): Promise<void> — ferme proprement le navigateur partagé. À appeler à l'arrêt de l'application (ex. onModuleDestroy sous NestJS).
  • GeneratePdfOptions — interface : inputIsUrl / inputIsFile / inputIsHtml, format: NxsPDFFormat (défaut 'a4'), browserPdfOptions: PDFOptions, launchOptions: LaunchOptions, headless: boolean | 'shell', noSandbox, disableGpu (headless/noSandbox/disableGpu actifs par défaut ; 'shell' utilise chrome-headless-shell, plus léger), reuseBrowser (réutilise le navigateur partagé ; défaut true), 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 seul Buffer.
  • PdfLibHelpers.addPdfPage(pdfFile: string | Buffer, opts?: { output?: string }): Promise<Buffer> — ajoute une page vierge ; écrit le résultat si opts.output est fourni.
  • SignPdfHelpers.sign(pdfInput, p12Cert, additionalOptions?): Promise<Buffer | null> — signe un PDF (chemin ou Buffer) 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, version 24.15.0) installé pour PDFHelpers ; un environnement Chromium fonctionnel (les options --no-sandbox, --disable-gpu et --disable-dev-shm-usage sont 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 passez reuseBrowser: false pour relancer un navigateur dédié à chaque appel).
  • pdf-lib (^1.17.1) pour PdfLibHelpers.
  • node-forge (^1.3.1) pour SignPdfHelpers.
  • Pour la signature : un certificat PKCS#12 (.p12/.pfx) et sa passphrase (ex. via P12_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 un Buffer si options.toBuffer est vrai, sinon écrit dans output.
    • ImageHelpers.convertImage(input, options) — convertit vers options.outFormat ('png' | 'jpeg' | 'webp' | 'jpg') et écrit dans options.output.
    • ImageHelpers.getImageInfo(input) — retourne les métadonnées (width, height).
  • ResizeImageOptionswidth?, height?, fit?, position?, toBuffer?, tryConvertHeic?, plus webPOptions / jpegOptions / pngOptions.
  • ConvertImageOptionsoutFormat, 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 dossier output/ (relatif au module), et un favicon.ico lorsque 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 (option tryConvertHeic sur un fichier .heic).
  • to-ico (^1.1.5) — requis pour la génération du favicon.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 — étend ExcelHelpersBrowserExcelJs. Méthodes d'instance async getExcelWorksheet(file: string, opts: GetExcelWorksheetOptions), async getExcelWorksheetContent(file: string, opts: GetExcelWorksheetContentOptions): Promise<any[][]> et async generateExcel(options: NxsGenerateExcelOptions): Promise<string | Excel.Buffer>. Les options proviennent de nextalys-js-helpers/dist/excel.
  • CsvHelpersstatic 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.
  • XmlHelpersstatic parseXmlString(xmlString: string): any et static xmlFileToJsObject(xmlFile: string): Promise<any>.
  • HtmlHelpersstatic registerHandleBarsHelpers(helpers: HandleBarsHelperType[]), static registerHandlebarsHelper(name, handler), static fillHtml(htmlTemplate, data, outputHtmlFile, returnHtmlContent, debug?) et static 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 base ExcelHelpersBrowserExcelJs et types GetExcelWorksheetOptions, 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 le WebClient interne avec un token Slack. À appeler avant sendMessage.
    • static sendMessage(message: string, channel: string, opts?: { channel?: string }): Promise<...> — poste un message texte dans un canal via chat.postMessage. Lève une erreur si init n'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 par init / 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) pour sendMessageWithWebhook.

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) — envoie input comme message user et retourne { success, message, error, jsonData? }. Si json vaut true, le response_format json_object est appliqué et la réponse est parsée dans jsonData. 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 depuis process.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 premier encrypt/decrypt.
  • CryptoHelpers.encrypt(str: string, key?: string) — renvoie un objet { iv, encryptedPayload, key, encryptedString } ; encryptedString (au format iv:payload) est la valeur à conserver.
  • CryptoHelpers.decrypt(textToDecrypt: string, key?: string): string — déchiffre une chaîne au format iv:payload et 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 crypto de Node.js.
  • La clé fournie à init (ou à encrypt/decrypt) doit avoir une longueur compatible avec l'algorithme choisi (32 octets pour aes-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...) puis req.connection/req.socket/req.requestContext.
  • NetworkHelpers.isLocalRequest(req: any): boolean — vrai si l'IP résolue contient 127.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 une NextalysHttpResponse<GetSirenResponse>.
  • GouvEntreprise.getEtablissements(siren: string)GET /sirene/V3/siret?q=siren:<siren>, renvoie une NextalysHttpResponse<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. via process.env.INSEE_JWT_TOKEN) avant tout appel — sinon le header Authorization: Bearer undefined est envoyé.
  • is_js (dépendance runtime utilisée par NetworkHelpers).
  • GouvEntreprise repose sur NextalysNodeHttpClient (et donc node-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 test

Contribution

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.