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

@trap_stevo/lockline

v0.0.11

Published

The ultimate solution for secure, scalable, and tamper-resistant license key validation. Combine flexible validation strategies, encrypted / pluggable storage, smart fallback resilience, and real-time revocation control to lock down your software — and un

Downloads

28

Readme

🔐 @trap_stevo/lockline

The ultimate solution for secure, scalable, and tamper-resistant license key validation.
Combine flexible validation strategies, encrypted / pluggable storage, smart fallback resilience, and real-time revocation control to lock down your software — and unlock next-gen licensing workflows.


🚀 Features

  • 🔎 Pluggable Validators – Register and chain custom validation strategies
  • 🧠 Smart Fallbacks – Automatically retry with secondary validators if primary fails
  • 📦 Flexible Storage Engine – Support for encrypted file-based or custom async storage
  • 🔒 Tamper-Resistant Sealing – Enrich keys with metadata and protect against injection
  • 🔁 Offline Tolerance – Optional trust logic when all validators are unreachable
  • 🧹 Automatic Cleanup – Purge or audit expired keys with configurable callbacks
  • 🧰 Provisioning & Revocation – Issue, inspect, or revoke license keys in real-time

⚙️ Storage Setup

Custom Storage

You can configure a custom storage backend with setStorage.

lock.setStorage({
     get     : async (key) => { /* retrieve */ },
     set     : async (key, value) => { /* store */ },
     delete  : async (key) => { /* remove */ },
     keys    : async () => { /* list keys */ }
}, {
     strict : false
});

Custom Callback Methods

| Key | Type | Description | |-----------|-------------------------------|----------------------------------------------| | get | (key) => Promise<value> | Retrieve a value by key | | set | (key, value) => Promise<void> | Store a key-value pair | | delete | (key) => Promise<void> | Delete a specific key | | keys | () => Promise<string[]> | Retrieve all stored keys |

setStorage Options

| Key | Type | Description | Default | |-----------|-----------|-----------------------------------------------|---------| | strict | boolean | Throw an error if found a missing a method | false |


🔐 Built-in Lockbox Shortcut

Use the built-in encrypted file storage engine with:

lock.setStorage({ path : "./lockbox" });

Full Lockbox Usage

lock.setStorage({
     path : "./lockbox",
     namespace : "my-service",
     encrypt : true,
     offset : "optional-entropy",
     lockprintOptions : {
          filename : ".device-id",
          printDNA : 64
     }
});

Equivalent to:

lock.setStorage(Lockline.lockbox("./lockbox", {
     namespace : "my-service",
     encrypt : true,
     offset : "optional-entropy",
     lockprintOptions : {
          filename : ".device-id",
          printDNA : 64
     }
}));

Lockbox Options

| Key | Type | Description | Default | |-------------------|------------|-----------------------------------------------------------------------------|---------------------------| | path | string | Root path for the lockbox storage | process.cwd()/lockbox | | namespace | string | Subfolder within the lockbox path | "default" | | encrypt | boolean | Enable lockbox encryption | true | | offset | string | Optional entropy used in secret derivation | "" | | lockprint | string | Provide a fixed fingerprint (skips auto generation) | null | | lockprintOptions| object | Options when generating a fingerprint if lockprint is not provided | {} |

lockprintOptions Fields

| Key | Type | Description | Default | |-------------|----------|--------------------------------------------------------|-----------------| | filename | string | File used to persist fingerprint | .fingerprint | | printDNA | number | Number of random bytes used for fingerprint generation | 32 |


🧠 Validator Management

| Method | Description | |--------------------------------|----------------------------------------------| | registerValidator(name, fn) | Register a custom validator by name | | setDefaultValidator(name) | Set the fallback validator if none defined |

Validator Function Signature

async function ({ key, input }) {
     return {
          valid : true,
          reason : "Optional message",
          raw : { any : "metadata" }
     };
}

🔐 License Key Workflow

| Method | Description | Async | |-------------------------|---------------------------------------------------------------|--------| | provisionKey(key, config) | Temporarily register a key for validation (in-memory) | ❌ | | validate(key, options) | Run validator chain against a key | ✅ | | sealKey(key, config, options)| Validate and persist enriched metadata to storage | ✅ | | inspectKey(key) | View current stored key metadata | ✅ | | revokeKey(key) | Delete key from storage | ✅ |


🔎 Validation Options

| Option | Type | Description | |------------------------|-----------|--------------------------------------------------------------------------| | recordAssumedValidation | boolean | Stores the assume validation metadata to the key | | assumePreviouslyValid | boolean | Trust stored key if validators are unreachable | | fallbackIfOffline | boolean | Allow fallback if offline (requires assumePreviouslyValid) | | autoRemoveExpired | boolean | Automatically remove key if expired | | storeInvalid | boolean | Store even if result is invalid | | metaFilter | Function| Custom function to filter extracted metadata |


🔏 Key Configuration

| Config Key | Type | Description | |------------------|------------------------|---------------------------------------------------------------| | validators | Array<{ name, input, fallback?, tag? }> | Chain of validator strategies | | validate | Function(results) | Custom reducer for validator results (default = AND) | | shortCircuit | boolean | Exit chain early if one validator fails | | meta | Object | Custom metadata (expiresAt, license tier, etc) |


🧹 Key Lifecycle

| Method | Description | Async | |------------------------|------------------------------------------------------------------|--------| | scanKeys({ filter }) | Returns keys by filter: "all", "valid", "expired" | ✅ | | auditExpiredKeys() | Returns list of expired keys with metadata | ✅ | | purgeExpiredKeys(cb) | Deletes expired keys, optionally invoking callback per key | ✅ |


🧭 License Scope Management

| Method | Description | Async | |-----------------------------------|-----------------------------------------------------------------------------|--------| | loadRecentLicenseKeys(groupBy?)| Loads most recently updated valid key per group and stores by scope | ✅ | | setCurrentLicenseKey(scope, key)| Manually set the active license key for a specific scope | ❌ | | getCurrentLicenseKey(scope?) | Retrieve the currently active license key for a given scope (default = "default") | ❌ | | touchLicenseKey(key) | Update a license key's lastUsedAt metadata to mark recent access | ✅ |

loadRecentLicenseKeys(groupBy?)

Scans all stored keys and selects the most recently updated valid key per logical group.
Groups are defined by the optional groupBy(meta) function (default returns "default").

Example

await lock.loadRecentLicenseKeys(meta => meta.module || "default");

const key = lock.getCurrentLicenseKey("analytics");

setCurrentLicenseKey(scope, key)

Manually assign a license key to a specific logical scope.

lock.setCurrentLicenseKey("videoEditor", "ACCESS-VID-123");

getCurrentLicenseKey(scope?)

Returns the current license key for the given scope. Defaults to "default".

const key = lock.getCurrentLicenseKey(); // returns key for "default"

touchLicenseKey(key)

Updates the lastUsedAt timestamp in storage for the license key.

await lock.touchLicenseKey("ACCESS-XYZ");

Use this in protected methods to track key usage and improve recent-key prioritization.


🛡️ License Protection Wrapper

| Method | Description | |-------------------------------|------------------------------------------------------------------| | withLicenseProtection(fn, scope?, options?) | Wrap a function to enforce license validation per scope |

Options Object

| Key | Type | Description | |--------------------|------------|-----------------------------------------------------------------------------| | onMissingKey | Function | Called if no license key found for the given scope | | onInvalidKey | Function | Called if the license invalid or expired | | onSuccess | Function | Called if the license valid and access granted | | onLicenseBlocked | Function | Called if access blocked; return fallback |

Example

lock.setStorage({ path : "./lockbox" });
await lock.loadRecentLicenseKeys();

const protectedExport = lock.withLicenseProtection(() => {
     return { success : true, data : "Exported data" };
}, "analytics", {
     onLicenseBlocked : () => ({ error : "License required to access this feature." }),
     onSuccess : () => console.log("🔓 License valid"),
     onInvalidKey : () => console.warn("❌ Invalid license"),
     onMissingKey : () => console.warn("⚠️ No license key loaded")
});

await protectedExport(); // Only runs if valid license valid

📦 Installation

npm install @trap_stevo/lockline

🛠️ Constructor

const Lockline = require("@trap_stevo/lockline");

const lock = new Lockline();

💡 Example Usage

Set storage and default validator

lock.setStorage({ path : "./lockbox" });

/*
If you want explicit control ~

lock.setStorage(lock.lockbox("./lockbox", {
     namespace : "keys",
     namespace : "keys",
     encrypt : true,
     offset : 7,
     lockprint : "CUSTOM-LOCKPRINT-1234"
}));
*/

Register a validator

lock.registerValidator("isAccessKey", async ({ key }) => {
     return {
          valid : key.startsWith("ACCESS-"),
          reason : "Must start with ACCESS-",
          raw : { region : "EU" }
     };
});

Set default validator

lock.setDefaultValidator("isAccessKey");

Provision and validate

lock.provisionKey("ACCESS-123", {
     validators : [{ name : "isAccessKey" }],
     meta : { expiresAt : Date.now() + 1000 * 60 * 60 }
});

const result = await lock.validate("ACCESS-123");
console.log(result.valid); // true

Seal to storage

await lock.sealKey("ACCESS-123", {
     validators : [{ name : "isAccessKey" }],
     meta : { licenseTier : "pro", expiresAt : Date.now() + 7 * 86400000 }
});

Purge expired

await lock.purgeExpiredKeys((key, meta) => {
     console.log(`Deleted expired key: ${key}`);
});

📜 License

See License in LICENSE.md


🔐 Lock Down. Unlock Possibilities.

Lockline gives you the tools to craft smart, trusted, resilient licensing workflows that adapt to your software’s ecosystem — from CLI tools to full SaaS systems. Empower validation logic that evolves with you.