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

@software-authority/license-service-sdk

v1.2.1

Published

Node SDK for the License Manager service API

Readme

License Service SDK

Node SDK for the Laravel license service exposed by this repository.

Features

  • Validate licenses with license_key or encrypted .lic payloads
  • Activate licenses with device context
  • Deactivate licenses
  • Download encrypted .lic files
  • Verify signed .lic files locally using a public key
  • Keep backward compatibility with legacy encrypted .lic files using LICENSE_FILE_KEY
  • Validate and activate .lic files offline without calling the license service

Install

npm install @software-authority/[email protected]

For consumers on other software, follow the major version you support:

npm install @software-authority/license-service-sdk@^1.2.1

Use exact 1.2.1 if you want to lock to one release. Use ^1.2.1 if you want future non-breaking updates in the 1.x line.

Publish

For a scoped npm package, publish it from this package folder:

npm publish

publishConfig.access is already set to public in the package manifest, so future publishes use the correct access level.

Versioning

Current version: v1.2.1.

Consumer guidance:

  • Stay on 1.x if your software is built against the current API contract.
  • Upgrade to 2.x only when you intentionally adopt a breaking SDK change.
  • Prefer ^1.2.1 in consuming software for safe backward-compatible updates.
  • Prefer exact 1.2.1 when you need fully locked deployments.

Use one of these commands before publishing an update:

npm run release:patch
npm run release:minor
npm run release:major

Typical release flow:

npm test
npm run build
npm run release:patch
npm run publish:npm

Version updates are stored in package.json and package-lock.json, so future releases keep a clear version history.

Usage

import { LicenseServiceClient } from '@software-authority/license-service-sdk';

const client = new LicenseServiceClient({
  baseUrl: 'https://example.com/api/licenses',
  auth: {
    appId: 'app_example',
    appSecret: 'sec_example',
  },
});

const result = await client.activate({
  licenseKey: 'ABCD-EFGH-IJKL-MNOP',
  machineId: 'machine-001',
  instanceName: 'pos-main',
});

Offline usage

Use the offline helpers in a Node or Electron service process when the software needs to work from a .lic file without contacting the server.

import { activateOfflineLicense, validateOfflineLicense } from '@software-authority/license-service-sdk';

const validation = validateOfflineLicense({
  licenseFile: encryptedLicenseFile,
  publicKey: process.env.LICENSE_FILE_PUBLIC_KEY!,
});

if (!validation.valid) {
  throw new Error(validation.message);
}

const activation = activateOfflineLicense({
  licenseFile: encryptedLicenseFile,
  publicKey: process.env.LICENSE_FILE_PUBLIC_KEY!,
  machineId: 'machine-001',
  instanceName: 'pos-main',
  meta: {
    machine_id: 'machine-001',
  },
});

console.log(activation.license?.effective_rules);
console.log(activation.activation);

Selecting the correct public key bundle

When the license provider uses different signing keys per product, the consuming software should keep a local trust bundle instead of a single public key string.

Recommended trust bundle shape:

type ProductTrustBundle = {
  productId: string;
  activeKeyId: string;
  keys: Array<{
    keyId: string;
    publicKey: string;
    retiredAt?: string | null;
  }>;
};

Recommended local storage per product:

  • the current active public key
  • older public keys kept for historical .lic files signed before rotation
  • the product identifier or software identifier that owns the bundle

Use parseLicenseFileEnvelope(...) first to inspect the signed file and choose the matching key by key_id.

import {
  resolvePublicKeyFromTrustBundle,
  validateOfflineLicense,
} from '@software-authority/license-service-sdk';

const publicKey = resolvePublicKeyFromTrustBundle(licenseFile, trustBundle);

const result = validateOfflineLicense({
  licenseFile,
  publicKey,
});

The provider's Offline Trust download now returns this JSON shape directly:

type ProviderProductTrustBundle = {
  product: {
    id: string | number;
    slug: string | null;
    name: string | null;
  };
  active_key_id: string;
  keys: Array<{
    key_id: string;
    public_key: string;
    activated_at?: string | null;
    retired_at?: string | null;
  }>;
};

resolvePublicKeyFromTrustBundle(...) accepts both the normalized camelCase bundle and the provider-exported snake_case bundle.

Why this matters:

  • new .lic files use the product's current active signing key
  • older .lic files may have been signed before a key rotation
  • keeping the historical keys in the local trust bundle allows both old and new files to verify correctly

Recommended provider handoff per product:

  • active public key PEM
  • active key ID
  • historical public keys when older offline files must remain usable
  • product or software identifier so the bundle is not mixed across products

Recommended consumer behavior after key rotation:

  1. Add the new public key to the local trust bundle instead of replacing the old one immediately.
  2. Mark the old key as retired, but keep it available for historical offline files.
  3. Use key_id from the .lic envelope to select the correct verification key.
  4. Remove old keys only when you are certain no installed software still depends on old offline files.

Offline helper behavior:

  • Verifies signed .lic payloads locally with a public key.
  • Checks status, expires_at, and offline_file_valid_until locally.
  • Returns rule data from the signed payload without calling the server.
  • Produces an activation-shaped response for offline service processes.
  • Does not persist activation state back to the server.

For legacy LM1. files, pass fileEncryptionKey instead of publicKey.

Auth modes

Use one of the following:

  • apiKey: sends Authorization: Bearer <key>
  • appId and appSecret: sends X-App-Id and X-App-Secret

Notes

  • This SDK is intended for trusted Node service processes.
  • Do not embed app secrets in browser code.
  • Offline parsing and activation are intended for local/offline execution paths and do not replace server-side activation tracking.