UNPKG

@licensehub/license-client

Version:

TypeScript license management client for protecting and monetizing proprietary software

530 lines (511 loc) 19.4 kB
/** * License activation status enum (mirrored from server) * - active: The activation is currently valid and operational * - revoked: The activation has been revoked * - deleted: The activation has been deleted */ export declare enum EnumLicenseActivationStatus { ACTIVE = "active", REVOKED = "revoked", DELETED = "deleted" } /** * License status enum (mirrored from server) * - pending: The license is pending activation. Users cannot utilize any features or services associated with this license until it is activated. * - active: The license is currently valid and operational. Users can utilize all features or services associated with this license. * - expired: The license has expired. Users can no longer utilize any features or services associated with this license. * - inactive: The license has been deactivated. Users can no longer utilize any features or services associated with this license. * - revoked: The license has been revoked. Users can no longer utilize any features or services associated with this license. * - deleted: The license has been deleted. Users can no longer utilize any features or services associated with this license. */ export declare enum EnumLicenseStatus { PENDING = "pending", ACTIVE = "active", EXPIRED = "expired", INACTIVE = "inactive", REVOKED = "revoked", DELETED = "deleted" } /** * License Client Enums * * This file contains all enums used by the License Client, including: * - Client-specific message codes and texts * - Server response message codes and texts (mirrored from server) * - License status enums * - License activation status enums */ /** * Message Code Enum * * Defines all message codes used by the license client for error handling and responses. * Includes both client-specific codes and server response codes. */ export declare enum EnumMessageCode { SUCCESS = "SUCCESS", MISSING_LICENSE_DATA = "MISSING_LICENSE_DATA", MISSING_FEATURES = "MISSING_FEATURES", REQUEST_FAILED = "REQUEST_FAILED", NETWORK_ERROR = "NETWORK_ERROR", LICENSE_NOT_FOUND = "LICENSE_NOT_FOUND", LICENSE_EXPIRED = "LICENSE_EXPIRED", LICENSE_DISABLED = "LICENSE_DISABLED", INVALID_DOMAIN = "INVALID_DOMAIN", ACTIVATION_LIMIT_REACHED = "ACTIVATION_LIMIT_REACHED", INVALID_LICENSE_TYPE = "INVALID_LICENSE_TYPE", LICENSE_ALREADY_ACTIVATED = "LICENSE_ALREADY_ACTIVATED", LICENSE_NOT_ACTIVATED = "LICENSE_NOT_ACTIVATED", INVALID_RESPONSE = "INVALID_RESPONSE", INVALID_JSON_FORMAT = "invalid_json_format", EXCEPTION = "exception", LICENSE_PENDING = "license_pending", LICENSE_INACTIVE = "license_inactive", LICENSE_REVOKED = "license_revoked", LICENSE_DELETED = "license_deleted", LICENSE_INVALID_STATUS = "license_invalid_status", MAX_ACTIVATIONS_REACHED = "max_activations_reached", INVALID_ACTIVATION = "invalid_activation", ACTIVATION_REVOKED = "activation_revoked", ACTIVATION_DELETED = "activation_deleted", ACTIVATION_INVALID_STATUS = "activation_invalid_status", ACTIVATION_FAILED = "activation_failed", LICENSE_TYPE_NOT_FOUND = "license_type_not_found" } /** * Message source enum (mirrored from server) */ export declare enum EnumMessageSource { REQUEST = "request", RESPONSE = "response" } /** * Message Text Enum * * Human-readable messages corresponding to message codes. * Provides descriptive text for both client errors and server responses. */ export declare enum EnumMessageText { SUCCESS = "Operation completed successfully.", MISSING_LICENSE_DATA = "License key and/or domain are required.", MISSING_FEATURES = "Missing required features.", REQUEST_FAILED = "The server request failed.", NETWORK_ERROR = "A network error occurred. Please check your connection.", LICENSE_NOT_FOUND = "License key not found.", LICENSE_EXPIRED = "License has expired.", LICENSE_DISABLED = "License is disabled.", INVALID_DOMAIN = "Invalid domain for this license.", ACTIVATION_LIMIT_REACHED = "Activation limit reached.", INVALID_LICENSE_TYPE = "Invalid license type.", LICENSE_ALREADY_ACTIVATED = "License is already activated for this domain.", LICENSE_NOT_ACTIVATED = "License is not activated for this domain.", UNKNOWN_ERROR = "Unknown error", INVALID_JSON_FORMAT = "Invalid JSON format", LICENSE_PENDING = "License is pending activation", LICENSE_INACTIVE = "License is inactive", LICENSE_REVOKED = "License has been revoked", LICENSE_DELETED = "License has been deleted", LICENSE_INVALID_STATUS = "License has an invalid status", MAX_ACTIVATIONS_REACHED = "Maximum number of activations reached", INVALID_ACTIVATION = "Invalid activation conditions", ACTIVATION_REVOKED = "Activation has been revoked", ACTIVATION_DELETED = "Activation has been deleted", ACTIVATION_INVALID_STATUS = "Activation has an invalid status", ACTIVATION_FAILED = "Activation failed", LICENSE_TYPE_NOT_FOUND = "License type not found" } /** * Client for interacting with the license server. * Supports offline validation via JWT caching and automatic public key fetching. * * @example * ```typescript * const client = new LicenseClient({ * LICENSE_SERVER_URL: 'https://license.example.com/api/v1', * // LICENSE_PUBLIC_KEY is optional; it will be fetched if not provided. * }); * * const response = await client.validate({ * licenseKey: 'YOUR_LICENSE_KEY', * domain: 'your-domain.com', * }); * * if (response.success) { * console.log('License is valid!', response.data); * } * ``` */ export declare class LicenseClient { /** * Creates a new LicenseClient instance. * @param {TypeLicenseClientOptions} options - The configuration for the client * @throws {Error} When required configuration is missing or invalid */ constructor(options: TypeLicenseClientOptions); /** * Activates a license key with the server. * @param {TypeLicensePayload} [payload] - The license data to activate. Uses the default if not provided * @param {string[]} [requiredFeatures] - Optional array of features that must be available in the license * @returns {Promise<TypeResponse>} The server's response containing activation details * @throws {Error} When payload is missing and no default is set */ activate(payload?: TypeLicensePayload, requiredFeatures?: string[]): Promise<TypeResponse>; /** * Clears all cached data including JWT tokens, operation results, and public key. * * WHY simplified clearing: With IntegrityCache used everywhere, we can clear * all cached data through the single cache instance, making the logic much simpler. * * Useful for logout scenarios or when switching between different license contexts. * @returns {Promise<void>} */ clearAllCaches(): Promise<void>; /** * Deactivates a license key on the server. This also clears any cached JWT for the license. * @param {TypeLicensePayload} [payload] - The license data to deactivate. Uses the default if not provided * @returns {Promise<TypeResponse>} The server's response confirming deactivation * @throws {Error} When payload is missing and no default is set */ deactivate(payload?: TypeLicensePayload): Promise<TypeResponse>; /** * Sets a default license payload for subsequent method calls. * This invalidates the cached validation response for the previous license context only. * @param {TypeLicensePayload} payload - The license data to use as a default */ setLicensePayload(payload: TypeLicensePayload): void; /** * Validates a license key. It first attempts to use cached validation response, * then offline validation using a cached JWT, and finally falls back to server validation. * Uses periodic server validation to catch license abuse at unpredictable intervals. * @param {TypeLicensePayload} [payload] - The license data to validate. Uses the default if not provided * @param {string[]} [requiredFeatures] - Optional array of features that must be available in the license * @returns {Promise<TypeResponse>} The validation result with license details * @throws {Error} When payload is missing and no default is set */ validate(payload?: TypeLicensePayload, requiredFeatures?: string[]): Promise<TypeResponse>; } /** * Singleton wrapper for LicenseClient. * Provides a global access point to a single LicenseClient instance. * * @example * ```typescript * // Set the instance first * const client = new LicenseClient({ * LICENSE_SERVER_URL: 'https://license.example.com/api/v1' * }); * LicenseClientSingleton.setInstance(client); * * // Later, get the instance anywhere in your app * const client = LicenseClientSingleton.getInstance(); * if (client) { * const response = await client.validate({ licenseKey: 'key' }); * } * ``` */ export declare class LicenseClientSingleton { /** * Gets the singleton instance. * @returns {LicenseClient | undefined} The LicenseClient instance, or undefined if not set. */ static getInstance(): LicenseClient | undefined; /** * Sets the singleton instance. * @param {LicenseClient} client - The LicenseClient instance to use as singleton. */ static setInstance(client: LicenseClient): void; } /** * Complete JWT structure with typed header and payload. * Used when we need to work with the complete decoded JWT structure. */ export declare interface TypeDecodedJwt<T = TypeLicenseJwtPayload> { /** * JWT header containing algorithm and type information */ header: TypeJwtHeader; /** * JWT payload containing claims and license data */ payload: T; /** * JWT signature (when available from verification) */ signature?: string; } /** * Default response data type for license operations * Contains token, public key, and source information with extensible properties */ export declare interface TypeDefaultResponseData { token?: string; publicKey?: string; source?: 'cache' | 'server'; features?: string[]; [key: string]: unknown; } /** * Error response interface for failed operations * Always has success: false and required messages array */ export declare interface TypeErrorResponse extends TypeResponse<undefined> { success: false; messages: TypeMessage[]; } /** * JWT Header interface. * Represents the JWT header structure. */ export declare interface TypeJwtHeader { /** * Algorithm used to sign the JWT (e.g., 'RS256', 'HS256') */ alg: string; /** * Token type (typically 'JWT') */ typ: string; /** * Key ID hint indicating which key was used to secure the JWS */ kid?: string; } /** * JWT Payload Type Definitions * * Type definitions for JWT token structures used in the License Client. * These types ensure proper typing when decoding JWT tokens. */ /** * Standard JWT claims interface. * Based on RFC 7519 JWT standard claims. */ export declare interface TypeJwtStandardClaims { /** * Issuer claim (iss) - identifies the principal that issued the JWT */ iss?: string; /** * Subject claim (sub) - identifies the principal that is the subject of the JWT */ sub?: string; /** * Audience claim (aud) - identifies the recipients that the JWT is intended for */ aud?: string | string[]; /** * Expiration Time claim (exp) - identifies the expiration time on or after which the JWT MUST NOT be accepted */ exp?: number; /** * Not Before claim (nbf) - identifies the time before which the JWT MUST NOT be accepted */ nbf?: number; /** * Issued At claim (iat) - identifies the time at which the JWT was issued */ iat?: number; /** * JWT ID claim (jti) - provides a unique identifier for the JWT */ jti?: string; } /** * License Client - Configuration Options Type * * Configuration options for the LicenseClient. * * **Cache Types:** * - `memory-cache` (default): In-memory caching, works everywhere, no setup required * - `cloudflare-cache`: For Cloudflare Workers/Edge environments (+3 kB bundle size) * - `upstash-redis-cache`: For serverless Redis environments (+138 kB bundle size) * - `redis-cache`: For traditional Redis setups (+743 kB bundle size) * * **Enabling Additional Cache Types:** * To use cache types other than memory cache, uncomment the corresponding import * in the LicenseClient source code: * ```typescript * // In LicenseClient.ts, uncomment the desired cache type: * import '@cachehub/cloudflare-cache'; // For Cloudflare Workers/Edge * import '@cachehub/upstash-redis-cache'; // For serverless Redis * import '@cachehub/redis-cache'; // For traditional Redis * ``` * * @example * ```typescript * // Memory cache (default) - works out of the box * const options: TypeLicenseClientOptions = { * LICENSE_SERVER_URL: 'https://license-server.example.com/api/v1', * LICENSE_PUBLIC_KEY: '-----BEGIN PUBLIC KEY-----...', * CACHE_TYPE: 'memory-cache' // or omit for default * }; * * // Cloudflare cache (requires enabling cloudflare-cache import) * const cloudflareOptions: TypeLicenseClientOptions = { * LICENSE_SERVER_URL: 'https://license-server.example.com/api/v1', * LICENSE_PUBLIC_KEY: '-----BEGIN PUBLIC KEY-----...', * CACHE_TYPE: 'cloudflare-cache', * CACHE_BASE_URL: 'https://api.cloudflare.com/client/v4', * CACHE_NAME: 'my-cache' * }; * * // Upstash Redis cache (requires enabling upstash-redis-cache import) * const upstashOptions: TypeLicenseClientOptions = { * LICENSE_SERVER_URL: 'https://license-server.example.com/api/v1', * LICENSE_PUBLIC_KEY: '-----BEGIN PUBLIC KEY-----...', * CACHE_TYPE: 'upstash-redis-cache', * CACHE_REDIS_URL: 'https://your-redis-url.upstash.io', * CACHE_REDIS_TOKEN: 'your-redis-token', * CACHE_KEY_PREFIX: 'license:' * }; * * // Traditional Redis cache (requires enabling redis-cache import) * const redisOptions: TypeLicenseClientOptions = { * LICENSE_SERVER_URL: 'https://license-server.example.com/api/v1', * LICENSE_PUBLIC_KEY: '-----BEGIN PUBLIC KEY-----...', * CACHE_TYPE: 'redis-cache', * CACHE_REDIS_URL: 'redis://localhost:6379' * }; * ``` */ export declare interface TypeLicenseClientOptions { /** * The base URL of the license server API. * @example 'https://license-server.example.com/api/v1' */ LICENSE_SERVER_URL: string; /** * The public key used to verify JWT tokens (optional). * If not provided, the client will contact the server for validation. * @example '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n-----END PUBLIC KEY-----' */ LICENSE_PUBLIC_KEY?: string; /** * The type of cache to use for storing JWT tokens. * @default 'memory-cache' * @example 'memory-cache', 'cloudflare-cache', 'upstash-redis-cache', 'redis-cache' */ CACHE_TYPE?: string; /** * Redis server URL (required for redis-cache and upstash-redis-cache). * @example 'redis://localhost:6379' or 'https://your-redis-url.upstash.io' */ CACHE_REDIS_URL?: string; /** * Redis authentication token (required for upstash-redis-cache). * @example 'your-redis-token' */ CACHE_REDIS_TOKEN?: string; /** * Optional prefix for cache keys (used by upstash-redis-cache). * @example 'license:' */ CACHE_KEY_PREFIX?: string; /** * Minimum hours between forced server validations (default: 6). * @example 1 */ VALIDATION_MIN_INTERVAL_HOURS?: number; /** * Maximum hours between forced server validations (default: 24). * @example 48 */ VALIDATION_MAX_INTERVAL_HOURS?: number; /** * Probability (0-1) of forcing server validation on each check (default: 0.1). * Set to 0 to disable probabilistic validation for testing. * @example 0.05 */ VALIDATION_PROBABILITY?: number; /** * Cloudflare API base URL (required for cloudflare-cache). * @example 'https://api.cloudflare.com/client/v4' */ CACHE_BASE_URL?: string; /** * Cloudflare cache name (optional for cloudflare-cache). * @example 'my-cache' */ CACHE_NAME?: string; } /** * License Information Interface * * Represents comprehensive license information extracted from JWT tokens * including features, expiration, validity status, and license metadata. */ /** * Complete license information extracted from JWT token * * @interface TypeLicenseInfo */ export declare interface TypeLicenseInfo { /** Array of feature strings available in this license */ features: string[]; /** Whether the license token is currently valid (has cached token) */ isValid: boolean; /** Type/tier of the license (e.g., 'basic', 'professional', 'enterprise') */ licenseType?: string; /** Domain this license is valid for (from JWT audience claim) */ domain?: string; /** Date when the license expires */ expiresAt?: Date; } /** * License-specific JWT payload interface. * Extends standard JWT claims with license-specific data. */ export declare interface TypeLicenseJwtPayload extends TypeJwtStandardClaims { /** * License features array. * Contains the list of features available in this license. */ features?: string[]; /** * License key identifier. * The license key this token was issued for. */ licenseKey?: string; /** * License type identifier. * The type/tier of license this token represents. */ licenseType?: string; /** * Custom license metadata. * Additional license-specific data that may be included in the token. */ metadata?: Record<string, unknown>; /** * Tenant identifier for multi-tenant licenses. * Identifies which tenant this license belongs to. */ tenantId?: string | number; } /** * License Client - License Payload Type * * Payload for license operations (activate, validate, deactivate) */ export declare interface TypeLicensePayload { licenseKey: string; domain?: string; subdomain?: string; ipAddress?: string; } /** * Message interface for API responses */ export declare interface TypeMessage { code: EnumMessageCode; text: string; } /** * Generic response interface for all API operations * @template T - The type of data returned in the response (defaults to TypeDefaultResponseData) */ export declare interface TypeResponse<T = TypeDefaultResponseData> { success: boolean; messages?: TypeMessage[]; data?: T; } export { }