@paylock/node
v0.1.2
Published
The official Node.js SDK for Paylock — designed to enforce license validation, secure your SaaS projects, and manage injectables, domains, and subscriptions effortlessly. Built for modern JavaScript and TypeScript environments.
Maintainers
Readme
🔒 Paylock Node SDK
The official Node.js SDK for Paylock — designed to enforce license validation, secure your SaaS projects, and manage injectables, domains, and subscriptions effortlessly. Built for modern JavaScript and TypeScript environments.
🌟 Why Paylock?
Paylock provides the infrastructure to protect your intellectual property and enforce subscription compliance without the complexity of building it yourself.
- ✅ Bulletproof Validation — Real-time license key verification.
- 🔐 Dynamic Injectables — Securely deliver encrypted assets (configs, binaries, tokens) only to authorized users.
- 🌐 Domain Locking — Prevent unauthorized distribution by restricting usage to specific domains.
- 📡 Service-First — Modular API access for projects, licenses, and payments.
- 🧩 Ultra Flexible — Framework-agnostic and fully customizable failure behaviors.
📦 Installation
Get started in seconds with your favorite package manager.
Using npm:
npm install @paylock/nodeUsing yarn:
yarn add @paylock/nodeNote: Requires Node.js v14+ and works seamlessly with TypeScript.
🚀 Quick Start
Initialize Paylock at the entry point of your application to start enforcing security immediately.
import { Paylock } from '@paylock/node';
Paylock.bootstrap({
license: 'your-license-key-here',
secret: 'your-secret-key', // for injectables
base_url: 'https://api.paylock.ng',
action: 'boot',
injectables: true,
onReady: (response) => {
console.log('✅ License Valid:', response);
},
invalidBehavior: 'modal', // or 'redirect', 'silent', 'log'
});If a license is invalid or unpaid, Paylock takes over based on your invalidBehavior setting — keeping your application secure by default.
⚙️ Configuration Options
Tailor the SDK to your specific needs.
Core Settings
| Key | Type | Description |
|------------|----------|-------------------------------------------------------|
| base_url | string | Your API base URL (e.g., https://api.paylock.ng) |
| secret | string | AES-256-CBC key for decrypting injectables |
Behavioral Settings
| Key | Type | Description |
|--------------------------|------------|----------------------------------------------------------------------------------------|
| license | string | The license key to validate. |
| api_key | string | API key for administrative or project-scoped access. |
| recheck | boolean | Force revalidation instead of using local cache. (true by default) |
| action | string | Tracking tag for the validation request (e.g. 'boot'). |
| timeout | number | HTTP request timeout in ms (1000 default). |
| per_page | number | Items per page for paginated API results. |
| injectables | boolean | Enable/disable injectable fetching (true by default). |
| injectablesVerify | boolean | Enable HMAC integrity checks (true by default). |
| injectablesPath | string | Local directory to store processed injectables. |
| handleInjectables | boolean | Auto-process and store injectables upon validation. |
| injectablesProcessor | function | Your custom logic for handling injectables. |
| invalidBehavior | string | 'modal' (default), 'redirect', 'log', or 'silent'. |
| redirectUrl | string | Target URL for the 'redirect' behavior. |
| customInvalidMessage | string | A custom message to show when validation fails. |
| customInvalidView | string | Path to a custom HTML template for the blocking view. |
| onReady | function | Success callback after validation. |
🛠 Service API Access
Need more control? Access the Paylock core services directly once bootstrapped.
import { Paylock } from '@paylock/node';
const projectService = Paylock.projects();
const licenseService = Paylock.licenses();
const domainService = Paylock.domains();
const injectableService = Paylock.injectables();
const paymentService = Paylock.payments();Available Methods
| Service | Methods |
|------------------|----------------------------------------------------------------------|
| projects() | list(), create(), show(), update(), delete() |
| licenses() | list(), show(), create(), revoke(), reactivate(), delete() |
| domains() | list(), create(), show(), update(), delete() |
| injectables() | list(), create(), show(), update(), delete(), stream() |
| payments() | checkWithLicenseKey(), checkWithApiKey() |
📦 Handling Injectables
Injectables are encrypted assets (scripts, blobs, configs) tied to a license. They are securely streamed and can be automatically processed.
Custom Processing
Override the default behavior to handle assets your way:
Paylock.bootstrap({
license: 'your-license-key',
secret: 'your-encryption-secret',
injectables: true,
handleInjectables: true,
injectablesProcessor: (injectable, secret, basePath, verify) => {
// Decrypt, verify, and save or handle it however you want
return `/custom/path/${injectable.name}`;
},
});Signature Verification
For maximum security, always keep verification enabled.
Paylock.bootstrap({
// ...
injectablesVerify: true // Ensure integrity check is enabled
});⚠️ Warning: Disabling verification (
injectablesVerify: false) exposes your app to tampered assets.
🔐 Security & Crypto Utilities
Access the underlying cryptographic engine for your own custom security workflows.
CryptoHelper
High-level encryption/decryption using AES-256-CBC.
Decrypting:
import { CryptoHelper } from '@paylock/node';
const decrypted = CryptoHelper.decrypt(encryptedString, secretKey);Encrypting:
const encrypted = CryptoHelper.encrypt('Hello World', secretKey);HashHelper
Secure hashing and HMAC signatures.
Generate:
const hash = HashHelper.hash('some content');
const signature = HashHelper.signature('content', secret);Verify:
HashHelper.verifyHash(content, expectedHash); // returns true/false
HashHelper.verifySignature(content, secret, sig); // returns true/false🚨 Error Handling & Failure Modes
Paylock gives you full control over what happens when things go wrong.
Failure Behaviors
| Mode | Action |
|---|---|
| modal | (Default) Shows a beautiful, non-bypassable HTML modal. |
| redirect | Forces a browser redirect to your upgrade page. |
| log | Simply logs the failure to the console. |
| silent | Keeps quiet—allowing you to handle the logic manually. |
invalidBehavior: 'redirect',
redirectUrl: 'https://yourdomain.com/upgrade',
customInvalidMessage: 'Your license is no longer valid.',
customInvalidView: '/views/custom-unlicensed.html'Catching Exceptions
For fine-grained control, use standard try/catch blocks.
try {
await Paylock.bootstrap({ ... });
} catch (error) {
if (error instanceof LicenseValidationException) {
console.warn('Invalid license:', error.message);
} else if (error instanceof HttpRequestException) {
console.error('API error:', error.statusCode, error.responseBody);
} else {
console.error('Unknown Paylock error:', error.message);
}
}🧪 Real-World Examples
We've included a variety of ready-to-use examples in the src/examples/ folder.
Basic Validation (validateLicense.ts)
import { Paylock } from '../core/Paylock';
Paylock.bootstrap({
license: 'your-license-key-here',
base_url: 'https://api.paylock.ng',
injectables: true,
debug: true,
secret: '',
timeout: 5000,
invalidBehavior: 'log',
onReady: (data: any) => {
console.log('✅ License validated successfully:', data.data);
}
});Run it locally:
npm run example🧠 Advanced Concepts
Direct Service Access
If you don't need runtime validation, you can use services as a standalone API client.
import { LicenseService, Config } from '@paylock/node';
const config = new Config({
api_key: 'your-api-key-here',
base_url: 'https://api.paylock.ng',
});
const licenses = new LicenseService(config);
licenses.list(1234).then(result => {
console.log('Licenses:', result);
});Headless/CLI Environments
For non-browser contexts, use the silent behavior:
invalidBehavior: 'silent'Custom Injectable Processors
Define how your application consumes delivered assets.
Type Definitions:
type InjectableProcessor = (injectable: InjectablePayload) => void | Promise<void>;Interface Structure:
interface InjectableProcessor {
handle(
injectable: InjectablePayload,
secret: string,
basePath: string,
verifySignature?: boolean
): string | Promise<string>;
}Payload Data:
interface InjectablePayload {
name: string; // Unique name for the blob
mode: 'append' | 'prepend' | 'replace'; // How to apply the content
content: string; // Decrypted content
signature: string; // HMAC-SHA256 signature
targetPath?: string; // Optional target path from backend
[key: string]: any; // Additional metadata
}Implementation Example:
import { InjectablePayload, InjectableProcessor } from '@paylock/node';
import { promises as fs } from 'fs';
import { join } from 'path';
export class MyInjectableSaver implements InjectableProcessor {
async handle(
injectable: InjectablePayload,
secret: string,
basePath: string,
verifySignature = true
): Promise<string> {
const filePath = join(basePath, injectable.name + '.txt');
await fs.writeFile(filePath, injectable.content, 'utf8');
return filePath;
}
}Enabling Your Processor:
import { Paylock } from '@paylock/node';
import { MyInjectableSaver } from './MyInjectableSaver';
Paylock.bootstrap({
license: 'your-license-key',
secret: 'your-shared-secret',
handleInjectables: true,
injectablesProcessor: new MyInjectableSaver()
});Manual Verification & Decryption:
import { InjectablePayload, CryptoHelper, HashHelper } from '@paylock/node';
export async function customInjectableProcessor(
injectable: InjectablePayload,
secret: string,
basePath: string,
verifySignature = true
): Promise<string> {
// 🔏 Verify signature
if (verifySignature && !HashHelper.verifySignature(injectable.content, secret, injectable.signature)) {
throw new Error('Invalid HMAC signature — injectable may have been tampered with.');
}
// 🔐 Decrypt content
const decrypted = CryptoHelper.decrypt(injectable.content, secret);
console.log(`Injectable ${injectable.name} verified and decrypted:`, decrypted);
return injectable.name;
}⚡ TypeScript First
Paylock is built with TypeScript from the ground up, providing a first-class developer experience.
"types": "dist/index.d.ts"Typed Response Example:
import { Paylock, LicenseService } from '@paylock/node';
Paylock.bootstrap({
license: 'your-license',
secret: 'your-secret',
injectables: true,
onReady: (response) => {
// Fully typed response structure
console.log('Validated license data:', response.data);
}
});
const licenseService: LicenseService = Paylock.licenses();📄 License
MIT © paylockHQ
