@clientsdemo/license-client
v3.5.1
Published
TypeScript client SDK for the ClientsDemo License Server. Validate licenses, manage seats, renew, activate/deactivate machines, send heartbeats, run a continuous enforcement watchdog, and verify offline.
Downloads
423
Readme
@clientsdemo/license-client
TypeScript client SDK for the ClientsDemo License Server. Validate licenses, activate/deactivate machines, send heartbeats, manage subscriptions, and verify offline with Ed25519 signatures.
Installation
npm install @clientsdemo/license-client
# or
pnpm add @clientsdemo/license-clientQuick Start
import { LicenseClient } from "@clientsdemo/license-client";
const client = new LicenseClient({
serverUrl: "https://license.clientsdemo.site",
apiKey: "lsk_...",
appId: "ehs",
});
// Validate a license
const result = await client.validate("XXXX-XXXX-XXXX-XXXX-XXXX");
if (result.valid) {
console.log("Features:", result.license?.features);
}
// Activate on this machine
const machineId = await LicenseClient.generateMachineId();
await client.activate("XXXX-XXXX-XXXX-XXXX-XXXX", machineId, {
machineName: "prod-server-01",
appVersion: "2.1.0",
});
// Start auto-heartbeat (every hour)
const stopHeartbeat = client.startHeartbeat("XXXX-XXXX-XXXX-XXXX-XXXX", machineId);
// Later: stopHeartbeat();Middleware Guard
Use the guard for automatic license checking in your middleware:
import { createLicenseGuard } from "@clientsdemo/license-client";
const guard = createLicenseGuard({
serverUrl: "https://license.clientsdemo.site",
apiKey: "lsk_...",
appId: "ehs",
licenseKey: "XXXX-XXXX-XXXX-XXXX-XXXX",
});
// Check feature access
if (guard.hasFeature("audits")) {
// Enable audit module
}
// Request-scoped guard (Cloudflare Workers — isolated cache per request)
const scopedGuard = guard.forRequest();Service Binding (Worker-to-Worker)
For zero-latency validation between Cloudflare Workers:
import { ServiceBindingClient } from "@clientsdemo/license-client/service-binding";
const client = new ServiceBindingClient(env.LICENSE_SERVER);
const result = await client.validate("XXXX-XXXX-XXXX-XXXX-XXXX", "ehs");Public Activation (No API Key)
For customer-facing activation flows:
import { activateSetupLicense } from "@clientsdemo/license-client";
const result = await activateSetupLicense({
serverUrl: "https://license.clientsdemo.site",
licenseKey: "XXXX-XXXX-XXXX-XXXX-XXXX",
orgName: "Acme Corp",
email: "[email protected]",
});Offline Verification
import { LicenseClient, verifyOffline } from "@clientsdemo/license-client";
// Download and cache the license file
const licenseFile = await client.downloadLicenseFile("XXXX-XXXX-XXXX-XXXX-XXXX");
// Store licenseFile in localStorage, a file, etc.
// Later, verify offline (no network needed)
const result = await verifyOffline(licenseFile);
if (result.valid) {
console.log("License valid offline");
}
// Or use validateWithFallback for automatic offline fallback
const result2 = await client.validateWithFallback(
"XXXX-XXXX-XXXX-XXXX-XXXX",
cachedLicenseFile,
machineId,
);Billing Methods
// Get pricing plans for an app
const pricing = await client.getPricing();
// Create a checkout session
const { checkoutUrl } = await client.createCheckout({
planTier: "professional",
billingPeriod: "yearly",
email: "[email protected]",
orgName: "Acme Corp",
});
// Get subscription status
const sub = await client.getSubscription("XXXX-XXXX-XXXX-XXXX-XXXX");
// Get invoices
const invoices = await client.getInvoices("XXXX-XXXX-XXXX-XXXX-XXXX");
// Get billing portal URL
const { portalUrl } = await client.getBillingPortalUrl(customerId);Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| serverUrl | string | required | Base URL of the license server |
| apiKey | string | required | API key for authentication |
| appId | string | required | Application identifier |
| timeout | number | 10000 | Request timeout in ms |
| maxRetries | number | 3 | Max retry attempts for failed requests |
| retryBaseDelay | number | 1000 | Base delay in ms for exponential backoff |
Supported App IDs
ehs, ehr, ksdb, isms, partnerhub, shoprewards, safearena, bustracker, gstfiling
API Reference
client.validate(licenseKey, machineId?)
Validate a license key. Returns { valid, reason?, license? }.
client.activate(licenseKey, machineId, options?)
Activate a license on a machine. Returns { success, reason?, activationId? }.
client.activatePublic(params)
Activate without API key (rate limited). Returns { success, reason?, activationId? }.
client.deactivate(licenseKey, machineId)
Deactivate a license from a machine. Returns { success, reason? }.
client.heartbeat(licenseKey, machineId)
Send a heartbeat for an active license. Returns { success, reason? }.
client.status(licenseKey)
Get full license status including activations.
client.downloadLicenseFile(licenseKey)
Download a signed offline license file.
client.startHeartbeat(licenseKey, machineId, intervalMs?)
Start automatic heartbeat. Returns a stop function.
client.validateWithFallback(licenseKey, cachedFile, machineId?)
Validate with automatic offline fallback.
client.getPricing()
Get pricing plans for the configured app.
client.createCheckout(params)
Create a Stripe checkout session.
client.getSubscription(licenseKey)
Get subscription status for a license.
client.getInvoices(licenseKey)
Get invoice history for a license.
client.getBillingPortalUrl(customerId)
Get Stripe billing portal URL.
LicenseClient.generateMachineId() (static)
Generate a machine ID from hostname/OS info (Node.js).
LicenseClient.generateBrowserMachineId() (static)
Generate a machine ID from browser navigator data.
verifyOffline(licenseFile)
Verify a license file offline using Ed25519 Web Crypto API.
createLicenseGuard(config)
Create a middleware guard for automatic license validation with caching.
guard.forRequest()
Create a request-scoped guard (Cloudflare Workers safety).
Security & Socket.dev Score
[!NOTE] Why is the Supply Chain Security score 79 on Socket.dev?
There is no actual vulnerability or malicious code in the package causing this score. The score of 79 simply reflects the fact that this package requires a high level of system privilege (Network, File System, OS Info, and Executables) to accomplish its intended job as a license enforcement client.
Specifically, the package:
- Contains a
binexecutable (license-fingerprint)- Reads from the File System for offline caching (
node:fs)- Accesses Environment/OS info for hardware fingerprinting (
node:os)- Makes Network requests to the license server
License
MIT
