leocense
v1.1.1
Published
Official Node.js SDK for LEOCENSE - Software Licensing & Distribution Platform
Maintainers
Readme
Leocense Node.js SDK
The official Node.js SDK for Leocense, the complete software licensing and distribution platform. This SDK allows you to verify licenses, implement hardware-locked device fingerprinting, and manage licenses/products programmatically.
Table of Contents
- Installation
- Getting Started
- Client-Side Usage (Verification)
- Server-Side Usage (Management)
- Type Definitions
- Integration Best Practices
- Changelog
Installation
Install the package via npm or yarn:
npm install leocense
# or
yarn add leocenseGetting Started
Import LeocenseClient from the package.
import { LeocenseClient } from 'leocense';There are two main ways to initialize the client:
Public/Client Mode: No API key required. Used inside your desktop or CLI application to verify licenses.
const client = new LeocenseClient();Management/Admin Mode: API Key required. Used on your backend server to create/manage licenses.
const client = new LeocenseClient('YOUR_SECRET_API_KEY');
Note: You can also specify a custom base URL if you are using a self-hosted instance:
const client = new LeocenseClient('API_KEY', 'https://your-custom-domain.com');Client-Side Usage (Verification)
These methods are safe to use in your distributed application. They do NOT require an API Key.
Verify License
Checks if a license key is valid, active, and not expired. This does not bind the license to a specific device.
Use Case: Lightweight check on app startup or web portal login.
const result = await client.verifyLicense('LICENSE-KEY-123', 'PRODUCT-ID-456');
if (result.success && result.valid) {
console.log('License is valid!');
console.log('App:', result.appName);
console.log('Owner:', result.ownerName);
console.log('Expiry:', result.expiryDate);
// You can also access raw data object:
// console.log('Data:', result.data);
} else {
console.error('Verification failed:', result.message);
}Verify with Hardware Locking
This is the recommended method for desktop/CLI apps. It generates a unique, weighted hardware fingerprint (Motherboard, Disk, CPU, MAC) of the user's machine, sends it to Leocense, and binds the license to that device.
Use Case: Preventing license sharing. The license will be locked to the first device(s) it is used on, up to the allowedDevices limit.
try {
const result = await client.verifyLicenseWithDevice('LICENSE-KEY-123', 'PRODUCT-ID-456');
if (result.success && result.valid) {
console.log('License active on this device.');
console.log('Variant:', result.variantName); // e.g., "Pro Version"
console.log('Properties:', result.properties);
} else {
// Handle specific failure reasons
switch (result.reason) {
case 'device_limit_blocked':
console.error('License used on too many devices.');
break;
case 'expired':
console.error('License has expired.');
break;
case 'blocked':
console.error('License has been blocked by the vendor.');
break;
default:
console.error('Invalid license:', result.message);
}
}
} catch (error) {
console.error('Network or System Error:', error);
}Check for Updates
Checks if a newer version of your product is available.
Use Case: Showing an "Update Available" notification in your app.
const update = await client.checkUpdate('PRODUCT-ID-456', '1.0.0'); // Current App Version
if (update && update.updateAvailable) {
console.log('New version found:', update.latestVersion);
console.log('Changelog:', update.changelog);
console.log('Download here:', update.downloadUrl);
}Server-Side Usage (Management)
These methods require an API Key with write permissions. NEVER use these in your client-side code distributed to users.
Create License
Generates a new license key for a customer.
Use Case: Automating license creation after a Stripe/PayPal payment webhook.
import { LeocenseClient, License } from 'leocense';
const adminClient = new LeocenseClient('YOUR_ADMIN_API_KEY');
async function generateLicenseForCustomer() {
try {
const newLicense = await adminClient.createLicense({
productId: 'PRODUCT-ID-456',
ownerName: 'John Doe',
email: '[email protected]', // Optional: Customer email
expiryDate: '2025-12-31T23:59:59Z', // Optional: Set expiration
limitDevices: true, // Enable hardware locking
allowedDevices: 2, // Allow use on 2 devices
metadata: { // Custom data
plan: 'pro',
source: 'stripe'
}
});
console.log('Created License:', newLicense.licenseKey);
} catch (err) {
console.error('Failed to create license:', err.message);
}
}Get/List Licenses
Retrieve details about specific licenses or list all licenses.
// Get single license
const license = await adminClient.getLicense('LICENSE-ID');
// List all licenses
const allLicenses = await adminClient.getLicenses();Activate/Block License
Control the status of issued licenses (e.g., if a refund occurs or a subscription is cancelled).
// Block a license (Prevent further verifications)
await adminClient.blockLicense('LICENSE-ID');
// Reactivate a blocked license
await adminClient.activateLicense('LICENSE-ID');
// Delete a license permanently
await adminClient.deleteLicense('LICENSE-ID');Manage Products
Create and retrieve products programmatically.
const newProduct = await adminClient.createProduct({
name: 'My Awesome App',
version: '1.0.0',
downloadUrl: 'https://example.com/download/app-v1.zip'
});Type Definitions
The SDK uses generic ApiResponse<T> types for all method returns.
LicenseResult
Returned by verification methods. Includes top-level access to license details.
interface LicenseResult {
success: boolean; // True if request succeeded
valid: boolean; // True if license is valid
message?: string; // Error message if any
data?: LicenseData; // Full license details object
// Convenience properties (merged from data):
reason?: string;
accessToken?: string;
appName?: string;
variantName?: string;
ownerName?: string;
ownerEmail?: string;
expiryDate?: string;
downloadUrl?: string;
properties?: string;
[key: string]: any; // Any other properties (e.g. flattened variant props)
}License
Standard License Interface.
interface License {
id: string;
licenseKey: string;
productId: string;
status: 'active' | 'blocked' | 'expired';
deviceIds?: string; // JSON string of bound devices
allowedDevices?: number;
metadata?: Record<string, any>;
// ... other standard fields
}
export interface AccessTokenData {
token: {
licenseId: string;
productId: string;
issuedAt: string;
};
license: Partial<License>;
properties?: string;
downloadUrl?: string;
}Integration Best Practices
- Local Caching: After a successful
verifyLicenseWithDevice, you should cache the result (and potentially theaccessTokenorexpiryDate) locally in a secure file. This allows your app to work offline for a grace period. - Graceful Failures: Always handle network errors (
try/catch). If the Leocense server is unreachable, decide if you want to allow access (soft fail) or block access (hard fail) based on your security needs. - Security: Obfuscate your
productIdin your client code. Do NOT ship your Admin API Key in your client application.
Changelog
v1.1.1
- Enhanced Device Fingerprinting: Added
hostnamecapture toverifyLicenseWithDevice(). - Robust Hostname Detection: Supports
os.hostname()with fallback to shellexec('hostname')for improved Linux/Kali/macOS support.
