ironlicensing-js/src/storage.ts

173 lines
4.0 KiB
TypeScript

import type { License, LicenseResult } from './types';
/**
* Storage interface for license caching.
*/
export interface StorageAdapter {
get(key: string): string | null;
set(key: string, value: string): void;
remove(key: string): void;
}
/**
* In-memory storage adapter.
*/
export class MemoryStorage implements StorageAdapter {
private data: Map<string, string> = new Map();
get(key: string): string | null {
return this.data.get(key) ?? null;
}
set(key: string, value: string): void {
this.data.set(key, value);
}
remove(key: string): void {
this.data.delete(key);
}
}
/**
* LocalStorage adapter for browser.
*/
export class LocalStorageAdapter implements StorageAdapter {
get(key: string): string | null {
try {
return localStorage.getItem(key);
} catch {
return null;
}
}
set(key: string, value: string): void {
try {
localStorage.setItem(key, value);
} catch {
// Ignore storage errors
}
}
remove(key: string): void {
try {
localStorage.removeItem(key);
} catch {
// Ignore storage errors
}
}
}
/**
* License cache manager.
*/
export class LicenseCache {
private storage: StorageAdapter;
private keyPrefix: string;
constructor(storage: StorageAdapter, keyPrefix: string = 'ironlicensing') {
this.storage = storage;
this.keyPrefix = keyPrefix;
}
private key(name: string): string {
return `${this.keyPrefix}:${name}`;
}
/**
* Gets the cached license.
*/
getLicense(): License | null {
const data = this.storage.get(this.key('license'));
if (!data) return null;
try {
const parsed = JSON.parse(data);
// Restore Date objects
if (parsed.expiresAt) parsed.expiresAt = new Date(parsed.expiresAt);
if (parsed.createdAt) parsed.createdAt = new Date(parsed.createdAt);
if (parsed.lastValidatedAt) parsed.lastValidatedAt = new Date(parsed.lastValidatedAt);
return parsed;
} catch {
return null;
}
}
/**
* Sets the cached license.
*/
setLicense(license: License): void {
this.storage.set(this.key('license'), JSON.stringify(license));
}
/**
* Gets the cached validation result.
*/
getValidationResult(): LicenseResult | null {
const data = this.storage.get(this.key('validation'));
if (!data) return null;
try {
const parsed = JSON.parse(data);
if (parsed.license) {
if (parsed.license.expiresAt) parsed.license.expiresAt = new Date(parsed.license.expiresAt);
if (parsed.license.createdAt) parsed.license.createdAt = new Date(parsed.license.createdAt);
if (parsed.license.lastValidatedAt) parsed.license.lastValidatedAt = new Date(parsed.license.lastValidatedAt);
}
return parsed;
} catch {
return null;
}
}
/**
* Sets the cached validation result.
*/
setValidationResult(result: LicenseResult, timestamp: Date): void {
this.storage.set(this.key('validation'), JSON.stringify(result));
this.storage.set(this.key('validation_time'), timestamp.toISOString());
}
/**
* Gets the validation timestamp.
*/
getValidationTime(): Date | null {
const data = this.storage.get(this.key('validation_time'));
if (!data) return null;
return new Date(data);
}
/**
* Gets the stored license key.
*/
getLicenseKey(): string | null {
return this.storage.get(this.key('license_key'));
}
/**
* Sets the license key.
*/
setLicenseKey(key: string): void {
this.storage.set(this.key('license_key'), key);
}
/**
* Clears all cached data.
*/
clear(): void {
this.storage.remove(this.key('license'));
this.storage.remove(this.key('validation'));
this.storage.remove(this.key('validation_time'));
this.storage.remove(this.key('license_key'));
}
}
/**
* Gets the default storage adapter based on environment.
*/
export function getDefaultStorage(): StorageAdapter {
if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
return new LocalStorageAdapter();
}
return new MemoryStorage();
}