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

@digitea/updater

v0.1.1

Published

Official lightweight client for the Digitea Software Updates API

Readme

@digitea/updater

Client TypeScript officiel pour intégrer les mises à jour de votre produit SOFTWARE Digitea dans une application Node.js ou dans le processus principal d’Electron.

Le SDK permet de :

  • rechercher publiquement une mise à jour compatible avec la version installée ;
  • demander un lien de téléchargement autorisé pour un artifact précis ;
  • gérer les timeouts, les retries, l’annulation et les erreurs typées.

Il ne télécharge pas les octets, n’installe rien et ne nécessite jamais de clé Developer API. L’installation, le remplacement des fichiers et le redémarrage de l’application restent sous le contrôle de votre logiciel.

Installation

npm install @digitea/updater

Le SDK nécessite Node.js 18 ou une version plus récente, notamment pour utiliser fetch et AbortSignal.

Le flux complet

  1. Créez une release publiée et ses artifacts depuis votre espace vendeur Digitea.
  2. Configurez dans l’application le productId public de votre produit.
  3. Appelez check() avec la version, la plateforme et l’architecture du build installé.
  4. Présentez la mise à jour à l’utilisateur et demandez son accord.
  5. Appelez getDownload() avec la licence et l’instance déjà activée.
  6. Téléchargez l’URL retournée, vérifiez sha256 lorsque la valeur est fournie, puis installez selon votre propre procédure.

Le productId est fourni dans le tableau de bord ou dans la réponse de création ou de lecture du produit. Il est public : vous pouvez le placer dans la configuration de l’application. Ne demandez pas ce paramètre au client et ne placez jamais une clé dgt_sk_live_... dans l’application distribuée.

Exemple rapide

import { DigiteaUpdater } from "@digitea/updater";

const updater = new DigiteaUpdater({
  productId: process.env.DIGITEA_PRODUCT_ID ?? "prd_demo123456",
});

const update = await updater.check({
  currentVersion: "1.2.0",
  platform: "WINDOWS",
  architecture: "X64",
  channel: "STABLE",
  packageType: "EXE",
});

if (update.available) {
  // Demandez l’accord de l’utilisateur avant le téléchargement.
  const download = await updater.getDownload({
    licenseKey,
    instanceId,
    artifactId: update.artifactId,
  });

  console.log(download.downloadUrl);
}

licenseKey est la clé complète remise au client après son achat. instanceId doit être le même identifiant stable que celui utilisé lors de l’activation avec @digitea/licensing. L’updater ne crée pas d’activation et ne remplace pas le SDK Licensing.

Configuration

const updater = new DigiteaUpdater({
  productId: "prd_demo123456",
  baseUrl: "https://api.getdigitea.com",
  timeoutMs: 10_000,
  retry: {
    maxRetries: 2,
    baseDelayMs: 250,
    maxDelayMs: 5_000,
  },
});

| Option | Obligatoire | Valeur par défaut | Description | |---|---:|---:|---| | productId | oui | — | Identifiant public du produit SOFTWARE. | | baseUrl | non | https://api.getdigitea.com | URL de l’API. HTTPS est obligatoire ; http://localhost est accepté pour les tests locaux. | | timeoutMs | non | 10000 | Délai maximal d’une tentative réseau, en millisecondes. | | retry.maxRetries | non | 2 | Nombre de nouvelles tentatives après une panne temporaire. | | retry.baseDelayMs | non | 250 | Délai initial du backoff. | | retry.maxDelayMs | non | 5000 | Délai maximal du backoff. |

Le constructeur rejette un productId vide et une baseUrl qui n’utilise pas HTTPS, sauf pour localhost. Les options de retry sont bornées par votre configuration ; utilisez-les avec mesure pour ne pas retarder l’expérience utilisateur.

Rechercher une mise à jour avec check()

const result = await updater.check({
  currentVersion: "1.2.0",
  platform: "ANDROID",
  architecture: "ANY",
  channel: "STABLE",
  packageType: "ZIP",
});

Cet appel est public : il ne demande ni licenseKey ni clé vendeur.

| Paramètre | Obligatoire | Valeurs | |---|---:|---| | currentVersion | oui | Version SemVer installée, par exemple 1.2.0. | | platform | oui | WINDOWS, MACOS, LINUX, ANDROID, BROWSER, CROSS_PLATFORM. | | architecture | oui | X64, X86, ARM64, UNIVERSAL, ANY. | | channel | non | STABLE, BETA, ALPHA. Par défaut : STABLE. | | packageType | non | EXE, MSI, DMG, PKG, APPIMAGE, DEB, RPM, APK, AAB, ZIP, CRX, XPI, VSIX, SCRIPT, OTHER. |

Décrivez la plateforme, l’architecture et le package du build réellement installé. N’utilisez CROSS_PLATFORM, UNIVERSAL ou ANY que lorsqu’un artifact est réellement compatible avec ces cibles.

Réponse sans mise à jour

{
  available: false,
  currentVersion: "1.2.0",
  latestVersion: "1.2.0",
  reason: "UP_TO_DATE"
}

reason peut être :

  • UP_TO_DATE : la version installée est déjà au niveau de la dernière release du canal demandé ;
  • NO_COMPATIBLE_ARTIFACT : une release plus récente existe, mais aucun artifact de cette release ne correspond à la plateforme, l’architecture ou au package demandé.

Quand aucune release publiée n’existe dans le canal, latestVersion vaut null et reason est absent.

Réponse avec mise à jour

{
  available: true,
  currentVersion: "1.2.0",
  latestVersion: "1.3.0",
  releaseId: "swr_demo123",
  channel: "STABLE",
  releaseNotes: "Corrections et améliorations.",
  publishedAt: "2026-09-01T09:00:00.000Z",
  artifactId: "swa_demo123",
  platform: "ANDROID",
  architecture: "ANY",
  packageType: "ZIP",
  sizeBytes: 48200123,
  sha256: "64 caractères hexadécimaux",
  deliveryMode: "HOSTED"
}

Le résultat available: true contient toujours releaseId, artifactId, channel, publishedAt, platform, architecture, packageType et deliveryMode. releaseNotes, sizeBytes et sha256 peuvent être null selon la configuration de l’artifact.

Règles de sélection

La sélection se fait dans cet ordre :

  1. Digitea prend la release publiée la plus récente selon SemVer dans le canal demandé.
  2. Il recherche un artifact uniquement dans cette release.
  3. Il préfère une plateforme exacte à CROSS_PLATFORM.
  4. Il préfère une architecture exacte à UNIVERSAL ou ANY.
  5. Il applique packageType lorsqu’il est fourni.

Digitea ne revient pas automatiquement à une ancienne release si la dernière release n’a aucun build compatible. check() renvoie alors available: false avec NO_COMPATIBLE_ARTIFACT.

Une application configurée sur STABLE ne reçoit jamais une release BETA ou ALPHA. Une release DRAFT, archivée ou non publiée n’est pas proposée.

Autoriser un téléchargement avec getDownload()

const download = await updater.getDownload({
  licenseKey,
  instanceId,
  artifactId: update.artifactId,
});

Les trois paramètres sont obligatoires :

| Paramètre | Description | |---|---| | licenseKey | Clé complète du client. Ne la journalisez jamais. | | instanceId | Instance déjà activée avec cette licence. | | artifactId | Artifact retourné par check(). |

Le service vérifie la licence, le produit, l’instance active et l’appartenance de l’artifact à une release SOFTWARE publiée. Une licence expirée, suspendue ou révoquée ne peut pas obtenir de téléchargement.

Réponse

{
  artifactId: "swa_demo123",
  deliveryMode: "HOSTED",
  downloadUrl: "https://...",
  expiresIn: 300,
  sha256: "64 caractères hexadécimaux"
}
  • HOSTED : Digitea renvoie une URL présignée valable 5 minutes. Utilisez-la rapidement et ne la stockez pas dans un cache permanent.
  • EXTERNAL : Digitea renvoie l’URL HTTPS configurée par le vendeur et expiresIn vaut null.

Le SDK ne suit pas l’URL et ne vérifie pas le hash à votre place. Téléchargez le fichier avec votre propre client HTTP, comparez son SHA-256 à download.sha256 lorsqu’il est fourni, puis lancez votre installateur.

import { createHash } from "node:crypto";

const response = await fetch(download.downloadUrl);
if (!response.ok) {
  throw new Error("Téléchargement impossible : HTTP " + response.status);
}

const bytes = Buffer.from(await response.arrayBuffer());

if (download.sha256) {
  const actualSha256 = createHash("sha256").update(bytes).digest("hex");
  if (actualSha256 !== download.sha256) {
    throw new Error("Le contrôle SHA-256 de la mise à jour a échoué");
  }
}

Pour les gros fichiers, utilisez un téléchargement en flux afin de ne pas charger tout l’artifact en mémoire.

Intégration avec Licensing

L’updater ne valide pas une licence et ne crée pas d’activation. Pour un téléchargement autorisé, l’instance doit déjà être active avec la licence utilisée.

import { DigiteaLicensing } from "@digitea/licensing";
import { DigiteaUpdater } from "@digitea/updater";

const productId = "prd_demo123456";
const licensing = new DigiteaLicensing({ productId });
const updater = new DigiteaUpdater({ productId });

const instanceId = await loadOrCreateStableInstanceId();
await licensing.activate({ licenseKey, instanceId });

const update = await updater.check({
  currentVersion: "1.2.0",
  platform: "WINDOWS",
  architecture: "X64",
});

if (update.available) {
  const download = await updater.getDownload({
    licenseKey,
    instanceId,
    artifactId: update.artifactId,
  });
}

Conservez le même productId et le même instanceId pour Licensing et Updates. Si l’activation est supprimée ou désactivée, getDownload() échoue avec INSTANCE_NOT_ACTIVATED.

Electron

Utilisez le SDK dans le processus principal Electron. Exposez au renderer uniquement les informations nécessaires à l’interface : version disponible, notes, progression et résultat de l’installation.

// main.ts
const updater = new DigiteaUpdater({ productId: "prd_demo123456" });

ipcMain.handle("updates:check", async () => updater.check({
  currentVersion: app.getVersion(),
  platform: "WINDOWS",
  architecture: "X64",
  channel: "STABLE",
  packageType: "EXE",
}));

Ne transmettez jamais une clé Developer API au renderer. La clé de licence client et l’URL de téléchargement doivent également rester absentes des logs et des messages inutiles.

Annuler une requête

Toutes les méthodes acceptent un AbortSignal en second argument :

const controller = new AbortController();

const pending = updater.check(
  {
    currentVersion: "1.2.0",
    platform: "LINUX",
    architecture: "X64",
  },
  { signal: controller.signal },
);

controller.abort();

await pending; // rejette avec DigiteaUpdaterError et le code ABORTED

Retries et disponibilité

Le SDK rejoue automatiquement les erreurs temporaires :

  • erreurs réseau ;
  • timeout ;
  • réponse HTTP 429 ;
  • réponse HTTP 5xx ;
  • erreur API TEMPORARILY_UNAVAILABLE.

Les erreurs de licence, de produit et de requête ne sont jamais rejouées. Le délai augmente progressivement jusqu’à maxDelayMs et l’en-tête Retry-After est respecté lorsqu’il est fourni.

Une panne réseau ne crée jamais de droit hors ligne et ne doit pas être traitée comme une validation de licence. Si toutes les tentatives échouent, laissez l’utilisateur réessayer plus tard.

Gérer les erreurs

Les erreurs sont des instances de DigiteaUpdaterError :

import { DigiteaUpdaterError } from "@digitea/updater";

try {
  await updater.getDownload({ licenseKey, instanceId, artifactId });
} catch (error) {
  if (error instanceof DigiteaUpdaterError) {
    console.log({
      code: error.code,
      status: error.httpStatus,
      retryable: error.retryable,
    });
  }
}

| Code | Signification | Rejouable ? | |---|---|---:| | LICENSE_INVALID | Clé inconnue ou invalide. | non | | LICENSE_EXPIRED | Licence expirée. | non | | LICENSE_SUSPENDED | Licence suspendue. | non | | LICENSE_REVOKED | Licence révoquée. | non | | INSTANCE_NOT_ACTIVATED | Instance absente ou non active pour cette licence. | non | | INVALID_PRODUCT | Produit inconnu ou incompatible. | non | | INVALID_REQUEST | Paramètres invalides. | non | | RATE_LIMITED | Limite de requêtes atteinte. | oui | | TEMPORARILY_UNAVAILABLE | Service momentanément indisponible. | oui | | NETWORK_ERROR | Service inaccessible après les tentatives prévues. | oui | | TIMEOUT | Tentatives dépassées après timeoutMs. | oui | | ABORTED | Requête annulée avec AbortController. | non | | INVALID_RESPONSE | Réponse absente, non JSON ou incompatible avec le contrat. | selon la cause |

Pour RATE_LIMITED, TEMPORARILY_UNAVAILABLE, NETWORK_ERROR et TIMEOUT, affichez un message compréhensible et proposez un nouvel essai plus tard.

Sécurité et bonnes pratiques

  • Le productId est public ; la licenseKey est une donnée sensible du client.
  • N’utilisez jamais une clé dgt_sk_live_... avec ce SDK : elle est réservée à la Developer API sur votre serveur.
  • Ne journalisez ni la licenseKey, ni downloadUrl, ni les réponses complètes de téléchargement.
  • Vérifiez sha256 avant de lancer un installateur lorsque cette valeur est disponible.
  • Ne considérez jamais un redirect ou une notification comme une preuve de mise à jour installée.
  • Demandez l’accord de l’utilisateur avant le téléchargement et l’installation.
  • Conservez la version réellement installée et relancez check() après l’installation.
  • Pour une application Electron, gardez la logique de téléchargement et d’installation dans le processus principal.

Types exportés

Le paquet exporte notamment :

DigiteaUpdater
DigiteaUpdaterError
SoftwarePlatform
SoftwareArchitecture
SoftwareReleaseChannel
SoftwarePackageType
SoftwareArtifactDeliveryMode
RetryConfig
DigiteaUpdaterConfig
RequestOptions
CheckUpdateInput
CheckUpdateResult
GetDownloadInput
UpdateDownloadResult
UpdaterErrorCode

Les types TypeScript sont inclus dans le paquet dans dist/index.d.ts.

Ce que le SDK ne fait pas

  • Il ne crée pas de produit, release ou artifact.
  • Il ne publie pas de release.
  • Il n’active pas une licence.
  • Il ne demande pas de clé Developer API.
  • Il ne télécharge pas automatiquement le fichier.
  • Il n’installe pas et ne remplace pas votre application.
  • Il n’accorde aucun mode hors ligne en cas de panne du service.

Pour gérer l’activation, la validation, la désactivation et le renouvellement d’une licence, utilisez @digitea/licensing sur npm. Pour le contrat HTTP complet, consultez la documentation Software Updates et la référence API v1.

Développement du paquet

npm run build
npm test

Le guide public complet est disponible sur docs.getdigitea.com/software-updates.