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

leocense

v1.1.1

Published

Official Node.js SDK for LEOCENSE - Software Licensing & Distribution Platform

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

Install the package via npm or yarn:

npm install leocense
# or
yarn add leocense

Getting Started

Import LeocenseClient from the package.

import { LeocenseClient } from 'leocense';

There are two main ways to initialize the client:

  1. Public/Client Mode: No API key required. Used inside your desktop or CLI application to verify licenses.

    const client = new LeocenseClient();
  2. 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

  1. Local Caching: After a successful verifyLicenseWithDevice, you should cache the result (and potentially the accessToken or expiryDate) locally in a secure file. This allows your app to work offline for a grace period.
  2. 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.
  3. Security: Obfuscate your productId in your client code. Do NOT ship your Admin API Key in your client application.

Changelog

v1.1.1

  • Enhanced Device Fingerprinting: Added hostname capture to verifyLicenseWithDevice().
  • Robust Hostname Detection: Supports os.hostname() with fallback to shell exec('hostname') for improved Linux/Kali/macOS support.