@nice2dev/licensing 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/SeatManager.ts","../src/UsageTelemetry.ts","../src/SourceAccessControl.ts","../src/ApiRateLimiter.ts","../src/WhiteLabel.ts","../src/SlaTracker.ts","../src/AuditTrail.ts","../src/portal/LicensePortal.tsx","../src/portal/ActivationWizard.tsx","../src/portal/LicenseTransfer.tsx","../src/billing/BillingIntegration.ts","../src/analytics/UsageAnalyticsDashboard.tsx","../src/refunds/RefundSystem.ts","../src/build/LicenseBuildPlugin.ts","../src/ci/CILicenseCheck.ts","../src/index.ts"],"sourcesContent":["/* ────────────────────────────────────────────────────────────────\r\n Seat Manager — License seat counting and management\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport { generateMachineId } from './HardwareFingerprint';\r\nimport type { LicenseKey, LicenseInfo, SeatInfo, MachineId } from './types';\r\n\r\n/** Seat activity timeout (30 minutes) */\r\nconst SEAT_TIMEOUT_MS = 30 * 60 * 1000;\r\n\r\n/** Heartbeat interval (5 minutes) */\r\nconst HEARTBEAT_INTERVAL_MS = 5 * 60 * 1000;\r\n\r\n/**\r\n * Seat Manager for tracking license usage\r\n */\r\nexport class SeatManager {\r\n private serverUrl: string;\r\n private apiKey?: string;\r\n private heartbeatInterval?: ReturnType<typeof setInterval>;\r\n private currentSeat?: SeatInfo;\r\n\r\n constructor(serverUrl: string, apiKey?: string) {\r\n this.serverUrl = serverUrl;\r\n this.apiKey = apiKey;\r\n }\r\n\r\n /**\r\n * Acquire a seat for the current user\r\n */\r\n async acquireSeat(\r\n licenseKey: LicenseKey,\r\n userId: string,\r\n displayName: string,\r\n email: string,\r\n ): Promise<{ success: boolean; seat?: SeatInfo; error?: string }> {\r\n const machineId = await generateMachineId();\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/seats/acquire`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n userId,\r\n displayName,\r\n email,\r\n machineId,\r\n }),\r\n });\r\n\r\n const data = await response.json();\r\n\r\n if (!response.ok) {\r\n return {\r\n success: false,\r\n error: data.error || 'Failed to acquire seat',\r\n };\r\n }\r\n\r\n this.currentSeat = data.seat;\r\n this.startHeartbeat(licenseKey);\r\n\r\n return {\r\n success: true,\r\n seat: data.seat,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: 'Network error',\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Release current seat\r\n */\r\n async releaseSeat(licenseKey: LicenseKey): Promise<boolean> {\r\n if (!this.currentSeat) {\r\n return true;\r\n }\r\n\r\n this.stopHeartbeat();\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/seats/release`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n seatId: this.currentSeat.seatId,\r\n }),\r\n });\r\n\r\n if (response.ok) {\r\n this.currentSeat = undefined;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get all active seats for a license\r\n */\r\n async getActiveSeats(licenseKey: LicenseKey): Promise<SeatInfo[]> {\r\n try {\r\n const response = await fetch(\r\n `${this.serverUrl}/seats/list?licenseKey=${encodeURIComponent(licenseKey)}`,\r\n {\r\n headers: {\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n },\r\n );\r\n\r\n if (!response.ok) {\r\n return [];\r\n }\r\n\r\n const data = await response.json();\r\n return data.seats || [];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Force release a seat (admin function)\r\n */\r\n async forceReleaseSeat(licenseKey: LicenseKey, seatId: string): Promise<boolean> {\r\n try {\r\n const response = await fetch(`${this.serverUrl}/seats/force-release`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n seatId,\r\n }),\r\n });\r\n\r\n return response.ok;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Check if seat limit is reached\r\n */\r\n async canAcquireSeat(license: LicenseInfo): Promise<boolean> {\r\n if (license.maxSeats === null) {\r\n return true;\r\n } // Unlimited\r\n\r\n const activeSeats = await this.getActiveSeats(license.key);\r\n return activeSeats.length < license.maxSeats;\r\n }\r\n\r\n /**\r\n * Start heartbeat to keep seat active\r\n */\r\n private startHeartbeat(licenseKey: LicenseKey): void {\r\n this.stopHeartbeat();\r\n\r\n this.heartbeatInterval = setInterval(async () => {\r\n if (!this.currentSeat) {\r\n this.stopHeartbeat();\r\n return;\r\n }\r\n\r\n try {\r\n await fetch(`${this.serverUrl}/seats/heartbeat`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n seatId: this.currentSeat.seatId,\r\n }),\r\n });\r\n } catch {\r\n // Heartbeat failed, seat may be released\r\n }\r\n }, HEARTBEAT_INTERVAL_MS);\r\n }\r\n\r\n /**\r\n * Stop heartbeat\r\n */\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Get current seat info\r\n */\r\n getCurrentSeat(): SeatInfo | undefined {\r\n return this.currentSeat;\r\n }\r\n\r\n /**\r\n * Cleanup on unmount/close\r\n */\r\n async cleanup(licenseKey: LicenseKey): Promise<void> {\r\n await this.releaseSeat(licenseKey);\r\n }\r\n}\r\n\r\n/**\r\n * Floating License Manager — for shared concurrent licenses\r\n */\r\nexport class FloatingLicenseManager {\r\n private serverUrl: string;\r\n private apiKey?: string;\r\n private leaseId?: string;\r\n private renewInterval?: ReturnType<typeof setInterval>;\r\n\r\n constructor(serverUrl: string, apiKey?: string) {\r\n this.serverUrl = serverUrl;\r\n this.apiKey = apiKey;\r\n }\r\n\r\n /**\r\n * Acquire a floating license\r\n */\r\n async acquireLease(licenseKey: LicenseKey): Promise<{\r\n success: boolean;\r\n leaseId?: string;\r\n expiresAt?: string;\r\n error?: string;\r\n }> {\r\n const machineId = await generateMachineId();\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/floating/acquire`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n machineId,\r\n }),\r\n });\r\n\r\n const data = await response.json();\r\n\r\n if (!response.ok) {\r\n return {\r\n success: false,\r\n error: data.error || 'No floating licenses available',\r\n };\r\n }\r\n\r\n this.leaseId = data.leaseId;\r\n this.startLeaseRenewal(licenseKey);\r\n\r\n return {\r\n success: true,\r\n leaseId: data.leaseId,\r\n expiresAt: data.expiresAt,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: 'Network error',\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Release floating license\r\n */\r\n async releaseLease(licenseKey: LicenseKey): Promise<boolean> {\r\n if (!this.leaseId) {\r\n return true;\r\n }\r\n\r\n this.stopLeaseRenewal();\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/floating/release`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n leaseId: this.leaseId,\r\n }),\r\n });\r\n\r\n if (response.ok) {\r\n this.leaseId = undefined;\r\n return true;\r\n }\r\n\r\n return false;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get floating license status\r\n */\r\n async getFloatingStatus(licenseKey: LicenseKey): Promise<{\r\n total: number;\r\n available: number;\r\n leases: Array<{ leaseId: string; machineId: MachineId; expiresAt: string }>;\r\n }> {\r\n try {\r\n const response = await fetch(\r\n `${this.serverUrl}/floating/status?licenseKey=${encodeURIComponent(licenseKey)}`,\r\n {\r\n headers: {\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n },\r\n );\r\n\r\n if (!response.ok) {\r\n return { total: 0, available: 0, leases: [] };\r\n }\r\n\r\n return response.json();\r\n } catch {\r\n return { total: 0, available: 0, leases: [] };\r\n }\r\n }\r\n\r\n /**\r\n * Start lease renewal interval\r\n */\r\n private startLeaseRenewal(licenseKey: LicenseKey): void {\r\n this.stopLeaseRenewal();\r\n\r\n // Renew every 2 minutes (leases typically last 5 minutes)\r\n this.renewInterval = setInterval(\r\n async () => {\r\n if (!this.leaseId) {\r\n this.stopLeaseRenewal();\r\n return;\r\n }\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/floating/renew`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}),\r\n },\r\n body: JSON.stringify({\r\n licenseKey,\r\n leaseId: this.leaseId,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n // Lease expired or revoked\r\n this.leaseId = undefined;\r\n this.stopLeaseRenewal();\r\n }\r\n } catch {\r\n // Network error, continue trying\r\n }\r\n },\r\n 2 * 60 * 1000,\r\n );\r\n }\r\n\r\n /**\r\n * Stop lease renewal\r\n */\r\n private stopLeaseRenewal(): void {\r\n if (this.renewInterval) {\r\n clearInterval(this.renewInterval);\r\n this.renewInterval = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Check if we have an active lease\r\n */\r\n hasActiveLease(): boolean {\r\n return !!this.leaseId;\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n async cleanup(licenseKey: LicenseKey): Promise<void> {\r\n await this.releaseLease(licenseKey);\r\n }\r\n}\r\n\r\n/** Create seat manager instance */\r\nexport function createSeatManager(serverUrl: string, apiKey?: string): SeatManager {\r\n return new SeatManager(serverUrl, apiKey);\r\n}\r\n\r\n/** Create floating license manager instance */\r\nexport function createFloatingLicenseManager(\r\n serverUrl: string,\r\n apiKey?: string,\r\n): FloatingLicenseManager {\r\n return new FloatingLicenseManager(serverUrl, apiKey);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n Usage Telemetry — Anonymous opt-in usage statistics\r\n \r\n Collects anonymous component / feature usage data.\r\n All telemetry is:\r\n • Opt-in only (disabled by default)\r\n • Anonymous — license keys are hashed, no PII stored\r\n • Batched for efficiency\r\n • Respects Do-Not-Track browser setting\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { TelemetryEvent } from './types';\r\n\r\n/** Telemetry configuration */\r\nexport interface UsageTelemetryConfig {\r\n /** Endpoint URL for sending telemetry */\r\n endpoint: string;\r\n /** API key for authentication */\r\n apiKey?: string;\r\n /** Hashed license key (never store raw key) */\r\n licenseKeyHash: string;\r\n /** Whether telemetry is enabled (default: false — opt-in) */\r\n enabled?: boolean;\r\n /** Batch size — events are sent when batch reaches this size (default: 20) */\r\n batchSize?: number;\r\n /** Flush interval in ms (default: 60000 — 1 minute) */\r\n flushInterval?: number;\r\n /** Max queue size — oldest events are dropped when exceeded (default: 500) */\r\n maxQueueSize?: number;\r\n /** Respect browser Do-Not-Track header (default: true) */\r\n respectDNT?: boolean;\r\n}\r\n\r\n/**\r\n * Simple FNV-1a hash for anonymising keys.\r\n * NOT cryptographic — for privacy bucketing only.\r\n */\r\nfunction fnv1a(str: string): string {\r\n let hash = 2166136261;\r\n for (let i = 0; i < str.length; i++) {\r\n hash ^= str.charCodeAt(i);\r\n hash = Math.imul(hash, 16777619);\r\n }\r\n return (hash >>> 0).toString(16).padStart(8, '0');\r\n}\r\n\r\n/** Hash a license key for anonymous tracking */\r\nexport function hashLicenseKey(key: string): string {\r\n return fnv1a(key) + fnv1a(key + 'nice2dev-salt');\r\n}\r\n\r\n/**\r\n * Usage Telemetry Service\r\n */\r\nexport class UsageTelemetry {\r\n private config: Required<UsageTelemetryConfig>;\r\n private queue: TelemetryEvent[] = [];\r\n private flushTimer: ReturnType<typeof setInterval> | null = null;\r\n private _active = false;\r\n\r\n constructor(config: UsageTelemetryConfig) {\r\n this.config = {\r\n enabled: false,\r\n batchSize: 20,\r\n flushInterval: 60_000,\r\n maxQueueSize: 500,\r\n respectDNT: true,\r\n apiKey: '',\r\n ...config,\r\n };\r\n }\r\n\r\n /** Start collecting telemetry (no-op if disabled or DNT) */\r\n start(): void {\r\n if (!this.isAllowed()) {\r\n return;\r\n }\r\n if (this._active) {\r\n return;\r\n }\r\n\r\n this._active = true;\r\n this.flushTimer = setInterval(() => this.flush(), this.config.flushInterval);\r\n }\r\n\r\n /** Stop collecting and flush remaining events */\r\n async stop(): Promise<void> {\r\n if (!this._active) {\r\n return;\r\n }\r\n this._active = false;\r\n\r\n if (this.flushTimer) {\r\n clearInterval(this.flushTimer);\r\n this.flushTimer = null;\r\n }\r\n\r\n await this.flush();\r\n }\r\n\r\n /** Track a telemetry event */\r\n track(type: TelemetryEvent['type'], data?: Record<string, unknown>): void {\r\n if (!this._active) {\r\n return;\r\n }\r\n\r\n const event: TelemetryEvent = {\r\n type,\r\n licenseKeyHash: this.config.licenseKeyHash,\r\n timestamp: new Date().toISOString(),\r\n data,\r\n };\r\n\r\n this.queue.push(event);\r\n\r\n // Trim queue if it exceeds max size\r\n if (this.queue.length > this.config.maxQueueSize) {\r\n this.queue = this.queue.slice(-this.config.maxQueueSize);\r\n }\r\n\r\n // Auto-flush when batch is full\r\n if (this.queue.length >= this.config.batchSize) {\r\n this.flush();\r\n }\r\n }\r\n\r\n /** Track feature usage */\r\n trackFeatureUse(featureId: string): void {\r\n this.track('feature_use', { featureId });\r\n }\r\n\r\n /** Track activation event */\r\n trackActivation(): void {\r\n this.track('activation');\r\n }\r\n\r\n /** Track deactivation event */\r\n trackDeactivation(): void {\r\n this.track('deactivation');\r\n }\r\n\r\n /** Track validation event */\r\n trackValidation(valid: boolean): void {\r\n this.track('validation', { valid });\r\n }\r\n\r\n /** Track error event */\r\n trackError(errorCode: string): void {\r\n this.track('error', { errorCode });\r\n }\r\n\r\n /** Get queued event count */\r\n get queueSize(): number {\r\n return this.queue.length;\r\n }\r\n\r\n /** Check if telemetry is active */\r\n get active(): boolean {\r\n return this._active;\r\n }\r\n\r\n /** Flush queued events to server */\r\n async flush(): Promise<void> {\r\n if (this.queue.length === 0) {\r\n return;\r\n }\r\n\r\n const batch = this.queue.splice(0, this.config.batchSize);\r\n\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.config.apiKey) {\r\n headers['X-API-Key'] = this.config.apiKey;\r\n }\r\n\r\n const response = await fetch(this.config.endpoint, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({ events: batch }),\r\n });\r\n\r\n if (!response.ok) {\r\n // Re-queue failed events (at the front)\r\n this.queue.unshift(...batch);\r\n }\r\n } catch {\r\n // Network error — re-queue\r\n this.queue.unshift(...batch);\r\n }\r\n }\r\n\r\n /** Enable telemetry (opt-in) */\r\n enable(): void {\r\n this.config.enabled = true;\r\n this.start();\r\n }\r\n\r\n /** Disable telemetry (opt-out) */\r\n disable(): void {\r\n this.config.enabled = false;\r\n this.stop();\r\n }\r\n\r\n /** Check if telemetry is allowed */\r\n private isAllowed(): boolean {\r\n if (!this.config.enabled) {\r\n return false;\r\n }\r\n\r\n // Respect Do-Not-Track\r\n if (\r\n this.config.respectDNT &&\r\n typeof navigator !== 'undefined' &&\r\n (navigator as Navigator & { doNotTrack?: string }).doNotTrack === '1'\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\n/** Convenience factory */\r\nexport function createTelemetry(config: UsageTelemetryConfig): UsageTelemetry {\r\n return new UsageTelemetry(config);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n Source Code Access Control — build-time obfuscation helpers\r\n\r\n Provides utilities for protecting licensed component source:\r\n • Component wrapper that checks license at runtime\r\n • Name mangling metadata for build pipelines\r\n • Bundle tagging for tier-based code splitting\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseTier, FeatureId } from './types';\r\n\r\n/** Access level for a protected component / module */\r\nexport type SourceAccessLevel = 'open' | 'obfuscated' | 'encrypted' | 'server-only';\r\n\r\n/** Manifest entry describing a protected module */\r\nexport interface ProtectedModuleEntry {\r\n /** Module / component path (relative to package root) */\r\n modulePath: string;\r\n /** Minimum tier required to access source */\r\n requiredTier: LicenseTier;\r\n /** Required feature ID (if any) */\r\n requiredFeature?: FeatureId;\r\n /** Protection level */\r\n accessLevel: SourceAccessLevel;\r\n /** Human-readable name */\r\n displayName: string;\r\n /** Description of what the module provides */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Registry of protected modules — consumed by the build pipeline\r\n * to decide which code paths to obfuscate / strip.\r\n */\r\nconst protectedModules = new Map<string, ProtectedModuleEntry>();\r\n\r\n/** Register a module as protected */\r\nexport function registerProtectedModule(entry: ProtectedModuleEntry): void {\r\n protectedModules.set(entry.modulePath, entry);\r\n}\r\n\r\n/** Register multiple protected modules */\r\nexport function registerProtectedModules(entries: ProtectedModuleEntry[]): void {\r\n entries.forEach(registerProtectedModule);\r\n}\r\n\r\n/** Get all protected module entries */\r\nexport function getAllProtectedModules(): ProtectedModuleEntry[] {\r\n return Array.from(protectedModules.values());\r\n}\r\n\r\n/** Get a protected module entry by path */\r\nexport function getProtectedModule(modulePath: string): ProtectedModuleEntry | undefined {\r\n return protectedModules.get(modulePath);\r\n}\r\n\r\n/** Check if a module is accessible for a given tier */\r\nexport function isModuleAccessible(modulePath: string, currentTier: LicenseTier): boolean {\r\n const entry = protectedModules.get(modulePath);\r\n if (!entry) {\r\n return true;\r\n } // Unprotected modules are always accessible\r\n\r\n const tierRank: Record<LicenseTier, number> = {\r\n trial: 0,\r\n personal: 1,\r\n team: 2,\r\n enterprise: 3,\r\n site: 4,\r\n oem: 5,\r\n };\r\n\r\n return tierRank[currentTier] >= tierRank[entry.requiredTier];\r\n}\r\n\r\n/** Get modules that require a higher tier than current */\r\nexport function getInaccessibleModules(currentTier: LicenseTier): ProtectedModuleEntry[] {\r\n return getAllProtectedModules().filter((m) => !isModuleAccessible(m.modulePath, currentTier));\r\n}\r\n\r\n/** Get modules accessible at a given tier */\r\nexport function getAccessibleModules(currentTier: LicenseTier): ProtectedModuleEntry[] {\r\n return getAllProtectedModules().filter((m) => isModuleAccessible(m.modulePath, currentTier));\r\n}\r\n\r\n// ─── Build-time metadata ────────────────────────────────────────\r\n\r\n/** Bundle tag added to chunks containing protected code */\r\nexport interface BundleTag {\r\n /** Chunk/file identifier */\r\n chunkId: string;\r\n /** Required tier */\r\n requiredTier: LicenseTier;\r\n /** Access level */\r\n accessLevel: SourceAccessLevel;\r\n /** Modules in this chunk */\r\n modules: string[];\r\n}\r\n\r\n/**\r\n * Generate bundle tags for a build manifest.\r\n * Consumed by the Vite/webpack plugin to tag output chunks.\r\n */\r\nexport function generateBundleTags(): BundleTag[] {\r\n const byTier = new Map<string, ProtectedModuleEntry[]>();\r\n\r\n for (const entry of protectedModules.values()) {\r\n const key = `${entry.requiredTier}:${entry.accessLevel}`;\r\n const group = byTier.get(key) ?? [];\r\n group.push(entry);\r\n byTier.set(key, group);\r\n }\r\n\r\n return Array.from(byTier.entries()).map(([key, entries]) => {\r\n const [requiredTier, accessLevel] = key.split(':') as [LicenseTier, SourceAccessLevel];\r\n return {\r\n chunkId: `protected-${requiredTier}-${accessLevel}`,\r\n requiredTier,\r\n accessLevel,\r\n modules: entries.map((e) => e.modulePath),\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * Generate a protection manifest (JSON-serializable) for embedding\r\n * in production builds.\r\n */\r\nexport function generateProtectionManifest(): {\r\n version: string;\r\n generated: string;\r\n modules: ProtectedModuleEntry[];\r\n bundleTags: BundleTag[];\r\n} {\r\n return {\r\n version: '1.0.0',\r\n generated: new Date().toISOString(),\r\n modules: getAllProtectedModules(),\r\n bundleTags: generateBundleTags(),\r\n };\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n API Rate Limiting — per-license tier request throttling\r\n\r\n Provides client-side rate limiting utilities:\r\n • Token-bucket algorithm per tier\r\n • Configurable limits per endpoint / action\r\n • React hook for gated API calls\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseTier } from './types';\r\n\r\n/** Rate limit configuration for a single tier */\r\nexport interface TierRateLimit {\r\n /** Maximum requests in the window */\r\n maxRequests: number;\r\n /** Window duration in ms */\r\n windowMs: number;\r\n /** Burst allowance (extra requests beyond max, refills over time) */\r\n burst?: number;\r\n}\r\n\r\n/** Rate limit configuration keyed by tier */\r\nexport type RateLimitConfig = Record<LicenseTier, TierRateLimit>;\r\n\r\n/** Default tier rate limits (requests per minute) */\r\nexport const DEFAULT_RATE_LIMITS: RateLimitConfig = {\r\n trial: { maxRequests: 30, windowMs: 60_000, burst: 5 },\r\n personal: { maxRequests: 120, windowMs: 60_000, burst: 20 },\r\n team: { maxRequests: 600, windowMs: 60_000, burst: 100 },\r\n enterprise: { maxRequests: 3000, windowMs: 60_000, burst: 500 },\r\n site: { maxRequests: 10_000, windowMs: 60_000, burst: 2000 },\r\n oem: { maxRequests: 50_000, windowMs: 60_000, burst: 10_000 },\r\n};\r\n\r\n/** Result of a rate limit check */\r\nexport interface RateLimitResult {\r\n /** Whether the request is allowed */\r\n allowed: boolean;\r\n /** Remaining requests in the current window */\r\n remaining: number;\r\n /** Time in ms until the next token is available (0 if allowed) */\r\n retryAfterMs: number;\r\n /** Total limit for the tier */\r\n limit: number;\r\n}\r\n\r\n/**\r\n * Token-bucket rate limiter.\r\n * Refills tokens at a constant rate up to the max capacity.\r\n */\r\nexport class RateLimiter {\r\n private tokens: number;\r\n private lastRefill: number;\r\n private config: TierRateLimit;\r\n\r\n constructor(config: TierRateLimit) {\r\n this.config = config;\r\n this.tokens = config.maxRequests + (config.burst ?? 0);\r\n this.lastRefill = Date.now();\r\n }\r\n\r\n /** Refill tokens based on elapsed time */\r\n private refill(): void {\r\n const now = Date.now();\r\n const elapsed = now - this.lastRefill;\r\n const maxTokens = this.config.maxRequests + (this.config.burst ?? 0);\r\n const refillRate = this.config.maxRequests / this.config.windowMs; // tokens per ms\r\n const newTokens = elapsed * refillRate;\r\n\r\n this.tokens = Math.min(maxTokens, this.tokens + newTokens);\r\n this.lastRefill = now;\r\n }\r\n\r\n /** Check and consume one request token */\r\n consume(): RateLimitResult {\r\n this.refill();\r\n\r\n const maxTokens = this.config.maxRequests + (this.config.burst ?? 0);\r\n\r\n if (this.tokens >= 1) {\r\n this.tokens -= 1;\r\n return {\r\n allowed: true,\r\n remaining: Math.floor(this.tokens),\r\n retryAfterMs: 0,\r\n limit: maxTokens,\r\n };\r\n }\r\n\r\n // Not allowed — calculate retry time\r\n const refillRate = this.config.maxRequests / this.config.windowMs;\r\n const retryAfterMs = Math.ceil((1 - this.tokens) / refillRate);\r\n\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n retryAfterMs,\r\n limit: maxTokens,\r\n };\r\n }\r\n\r\n /** Reset the limiter (e.g. after tier change) */\r\n reset(config?: TierRateLimit): void {\r\n if (config) {\r\n this.config = config;\r\n }\r\n this.tokens = this.config.maxRequests + (this.config.burst ?? 0);\r\n this.lastRefill = Date.now();\r\n }\r\n\r\n /** Peek at remaining tokens without consuming */\r\n peek(): RateLimitResult {\r\n this.refill();\r\n const maxTokens = this.config.maxRequests + (this.config.burst ?? 0);\r\n return {\r\n allowed: this.tokens >= 1,\r\n remaining: Math.floor(this.tokens),\r\n retryAfterMs: 0,\r\n limit: maxTokens,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Multi-endpoint rate limiter — maintains a separate bucket per endpoint/action.\r\n */\r\nexport class ApiRateLimiter {\r\n private limiters: Map<string, RateLimiter> = new Map();\r\n private tier: LicenseTier;\r\n private config: RateLimitConfig;\r\n private endpointOverrides: Map<string, Partial<RateLimitConfig>> = new Map();\r\n\r\n constructor(tier: LicenseTier, config: RateLimitConfig = DEFAULT_RATE_LIMITS) {\r\n this.tier = tier;\r\n this.config = config;\r\n }\r\n\r\n /** Set endpoint-specific rate limit overrides */\r\n setEndpointOverride(endpoint: string, overrides: Partial<RateLimitConfig>): void {\r\n this.endpointOverrides.set(endpoint, overrides);\r\n }\r\n\r\n /** Update the current tier (resets all limiters) */\r\n setTier(tier: LicenseTier): void {\r\n this.tier = tier;\r\n this.limiters.clear();\r\n }\r\n\r\n /** Get or create a limiter for an endpoint */\r\n private getLimiter(endpoint: string): RateLimiter {\r\n let limiter = this.limiters.get(endpoint);\r\n if (!limiter) {\r\n const override = this.endpointOverrides.get(endpoint);\r\n const tierConfig = (override && override[this.tier]) ?? this.config[this.tier];\r\n limiter = new RateLimiter(tierConfig);\r\n this.limiters.set(endpoint, limiter);\r\n }\r\n return limiter;\r\n }\r\n\r\n /** Check if a request to the given endpoint is allowed and consume a token */\r\n check(endpoint: string = 'default'): RateLimitResult {\r\n return this.getLimiter(endpoint).consume();\r\n }\r\n\r\n /** Peek without consuming */\r\n peek(endpoint: string = 'default'): RateLimitResult {\r\n return this.getLimiter(endpoint).peek();\r\n }\r\n\r\n /** Reset all limiters */\r\n reset(): void {\r\n this.limiters.clear();\r\n }\r\n}\r\n\r\n/** Convenience factory */\r\nexport function createApiRateLimiter(tier: LicenseTier, config?: RateLimitConfig): ApiRateLimiter {\r\n return new ApiRateLimiter(tier, config);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n White-labeling — Rebranding support per license\r\n\r\n Manages brand overrides (logo, colors, product name) that\r\n can be applied when a license permits white-labeling.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseTier } from './types';\r\n\r\n/** White-label brand configuration */\r\nexport interface WhiteLabelConfig {\r\n /** Custom product name */\r\n productName?: string;\r\n /** Logo URL (light theme) */\r\n logoUrl?: string;\r\n /** Logo URL (dark theme) */\r\n logoDarkUrl?: string;\r\n /** Favicon URL */\r\n faviconUrl?: string;\r\n /** Primary brand color (hex) */\r\n primaryColor?: string;\r\n /** Secondary brand color (hex) */\r\n secondaryColor?: string;\r\n /** Accent color (hex) */\r\n accentColor?: string;\r\n /** Custom CSS to inject */\r\n customCss?: string;\r\n /** Custom footer text */\r\n footerText?: string;\r\n /** Hide \"Powered by Nice2Dev\" badge */\r\n hidePoweredBy?: boolean;\r\n /** Custom domain for white-labeled deployment */\r\n customDomain?: string;\r\n /** Custom email sender domain */\r\n emailDomain?: string;\r\n}\r\n\r\n/** Minimum tier required for each white-label feature */\r\nconst FEATURE_TIER_REQUIREMENTS: Record<keyof WhiteLabelConfig, LicenseTier> = {\r\n productName: 'team',\r\n logoUrl: 'team',\r\n logoDarkUrl: 'team',\r\n faviconUrl: 'team',\r\n primaryColor: 'team',\r\n secondaryColor: 'team',\r\n accentColor: 'team',\r\n customCss: 'enterprise',\r\n footerText: 'enterprise',\r\n hidePoweredBy: 'enterprise',\r\n customDomain: 'site',\r\n emailDomain: 'site',\r\n};\r\n\r\nconst tierRank: Record<LicenseTier, number> = {\r\n trial: 0,\r\n personal: 1,\r\n team: 2,\r\n enterprise: 3,\r\n site: 4,\r\n oem: 5,\r\n};\r\n\r\n/**\r\n * White-label manager — applies brand overrides based on license tier\r\n */\r\nexport class WhiteLabelManager {\r\n private config: WhiteLabelConfig = {};\r\n private currentTier: LicenseTier = 'trial';\r\n\r\n /** Set the active license tier */\r\n setTier(tier: LicenseTier): void {\r\n this.currentTier = tier;\r\n }\r\n\r\n /** Update white-label configuration (only applicable fields per tier are kept) */\r\n setConfig(config: WhiteLabelConfig): void {\r\n this.config = config;\r\n }\r\n\r\n /** Get the resolved configuration (filtered by tier permissions) */\r\n getResolvedConfig(): Partial<WhiteLabelConfig> {\r\n const resolved: Partial<WhiteLabelConfig> = {};\r\n\r\n for (const [key, value] of Object.entries(this.config)) {\r\n if (value === undefined) {\r\n continue;\r\n }\r\n const requiredTier = FEATURE_TIER_REQUIREMENTS[key as keyof WhiteLabelConfig];\r\n if (requiredTier && tierRank[this.currentTier] >= tierRank[requiredTier]) {\r\n (resolved as Record<string, unknown>)[key] = value;\r\n }\r\n }\r\n\r\n return resolved;\r\n }\r\n\r\n /** Check if a specific white-label feature is allowed */\r\n isFeatureAllowed(feature: keyof WhiteLabelConfig): boolean {\r\n const requiredTier = FEATURE_TIER_REQUIREMENTS[feature];\r\n return tierRank[this.currentTier] >= tierRank[requiredTier];\r\n }\r\n\r\n /** Get list of features not available at current tier */\r\n getLockedFeatures(): (keyof WhiteLabelConfig)[] {\r\n return (Object.keys(FEATURE_TIER_REQUIREMENTS) as (keyof WhiteLabelConfig)[]).filter(\r\n (f) => !this.isFeatureAllowed(f),\r\n );\r\n }\r\n\r\n /** Get list of features available at current tier */\r\n getUnlockedFeatures(): (keyof WhiteLabelConfig)[] {\r\n return (Object.keys(FEATURE_TIER_REQUIREMENTS) as (keyof WhiteLabelConfig)[]).filter((f) =>\r\n this.isFeatureAllowed(f),\r\n );\r\n }\r\n\r\n /** Generate CSS custom properties from the resolved config */\r\n generateCssVariables(): string {\r\n const cfg = this.getResolvedConfig();\r\n const vars: string[] = [];\r\n\r\n if (cfg.primaryColor) {\r\n vars.push(`--nice-brand-primary: ${cfg.primaryColor};`);\r\n }\r\n if (cfg.secondaryColor) {\r\n vars.push(`--nice-brand-secondary: ${cfg.secondaryColor};`);\r\n }\r\n if (cfg.accentColor) {\r\n vars.push(`--nice-brand-accent: ${cfg.accentColor};`);\r\n }\r\n if (cfg.logoUrl) {\r\n vars.push(`--nice-brand-logo: url(${cfg.logoUrl});`);\r\n }\r\n if (cfg.logoDarkUrl) {\r\n vars.push(`--nice-brand-logo-dark: url(${cfg.logoDarkUrl});`);\r\n }\r\n\r\n if (vars.length === 0) {\r\n return '';\r\n }\r\n return `:root {\\n ${vars.join('\\n ')}\\n}`;\r\n }\r\n\r\n /** Apply the brand configuration to the document */\r\n applyToDocument(): void {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const cfg = this.getResolvedConfig();\r\n\r\n // Apply CSS variables\r\n const css = this.generateCssVariables();\r\n if (css) {\r\n let styleEl = document.getElementById('nice-whitelabel-styles');\r\n if (!styleEl) {\r\n styleEl = document.createElement('style');\r\n styleEl.id = 'nice-whitelabel-styles';\r\n document.head.appendChild(styleEl);\r\n }\r\n styleEl.textContent = css + (cfg.customCss ? `\\n${cfg.customCss}` : '');\r\n }\r\n\r\n // Apply favicon\r\n if (cfg.faviconUrl) {\r\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"icon\"]');\r\n if (!link) {\r\n link = document.createElement('link');\r\n link.rel = 'icon';\r\n document.head.appendChild(link);\r\n }\r\n link.href = cfg.faviconUrl;\r\n }\r\n\r\n // Apply page title\r\n if (cfg.productName) {\r\n document.title = cfg.productName;\r\n }\r\n }\r\n}\r\n\r\n/** Convenience factory */\r\nexport function createWhiteLabelManager(\r\n tier: LicenseTier,\r\n config?: WhiteLabelConfig,\r\n): WhiteLabelManager {\r\n const mgr = new WhiteLabelManager();\r\n mgr.setTier(tier);\r\n if (config) {\r\n mgr.setConfig(config);\r\n }\r\n return mgr;\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n SLA Tier Tracking — Service Level Agreement tracking per tier\r\n\r\n Tracks SLA metrics (uptime, response time, support priority)\r\n per license tier and provides utilities for SLA reporting.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseTier } from './types';\r\n\r\n/** SLA configuration for a single tier */\r\nexport interface SlaTierConfig {\r\n /** Guaranteed uptime percentage (e.g. 99.9) */\r\n uptimePercent: number;\r\n /** Maximum response time for support (hours) */\r\n supportResponseHours: number;\r\n /** Maximum resolution time (hours) */\r\n supportResolutionHours: number;\r\n /** Support channels available */\r\n supportChannels: SupportChannel[];\r\n /** Priority level (1 = highest) */\r\n priority: number;\r\n /** Included support hours per month (null = unlimited) */\r\n includedHours: number | null;\r\n /** Penalty per SLA breach (as percentage credit) */\r\n breachPenaltyPercent: number;\r\n}\r\n\r\n/** Available support channels */\r\nexport type SupportChannel = 'email' | 'chat' | 'phone' | 'dedicated-manager' | 'on-site';\r\n\r\n/** Default SLA configurations per tier */\r\nexport const DEFAULT_SLA_CONFIGS: Record<LicenseTier, SlaTierConfig> = {\r\n trial: {\r\n uptimePercent: 95,\r\n supportResponseHours: 72,\r\n supportResolutionHours: 168,\r\n supportChannels: ['email'],\r\n priority: 6,\r\n includedHours: 0,\r\n breachPenaltyPercent: 0,\r\n },\r\n personal: {\r\n uptimePercent: 99,\r\n supportResponseHours: 48,\r\n supportResolutionHours: 120,\r\n supportChannels: ['email'],\r\n priority: 5,\r\n includedHours: 2,\r\n breachPenaltyPercent: 0,\r\n },\r\n team: {\r\n uptimePercent: 99.5,\r\n supportResponseHours: 24,\r\n supportResolutionHours: 72,\r\n supportChannels: ['email', 'chat'],\r\n priority: 4,\r\n includedHours: 10,\r\n breachPenaltyPercent: 5,\r\n },\r\n enterprise: {\r\n uptimePercent: 99.9,\r\n supportResponseHours: 4,\r\n supportResolutionHours: 24,\r\n supportChannels: ['email', 'chat', 'phone'],\r\n priority: 3,\r\n includedHours: 40,\r\n breachPenaltyPercent: 10,\r\n },\r\n site: {\r\n uptimePercent: 99.95,\r\n supportResponseHours: 2,\r\n supportResolutionHours: 12,\r\n supportChannels: ['email', 'chat', 'phone', 'dedicated-manager'],\r\n priority: 2,\r\n includedHours: null,\r\n breachPenaltyPercent: 15,\r\n },\r\n oem: {\r\n uptimePercent: 99.99,\r\n supportResponseHours: 1,\r\n supportResolutionHours: 4,\r\n supportChannels: ['email', 'chat', 'phone', 'dedicated-manager', 'on-site'],\r\n priority: 1,\r\n includedHours: null,\r\n breachPenaltyPercent: 20,\r\n },\r\n};\r\n\r\n/** SLA event record (uptime check, support ticket, etc.) */\r\nexport interface SlaEvent {\r\n /** Event ID */\r\n id: string;\r\n /** Event type */\r\n type: 'uptime-check' | 'downtime-start' | 'downtime-end' | 'ticket-opened' | 'ticket-resolved';\r\n /** ISO timestamp */\r\n timestamp: string;\r\n /** Duration in ms (for downtime or resolution) */\r\n durationMs?: number;\r\n /** Associated metadata */\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n/** SLA compliance report */\r\nexport interface SlaReport {\r\n /** Reporting period start (ISO) */\r\n periodStart: string;\r\n /** Reporting period end (ISO) */\r\n periodEnd: string;\r\n /** License tier */\r\n tier: LicenseTier;\r\n /** SLA config for this tier */\r\n slaConfig: SlaTierConfig;\r\n /** Actual uptime percentage */\r\n actualUptimePercent: number;\r\n /** Total downtime in ms */\r\n totalDowntimeMs: number;\r\n /** Average support response time (hours) */\r\n avgResponseHours: number;\r\n /** Average resolution time (hours) */\r\n avgResolutionHours: number;\r\n /** Number of SLA breaches */\r\n breachCount: number;\r\n /** Is SLA compliant */\r\n compliant: boolean;\r\n /** Credit owed (if breached) */\r\n creditPercent: number;\r\n}\r\n\r\n/**\r\n * SLA Tracker — Monitors and reports SLA compliance\r\n */\r\nexport class SlaTracker {\r\n private events: SlaEvent[] = [];\r\n private tier: LicenseTier;\r\n private config: Record<LicenseTier, SlaTierConfig>;\r\n\r\n constructor(tier: LicenseTier, config: Record<LicenseTier, SlaTierConfig> = DEFAULT_SLA_CONFIGS) {\r\n this.tier = tier;\r\n this.config = config;\r\n }\r\n\r\n /** Update the license tier */\r\n setTier(tier: LicenseTier): void {\r\n this.tier = tier;\r\n }\r\n\r\n /** Get the SLA config for the current tier */\r\n getSlaConfig(): SlaTierConfig {\r\n return this.config[this.tier];\r\n }\r\n\r\n /** Record an event */\r\n recordEvent(event: SlaEvent): void {\r\n this.events.push(event);\r\n }\r\n\r\n /** Record an uptime check */\r\n recordUptimeCheck(): void {\r\n this.recordEvent({\r\n id: crypto.randomUUID?.() ?? Date.now().toString(36),\r\n type: 'uptime-check',\r\n timestamp: new Date().toISOString(),\r\n });\r\n }\r\n\r\n /** Record downtime */\r\n recordDowntime(durationMs: number): void {\r\n const now = new Date();\r\n this.recordEvent({\r\n id: crypto.randomUUID?.() ?? Date.now().toString(36),\r\n type: 'downtime-start',\r\n timestamp: new Date(now.getTime() - durationMs).toISOString(),\r\n durationMs,\r\n });\r\n this.recordEvent({\r\n id: crypto.randomUUID?.() ?? (Date.now() + 1).toString(36),\r\n type: 'downtime-end',\r\n timestamp: now.toISOString(),\r\n });\r\n }\r\n\r\n /** Record a support ticket lifecycle */\r\n recordTicket(responseTimeHours: number, resolutionTimeHours: number): void {\r\n const now = new Date();\r\n this.recordEvent({\r\n id: crypto.randomUUID?.() ?? Date.now().toString(36),\r\n type: 'ticket-opened',\r\n timestamp: now.toISOString(),\r\n metadata: { responseTimeHours, resolutionTimeHours },\r\n });\r\n this.recordEvent({\r\n id: crypto.randomUUID?.() ?? (Date.now() + 1).toString(36),\r\n type: 'ticket-resolved',\r\n timestamp: new Date(now.getTime() + resolutionTimeHours * 3600_000).toISOString(),\r\n durationMs: resolutionTimeHours * 3600_000,\r\n metadata: { responseTimeHours },\r\n });\r\n }\r\n\r\n /** Generate an SLA report for a given period */\r\n generateReport(periodStart: Date, periodEnd: Date): SlaReport {\r\n const slaConfig = this.getSlaConfig();\r\n const periodMs = periodEnd.getTime() - periodStart.getTime();\r\n\r\n // Filter events in period\r\n const periodEvents = this.events.filter((e) => {\r\n const t = new Date(e.timestamp).getTime();\r\n return t >= periodStart.getTime() && t <= periodEnd.getTime();\r\n });\r\n\r\n // Calculate downtime\r\n const downtimeEvents = periodEvents.filter((e) => e.type === 'downtime-start');\r\n const totalDowntimeMs = downtimeEvents.reduce((sum, e) => sum + (e.durationMs ?? 0), 0);\r\n const actualUptimePercent =\r\n periodMs > 0 ? ((periodMs - totalDowntimeMs) / periodMs) * 100 : 100;\r\n\r\n // Calculate support metrics\r\n const tickets = periodEvents.filter((e) => e.type === 'ticket-resolved');\r\n const responseTimes = tickets\r\n .map((t) => (t.metadata?.responseTimeHours as number) ?? 0)\r\n .filter((h) => h > 0);\r\n const resolutionTimes = tickets.map((t) => (t.durationMs ?? 0) / 3600_000).filter((h) => h > 0);\r\n\r\n const avgResponseHours =\r\n responseTimes.length > 0\r\n ? responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length\r\n : 0;\r\n const avgResolutionHours =\r\n resolutionTimes.length > 0\r\n ? resolutionTimes.reduce((a, b) => a + b, 0) / resolutionTimes.length\r\n : 0;\r\n\r\n // Determine breaches\r\n let breachCount = 0;\r\n if (actualUptimePercent < slaConfig.uptimePercent) {\r\n breachCount++;\r\n }\r\n if (avgResponseHours > slaConfig.supportResponseHours && responseTimes.length > 0) {\r\n breachCount++;\r\n }\r\n if (avgResolutionHours > slaConfig.supportResolutionHours && resolutionTimes.length > 0) {\r\n breachCount++;\r\n }\r\n\r\n const compliant = breachCount === 0;\r\n const creditPercent = compliant ? 0 : breachCount * slaConfig.breachPenaltyPercent;\r\n\r\n return {\r\n periodStart: periodStart.toISOString(),\r\n periodEnd: periodEnd.toISOString(),\r\n tier: this.tier,\r\n slaConfig,\r\n actualUptimePercent: Math.round(actualUptimePercent * 100) / 100,\r\n totalDowntimeMs,\r\n avgResponseHours: Math.round(avgResponseHours * 10) / 10,\r\n avgResolutionHours: Math.round(avgResolutionHours * 10) / 10,\r\n breachCount,\r\n compliant,\r\n creditPercent: Math.min(100, creditPercent),\r\n };\r\n }\r\n\r\n /** Get all recorded events */\r\n getEvents(): SlaEvent[] {\r\n return [...this.events];\r\n }\r\n\r\n /** Clear all events */\r\n clearEvents(): void {\r\n this.events = [];\r\n }\r\n}\r\n\r\n/** Convenience factory */\r\nexport function createSlaTracker(tier: LicenseTier): SlaTracker {\r\n return new SlaTracker(tier);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n Audit Trail — License change history tracking\r\n\r\n Immutable, append-only log of all license-related actions.\r\n Provides querying, filtering, and export capabilities.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseKey, LicenseTier } from './types';\r\n\r\n/** Audit event types */\r\nexport type AuditEventType =\r\n | 'license.created'\r\n | 'license.activated'\r\n | 'license.deactivated'\r\n | 'license.renewed'\r\n | 'license.expired'\r\n | 'license.revoked'\r\n | 'license.tier-changed'\r\n | 'license.seats-changed'\r\n | 'license.feature-added'\r\n | 'license.feature-removed'\r\n | 'license.machine-bound'\r\n | 'license.machine-unbound'\r\n | 'license.validation-failed'\r\n | 'license.grace-started'\r\n | 'license.grace-ended'\r\n | 'whitelabel.config-changed'\r\n | 'sla.breach-detected'\r\n | 'admin.key-generated'\r\n | 'admin.bulk-action';\r\n\r\n/** Single audit log entry */\r\nexport interface AuditEntry {\r\n /** Unique entry ID */\r\n id: string;\r\n /** Event type */\r\n event: AuditEventType;\r\n /** ISO timestamp */\r\n timestamp: string;\r\n /** License key (hashed for security) */\r\n licenseKeyHash: string;\r\n /** Actor who performed the action */\r\n actor: AuditActor;\r\n /** Previous value (for changes) */\r\n previousValue?: unknown;\r\n /** New value (for changes) */\r\n newValue?: unknown;\r\n /** Human-readable description */\r\n description: string;\r\n /** IP address of the action (hashed) */\r\n ipHash?: string;\r\n /** Additional metadata */\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n/** Actor who triggered an audit event */\r\nexport interface AuditActor {\r\n /** Actor type */\r\n type: 'user' | 'admin' | 'system' | 'api';\r\n /** Actor identifier (user ID, service name, etc.) */\r\n id: string;\r\n /** Display name */\r\n name?: string;\r\n}\r\n\r\n/** Query filter for audit log */\r\nexport interface AuditQuery {\r\n /** Filter by event types */\r\n events?: AuditEventType[];\r\n /** Filter by license key hash */\r\n licenseKeyHash?: string;\r\n /** Filter by actor ID */\r\n actorId?: string;\r\n /** Start date (inclusive) */\r\n from?: Date;\r\n /** End date (inclusive) */\r\n to?: Date;\r\n /** Maximum number of results */\r\n limit?: number;\r\n /** Offset for pagination */\r\n offset?: number;\r\n}\r\n\r\n/** Audit export format */\r\nexport type AuditExportFormat = 'json' | 'csv';\r\n\r\n/**\r\n * FNV-1a hash (same as in UsageTelemetry, duplicated to avoid cross-dependency)\r\n */\r\nfunction auditHash(str: string): string {\r\n let hash = 2166136261;\r\n for (let i = 0; i < str.length; i++) {\r\n hash ^= str.charCodeAt(i);\r\n hash = Math.imul(hash, 16777619);\r\n }\r\n return (hash >>> 0).toString(16).padStart(8, '0');\r\n}\r\n\r\n/** Hash a license key for audit storage */\r\nexport function hashKeyForAudit(key: LicenseKey): string {\r\n return auditHash(key) + auditHash(key + 'audit-salt');\r\n}\r\n\r\n/**\r\n * Audit Trail — append-only log with query and export capabilities\r\n */\r\nexport class AuditTrail {\r\n private entries: AuditEntry[] = [];\r\n private serverUrl?: string;\r\n private apiKey?: string;\r\n\r\n constructor(options?: { serverUrl?: string; apiKey?: string }) {\r\n this.serverUrl = options?.serverUrl;\r\n this.apiKey = options?.apiKey;\r\n }\r\n\r\n /** Append an audit entry */\r\n log(\r\n event: AuditEventType,\r\n licenseKey: LicenseKey,\r\n actor: AuditActor,\r\n description: string,\r\n details?: {\r\n previousValue?: unknown;\r\n newValue?: unknown;\r\n ipHash?: string;\r\n metadata?: Record<string, unknown>;\r\n },\r\n ): AuditEntry {\r\n const entry: AuditEntry = {\r\n id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\r\n event,\r\n timestamp: new Date().toISOString(),\r\n licenseKeyHash: hashKeyForAudit(licenseKey),\r\n actor,\r\n description,\r\n previousValue: details?.previousValue,\r\n newValue: details?.newValue,\r\n ipHash: details?.ipHash,\r\n metadata: details?.metadata,\r\n };\r\n\r\n this.entries.push(entry);\r\n\r\n // Send to server asynchronously (fire-and-forget)\r\n if (this.serverUrl) {\r\n this.sendToServer(entry).catch(() => {\r\n /* Audit log network errors are silently ignored */\r\n });\r\n }\r\n\r\n return entry;\r\n }\r\n\r\n // ─── Convenience logging methods ────────────────────────────\r\n\r\n logActivation(licenseKey: LicenseKey, actor: AuditActor): AuditEntry {\r\n return this.log('license.activated', licenseKey, actor, 'License activated');\r\n }\r\n\r\n logDeactivation(licenseKey: LicenseKey, actor: AuditActor): AuditEntry {\r\n return this.log('license.deactivated', licenseKey, actor, 'License deactivated');\r\n }\r\n\r\n logTierChange(\r\n licenseKey: LicenseKey,\r\n actor: AuditActor,\r\n from: LicenseTier,\r\n to: LicenseTier,\r\n ): AuditEntry {\r\n return this.log(\r\n 'license.tier-changed',\r\n licenseKey,\r\n actor,\r\n `Tier changed from ${from} to ${to}`,\r\n { previousValue: from, newValue: to },\r\n );\r\n }\r\n\r\n logSeatsChange(licenseKey: LicenseKey, actor: AuditActor, from: number, to: number): AuditEntry {\r\n return this.log(\r\n 'license.seats-changed',\r\n licenseKey,\r\n actor,\r\n `Seats changed from ${from} to ${to}`,\r\n { previousValue: from, newValue: to },\r\n );\r\n }\r\n\r\n logRevocation(licenseKey: LicenseKey, actor: AuditActor, reason?: string): AuditEntry {\r\n return this.log(\r\n 'license.revoked',\r\n licenseKey,\r\n actor,\r\n `License revoked${reason ? `: ${reason}` : ''}`,\r\n {\r\n metadata: reason ? { reason } : undefined,\r\n },\r\n );\r\n }\r\n\r\n // ─── Query ──────────────────────────────────────────────────\r\n\r\n /** Query audit entries with filters */\r\n query(filter: AuditQuery = {}): AuditEntry[] {\r\n let results = [...this.entries];\r\n\r\n if (filter.events?.length) {\r\n const set = new Set(filter.events);\r\n results = results.filter((e) => set.has(e.event));\r\n }\r\n if (filter.licenseKeyHash) {\r\n results = results.filter((e) => e.licenseKeyHash === filter.licenseKeyHash);\r\n }\r\n if (filter.actorId) {\r\n results = results.filter((e) => e.actor.id === filter.actorId);\r\n }\r\n if (filter.from) {\r\n const from = filter.from.getTime();\r\n results = results.filter((e) => new Date(e.timestamp).getTime() >= from);\r\n }\r\n if (filter.to) {\r\n const to = filter.to.getTime();\r\n results = results.filter((e) => new Date(e.timestamp).getTime() <= to);\r\n }\r\n\r\n // Sort newest first\r\n results.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\r\n\r\n if (filter.offset) {\r\n results = results.slice(filter.offset);\r\n }\r\n if (filter.limit) {\r\n results = results.slice(0, filter.limit);\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /** Get total entry count (optionally filtered) */\r\n count(filter?: AuditQuery): number {\r\n if (!filter) {\r\n return this.entries.length;\r\n }\r\n return this.query({ ...filter, limit: undefined, offset: undefined }).length;\r\n }\r\n\r\n // ─── Export ─────────────────────────────────────────────────\r\n\r\n /** Export audit entries */\r\n export(filter?: AuditQuery, format: AuditExportFormat = 'json'): string {\r\n const entries = this.query(filter ?? {});\r\n\r\n if (format === 'csv') {\r\n const header = 'id,event,timestamp,licenseKeyHash,actorType,actorId,description';\r\n const rows = entries.map(\r\n (e) =>\r\n `\"${e.id}\",\"${e.event}\",\"${e.timestamp}\",\"${e.licenseKeyHash}\",\"${e.actor.type}\",\"${e.actor.id}\",\"${e.description.replace(/\"/g, '\"\"')}\"`,\r\n );\r\n return [header, ...rows].join('\\n');\r\n }\r\n\r\n return JSON.stringify(entries, null, 2);\r\n }\r\n\r\n // ─── Server sync ────────────────────────────────────────────\r\n\r\n private async sendToServer(entry: AuditEntry): Promise<void> {\r\n if (!this.serverUrl) {\r\n return;\r\n }\r\n\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n if (this.apiKey) {\r\n headers['X-API-Key'] = this.apiKey;\r\n }\r\n\r\n await fetch(`${this.serverUrl}/audit`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(entry),\r\n });\r\n }\r\n\r\n /** Get all entries (read-only copy) */\r\n getAll(): AuditEntry[] {\r\n return [...this.entries];\r\n }\r\n}\r\n\r\n/** Convenience factory */\r\nexport function createAuditTrail(options?: { serverUrl?: string; apiKey?: string }): AuditTrail {\r\n return new AuditTrail(options);\r\n}\r\n","/* eslint-disable jsx-a11y/click-events-have-key-events -- modal overlay backdrops (Esc-on-parent provides keyboard close), selection rows in .map() accompanied by visible cursor:pointer styling and sibling buttons; full keyboard migration via useAccessibleClick + extracted subcomponents tracked in TODO_1.0.10 A2.3 */\r\n/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — License Management Web Portal\r\n \r\n Self-service portal for customers to view, activate, transfer,\r\n and manage their Nice2Dev licenses.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport React, { useState, useEffect, useCallback } from 'react';\r\n\r\nimport type {\r\n LicenseInfo,\r\n LicenseKey,\r\n LicenseStatus,\r\n LicenseTier,\r\n FeatureId,\r\n SeatInfo,\r\n} from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES & INTERFACES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface LicensePortalConfig {\r\n /** API base URL for license operations */\r\n apiBaseUrl: string;\r\n /** Authentication token */\r\n authToken?: string;\r\n /** Customer/Organization ID */\r\n customerId: string;\r\n /** Enable dark mode */\r\n darkMode?: boolean;\r\n /** Locale for date/number formatting */\r\n locale?: string;\r\n /** Currency code for billing */\r\n currency?: string;\r\n /** Show billing section */\r\n showBilling?: boolean;\r\n /** Show usage analytics */\r\n showAnalytics?: boolean;\r\n /** Allow license transfers */\r\n allowTransfers?: boolean;\r\n /** Allow seat management */\r\n allowSeatManagement?: boolean;\r\n /** Custom theme colors */\r\n theme?: LicensePortalTheme;\r\n /** Callback when license is activated */\r\n onLicenseActivated?: (license: LicenseInfo) => void;\r\n /** Callback when license is deactivated */\r\n onLicenseDeactivated?: (licenseKey: LicenseKey) => void;\r\n /** Callback on error */\r\n onError?: (error: LicensePortalError) => void;\r\n}\r\n\r\nexport interface LicensePortalTheme {\r\n primaryColor: string;\r\n secondaryColor: string;\r\n backgroundColor: string;\r\n surfaceColor: string;\r\n textColor: string;\r\n errorColor: string;\r\n successColor: string;\r\n warningColor: string;\r\n}\r\n\r\nexport interface LicensePortalError {\r\n code: string;\r\n message: string;\r\n details?: Record<string, unknown>;\r\n}\r\n\r\nexport interface CustomerLicenseOverview {\r\n /** Total licenses owned */\r\n totalLicenses: number;\r\n /** Active licenses */\r\n activeLicenses: number;\r\n /** Expired licenses */\r\n expiredLicenses: number;\r\n /** Licenses in grace period */\r\n gracePeriodLicenses: number;\r\n /** Total seats across all licenses */\r\n totalSeats: number;\r\n /** Used seats */\r\n usedSeats: number;\r\n /** Available seats */\r\n availableSeats: number;\r\n /** Licenses expiring soon (30 days) */\r\n expiringSoon: LicenseInfo[];\r\n /** All licenses */\r\n licenses: LicenseInfo[];\r\n}\r\n\r\nexport interface LicenseAction {\r\n id: string;\r\n type: 'activate' | 'deactivate' | 'transfer' | 'upgrade' | 'renew' | 'revoke';\r\n licenseKey: LicenseKey;\r\n timestamp: string;\r\n performedBy: string;\r\n details?: Record<string, unknown>;\r\n}\r\n\r\nexport interface SubscriptionInfo {\r\n id: string;\r\n status: 'active' | 'past_due' | 'canceled' | 'trialing' | 'paused';\r\n plan: string;\r\n tier: LicenseTier;\r\n pricePerMonth: number;\r\n pricePerYear: number;\r\n currency: string;\r\n currentPeriodStart: string;\r\n currentPeriodEnd: string;\r\n cancelAtPeriodEnd: boolean;\r\n seats: number;\r\n paymentMethod?: PaymentMethodInfo;\r\n}\r\n\r\nexport interface PaymentMethodInfo {\r\n type: 'card' | 'bank_account' | 'paypal';\r\n brand?: string;\r\n last4?: string;\r\n expiryMonth?: number;\r\n expiryYear?: number;\r\n}\r\n\r\nexport interface InvoiceInfo {\r\n id: string;\r\n number: string;\r\n status: 'draft' | 'open' | 'paid' | 'void' | 'uncollectible';\r\n amount: number;\r\n currency: string;\r\n issuedAt: string;\r\n dueAt: string;\r\n paidAt?: string;\r\n downloadUrl?: string;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n PORTAL STATE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface LicensePortalState {\r\n loading: boolean;\r\n error: LicensePortalError | null;\r\n overview: CustomerLicenseOverview | null;\r\n selectedLicense: LicenseInfo | null;\r\n actionHistory: LicenseAction[];\r\n subscription: SubscriptionInfo | null;\r\n invoices: InvoiceInfo[];\r\n activeTab: 'overview' | 'licenses' | 'seats' | 'billing' | 'analytics' | 'settings';\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n LICENSE PORTAL API SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class LicensePortalService {\r\n private config: LicensePortalConfig;\r\n\r\n constructor(config: LicensePortalConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && {\r\n Authorization: `Bearer ${this.config.authToken}`,\r\n }),\r\n };\r\n\r\n const response = await fetch(url, {\r\n ...options,\r\n headers: { ...headers, ...options.headers },\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw {\r\n code: `HTTP_${response.status}`,\r\n message: error.message || response.statusText,\r\n details: error,\r\n } as LicensePortalError;\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /** Get customer license overview */\r\n async getOverview(): Promise<CustomerLicenseOverview> {\r\n return this.request<CustomerLicenseOverview>(\r\n `/customers/${this.config.customerId}/licenses/overview`,\r\n );\r\n }\r\n\r\n /** Get detailed license info */\r\n async getLicense(licenseKey: LicenseKey): Promise<LicenseInfo> {\r\n return this.request<LicenseInfo>(`/licenses/${encodeURIComponent(licenseKey)}`);\r\n }\r\n\r\n /** Activate license on current machine */\r\n async activateLicense(\r\n licenseKey: LicenseKey,\r\n machineId: string,\r\n machineName?: string,\r\n ): Promise<LicenseInfo> {\r\n return this.request<LicenseInfo>(`/licenses/${encodeURIComponent(licenseKey)}/activate`, {\r\n method: 'POST',\r\n body: JSON.stringify({ machineId, machineName }),\r\n });\r\n }\r\n\r\n /** Deactivate license from machine */\r\n async deactivateLicense(licenseKey: LicenseKey, machineId: string): Promise<void> {\r\n await this.request<void>(`/licenses/${encodeURIComponent(licenseKey)}/deactivate`, {\r\n method: 'POST',\r\n body: JSON.stringify({ machineId }),\r\n });\r\n }\r\n\r\n /** Transfer license to another user/org */\r\n async transferLicense(\r\n licenseKey: LicenseKey,\r\n targetEmail: string,\r\n notes?: string,\r\n ): Promise<{ transferId: string; status: string }> {\r\n return this.request(`/licenses/${encodeURIComponent(licenseKey)}/transfer`, {\r\n method: 'POST',\r\n body: JSON.stringify({ targetEmail, notes }),\r\n });\r\n }\r\n\r\n /** Get seat assignments */\r\n async getSeats(licenseKey: LicenseKey): Promise<SeatInfo[]> {\r\n return this.request<SeatInfo[]>(`/licenses/${encodeURIComponent(licenseKey)}/seats`);\r\n }\r\n\r\n /** Assign seat to user */\r\n async assignSeat(licenseKey: LicenseKey, userId: string, email: string): Promise<SeatInfo> {\r\n return this.request<SeatInfo>(`/licenses/${encodeURIComponent(licenseKey)}/seats`, {\r\n method: 'POST',\r\n body: JSON.stringify({ userId, email }),\r\n });\r\n }\r\n\r\n /** Remove seat assignment */\r\n async removeSeat(licenseKey: LicenseKey, seatId: string): Promise<void> {\r\n await this.request<void>(`/licenses/${encodeURIComponent(licenseKey)}/seats/${seatId}`, {\r\n method: 'DELETE',\r\n });\r\n }\r\n\r\n /** Get subscription info */\r\n async getSubscription(): Promise<SubscriptionInfo | null> {\r\n try {\r\n return await this.request<SubscriptionInfo>(\r\n `/customers/${this.config.customerId}/subscription`,\r\n );\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /** Get invoices */\r\n async getInvoices(limit = 10, offset = 0): Promise<{ invoices: InvoiceInfo[]; total: number }> {\r\n return this.request(\r\n `/customers/${this.config.customerId}/invoices?limit=${limit}&offset=${offset}`,\r\n );\r\n }\r\n\r\n /** Get action history */\r\n async getActionHistory(licenseKey?: LicenseKey, limit = 50): Promise<LicenseAction[]> {\r\n const params = new URLSearchParams({ limit: String(limit) });\r\n if (licenseKey) {\r\n params.set('licenseKey', licenseKey);\r\n }\r\n return this.request<LicenseAction[]>(`/customers/${this.config.customerId}/actions?${params}`);\r\n }\r\n\r\n /** Request license renewal */\r\n async requestRenewal(licenseKey: LicenseKey): Promise<{ checkoutUrl: string }> {\r\n return this.request(`/licenses/${encodeURIComponent(licenseKey)}/renew`, {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /** Request tier upgrade */\r\n async requestUpgrade(\r\n licenseKey: LicenseKey,\r\n targetTier: LicenseTier,\r\n ): Promise<{ checkoutUrl: string; proratedAmount: number }> {\r\n return this.request(`/licenses/${encodeURIComponent(licenseKey)}/upgrade`, {\r\n method: 'POST',\r\n body: JSON.stringify({ targetTier }),\r\n });\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n HELPER FUNCTIONS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function getStatusColor(status: LicenseStatus): string {\r\n const colors: Record<LicenseStatus, string> = {\r\n valid: '#22c55e',\r\n expired: '#ef4444',\r\n revoked: '#a855f7',\r\n invalid: '#f97316',\r\n grace: '#eab308',\r\n pending: '#6b7280',\r\n };\r\n return colors[status] || '#6b7280';\r\n}\r\n\r\nexport function getTierLabel(tier: LicenseTier): string {\r\n const labels: Record<LicenseTier, string> = {\r\n trial: 'Trial',\r\n personal: 'Personal',\r\n team: 'Team',\r\n enterprise: 'Enterprise',\r\n site: 'Site License',\r\n oem: 'OEM',\r\n };\r\n return labels[tier] || tier;\r\n}\r\n\r\nexport function formatDate(isoDate: string, locale = 'en-US'): string {\r\n return new Date(isoDate).toLocaleDateString(locale, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n });\r\n}\r\n\r\nexport function getDaysUntilExpiration(expiresAt: string | null): number | null {\r\n if (!expiresAt) {\r\n return null;\r\n }\r\n const now = new Date();\r\n const expiry = new Date(expiresAt);\r\n const diff = expiry.getTime() - now.getTime();\r\n return Math.ceil(diff / (1000 * 60 * 60 * 24));\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT HOOKS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function useLicensePortal(config: LicensePortalConfig) {\r\n const [state, setState] = useState<LicensePortalState>({\r\n loading: true,\r\n error: null,\r\n overview: null,\r\n selectedLicense: null,\r\n actionHistory: [],\r\n subscription: null,\r\n invoices: [],\r\n activeTab: 'overview',\r\n });\r\n\r\n const service = React.useMemo(\r\n () => new LicensePortalService(config),\r\n [config.apiBaseUrl, config.authToken, config.customerId],\r\n );\r\n\r\n const loadData = useCallback(async () => {\r\n setState((s) => ({ ...s, loading: true, error: null }));\r\n try {\r\n const [overview, subscription, actionsData, invoicesData] = await Promise.all([\r\n service.getOverview(),\r\n config.showBilling ? service.getSubscription() : null,\r\n service.getActionHistory(),\r\n config.showBilling ? service.getInvoices() : { invoices: [], total: 0 },\r\n ]);\r\n\r\n setState((s) => ({\r\n ...s,\r\n loading: false,\r\n overview,\r\n subscription,\r\n actionHistory: actionsData,\r\n invoices: invoicesData.invoices,\r\n }));\r\n } catch (error) {\r\n const licenseError = error as LicensePortalError;\r\n setState((s) => ({ ...s, loading: false, error: licenseError }));\r\n config.onError?.(licenseError);\r\n }\r\n }, [service, config]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const activateLicense = useCallback(\r\n async (licenseKey: LicenseKey, machineId: string, machineName?: string) => {\r\n try {\r\n const license = await service.activateLicense(licenseKey, machineId, machineName);\r\n config.onLicenseActivated?.(license);\r\n await loadData();\r\n return license;\r\n } catch (error) {\r\n config.onError?.(error as LicensePortalError);\r\n throw error;\r\n }\r\n },\r\n [service, config, loadData],\r\n );\r\n\r\n const deactivateLicense = useCallback(\r\n async (licenseKey: LicenseKey, machineId: string) => {\r\n try {\r\n await service.deactivateLicense(licenseKey, machineId);\r\n config.onLicenseDeactivated?.(licenseKey);\r\n await loadData();\r\n } catch (error) {\r\n config.onError?.(error as LicensePortalError);\r\n throw error;\r\n }\r\n },\r\n [service, config, loadData],\r\n );\r\n\r\n const transferLicense = useCallback(\r\n async (licenseKey: LicenseKey, targetEmail: string, notes?: string) => {\r\n try {\r\n const result = await service.transferLicense(licenseKey, targetEmail, notes);\r\n await loadData();\r\n return result;\r\n } catch (error) {\r\n config.onError?.(error as LicensePortalError);\r\n throw error;\r\n }\r\n },\r\n [service, config, loadData],\r\n );\r\n\r\n const selectLicense = useCallback((license: LicenseInfo | null) => {\r\n setState((s) => ({ ...s, selectedLicense: license }));\r\n }, []);\r\n\r\n const setActiveTab = useCallback((tab: LicensePortalState['activeTab']) => {\r\n setState((s) => ({ ...s, activeTab: tab }));\r\n }, []);\r\n\r\n return {\r\n state,\r\n service,\r\n loadData,\r\n activateLicense,\r\n deactivateLicense,\r\n transferLicense,\r\n selectLicense,\r\n setActiveTab,\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT COMPONENTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface LicensePortalProps extends LicensePortalConfig {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\n/** License status badge */\r\nexport const LicenseStatusBadge: React.FC<{\r\n status: LicenseStatus;\r\n size?: 'sm' | 'md' | 'lg';\r\n}> = ({ status, size = 'md' }) => {\r\n const sizeClasses = {\r\n sm: 'px-2 py-0.5 text-xs',\r\n md: 'px-2.5 py-1 text-sm',\r\n lg: 'px-3 py-1.5 text-base',\r\n };\r\n\r\n return (\r\n <span\r\n className={`inline-flex items-center rounded-full font-medium ${sizeClasses[size]}`}\r\n style={{\r\n backgroundColor: `${getStatusColor(status)}20`,\r\n color: getStatusColor(status),\r\n }}\r\n >\r\n <span\r\n className=\"mr-1.5 h-2 w-2 rounded-full\"\r\n style={{ backgroundColor: getStatusColor(status) }}\r\n />\r\n {status.charAt(0).toUpperCase() + status.slice(1)}\r\n </span>\r\n );\r\n};\r\n\r\n/** License tier badge */\r\nexport const LicenseTierBadge: React.FC<{\r\n tier: LicenseTier;\r\n size?: 'sm' | 'md' | 'lg';\r\n}> = ({ tier, size = 'md' }) => {\r\n const tierColors: Record<LicenseTier, string> = {\r\n trial: '#6b7280',\r\n personal: '#3b82f6',\r\n team: '#8b5cf6',\r\n enterprise: '#f59e0b',\r\n site: '#10b981',\r\n oem: '#ec4899',\r\n };\r\n\r\n const sizeClasses = {\r\n sm: 'px-2 py-0.5 text-xs',\r\n md: 'px-2.5 py-1 text-sm',\r\n lg: 'px-3 py-1.5 text-base',\r\n };\r\n\r\n return (\r\n <span\r\n className={`inline-flex items-center rounded font-semibold ${sizeClasses[size]}`}\r\n style={{\r\n backgroundColor: `${tierColors[tier]}20`,\r\n color: tierColors[tier],\r\n border: `1px solid ${tierColors[tier]}40`,\r\n }}\r\n >\r\n {getTierLabel(tier)}\r\n </span>\r\n );\r\n};\r\n\r\n/** License card component */\r\nexport const LicenseCard: React.FC<{\r\n license: LicenseInfo;\r\n onSelect?: () => void;\r\n onActivate?: () => void;\r\n onDeactivate?: () => void;\r\n selected?: boolean;\r\n}> = ({ license, onSelect, onActivate, onDeactivate, selected }) => {\r\n const daysRemaining = getDaysUntilExpiration(license.expiresAt);\r\n const isExpiringSoon = daysRemaining !== null && daysRemaining <= 30 && daysRemaining > 0;\r\n\r\n return (\r\n <div\r\n className={`rounded-lg border p-4 transition-all cursor-pointer hover:shadow-md ${\r\n selected ? 'border-blue-500 ring-2 ring-blue-200' : 'border-gray-200'\r\n }`}\r\n onClick={onSelect}\r\n >\r\n <div className=\"flex items-start justify-between mb-3\">\r\n <div>\r\n <div className=\"font-mono text-sm text-gray-500 mb-1\">{license.key}</div>\r\n <div className=\"flex items-center gap-2\">\r\n <LicenseTierBadge tier={license.tier} size=\"sm\" />\r\n <LicenseStatusBadge status={license.status} size=\"sm\" />\r\n </div>\r\n </div>\r\n <div className=\"text-right text-sm\">\r\n <div className=\"text-gray-500\">Seats</div>\r\n <div className=\"font-semibold\">\r\n {license.activeSeats}/{license.maxSeats ?? '∞'}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"text-sm text-gray-600 mb-3\">\r\n <div>Licensee: {license.licensee}</div>\r\n <div>Email: {license.email}</div>\r\n </div>\r\n\r\n {license.expiresAt && (\r\n <div className={`text-sm ${isExpiringSoon ? 'text-orange-600' : 'text-gray-500'}`}>\r\n {daysRemaining !== null && daysRemaining > 0 ? (\r\n <>\r\n Expires in {daysRemaining} days ({formatDate(license.expiresAt)})\r\n </>\r\n ) : daysRemaining === 0 ? (\r\n <span className=\"text-red-600\">Expires today</span>\r\n ) : (\r\n <span className=\"text-red-600\">Expired {formatDate(license.expiresAt)}</span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {(onActivate || onDeactivate) && (\r\n <div className=\"flex gap-2 mt-3 pt-3 border-t\">\r\n {onActivate && license.status === 'valid' && (\r\n <button\r\n className=\"px-3 py-1.5 text-sm bg-blue-500 text-white rounded hover:bg-blue-600\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onActivate();\r\n }}\r\n >\r\n Activate\r\n </button>\r\n )}\r\n {onDeactivate && (\r\n <button\r\n className=\"px-3 py-1.5 text-sm bg-gray-200 text-gray-700 rounded hover:bg-gray-300\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onDeactivate();\r\n }}\r\n >\r\n Deactivate\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n/** Main License Portal component */\r\nexport const LicensePortal: React.FC<LicensePortalProps> = (props) => {\r\n const { className, style, ...config } = props;\r\n const { state, activateLicense, deactivateLicense, selectLicense, setActiveTab, loadData } =\r\n useLicensePortal(config);\r\n\r\n if (state.loading) {\r\n return (\r\n <div className={`nice-license-portal ${className || ''}`} style={style}>\r\n <div className=\"flex items-center justify-center p-8\">\r\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500\" />\r\n <span className=\"ml-3 text-gray-600\">Loading licenses...</span>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (state.error) {\r\n return (\r\n <div className={`nice-license-portal ${className || ''}`} style={style}>\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <h3 className=\"text-red-800 font-semibold\">Error loading licenses</h3>\r\n <p className=\"text-red-600 text-sm mt-1\">{state.error.message}</p>\r\n <button\r\n className=\"mt-3 px-4 py-2 bg-red-100 text-red-700 rounded hover:bg-red-200\"\r\n onClick={loadData}\r\n >\r\n Retry\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n const { overview } = state;\r\n if (!overview) {\r\n return null;\r\n }\r\n\r\n const tabs = [\r\n { id: 'overview' as const, label: 'Overview' },\r\n { id: 'licenses' as const, label: 'Licenses' },\r\n { id: 'seats' as const, label: 'Seat Management' },\r\n ...(config.showBilling ? [{ id: 'billing' as const, label: 'Billing' }] : []),\r\n ...(config.showAnalytics ? [{ id: 'analytics' as const, label: 'Analytics' }] : []),\r\n { id: 'settings' as const, label: 'Settings' },\r\n ];\r\n\r\n return (\r\n <div className={`nice-license-portal ${className || ''}`} style={style}>\r\n {/* Header */}\r\n <div className=\"mb-6\">\r\n <h1 className=\"text-2xl font-bold text-gray-900\">License Portal</h1>\r\n <p className=\"text-gray-600\">Manage your Nice2Dev licenses and subscriptions</p>\r\n </div>\r\n\r\n {/* Tab Navigation */}\r\n <div className=\"border-b border-gray-200 mb-6\">\r\n <nav className=\"flex gap-6\">\r\n {tabs.map((tab) => (\r\n <button\r\n key={tab.id}\r\n className={`pb-3 text-sm font-medium border-b-2 transition-colors ${\r\n state.activeTab === tab.id\r\n ? 'border-blue-500 text-blue-600'\r\n : 'border-transparent text-gray-500 hover:text-gray-700'\r\n }`}\r\n onClick={() => setActiveTab(tab.id)}\r\n >\r\n {tab.label}\r\n </button>\r\n ))}\r\n </nav>\r\n </div>\r\n\r\n {/* Overview Tab */}\r\n {state.activeTab === 'overview' && (\r\n <div className=\"space-y-6\">\r\n {/* Stats Grid */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-4 gap-4\">\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <div className=\"text-sm text-gray-500\">Total Licenses</div>\r\n <div className=\"text-2xl font-bold\">{overview.totalLicenses}</div>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <div className=\"text-sm text-gray-500\">Active</div>\r\n <div className=\"text-2xl font-bold text-green-600\">{overview.activeLicenses}</div>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <div className=\"text-sm text-gray-500\">Seats Used</div>\r\n <div className=\"text-2xl font-bold\">\r\n {overview.usedSeats}/{overview.totalSeats}\r\n </div>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <div className=\"text-sm text-gray-500\">Expiring Soon</div>\r\n <div className=\"text-2xl font-bold text-orange-600\">\r\n {overview.expiringSoon.length}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Expiring Soon Alert */}\r\n {overview.expiringSoon.length > 0 && (\r\n <div className=\"bg-orange-50 border border-orange-200 rounded-lg p-4\">\r\n <h3 className=\"font-semibold text-orange-800 mb-2\">Licenses Expiring Soon</h3>\r\n <div className=\"space-y-2\">\r\n {overview.expiringSoon.map((license) => (\r\n <div key={license.key} className=\"flex items-center justify-between text-sm\">\r\n <span className=\"font-mono text-orange-700\">{license.key}</span>\r\n <span className=\"text-orange-600\">\r\n {getDaysUntilExpiration(license.expiresAt)} days remaining\r\n </span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Recent Activity */}\r\n <div className=\"bg-white rounded-lg border border-gray-200\">\r\n <div className=\"p-4 border-b border-gray-200\">\r\n <h3 className=\"font-semibold\">Recent Activity</h3>\r\n </div>\r\n <div className=\"divide-y divide-gray-100\">\r\n {state.actionHistory.slice(0, 5).map((action) => (\r\n <div key={action.id} className=\"p-4 flex items-center justify-between\">\r\n <div>\r\n <span className=\"capitalize font-medium\">{action.type}</span>\r\n <span className=\"text-gray-500 ml-2 font-mono text-sm\">\r\n {action.licenseKey}\r\n </span>\r\n </div>\r\n <span className=\"text-sm text-gray-500\">{formatDate(action.timestamp)}</span>\r\n </div>\r\n ))}\r\n {state.actionHistory.length === 0 && (\r\n <div className=\"p-4 text-gray-500 text-center\">No recent activity</div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Licenses Tab */}\r\n {state.activeTab === 'licenses' && (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {overview.licenses.map((license) => (\r\n <LicenseCard\r\n key={license.key}\r\n license={license}\r\n selected={state.selectedLicense?.key === license.key}\r\n onSelect={() => selectLicense(license)}\r\n onActivate={() => {\r\n // In real implementation, would prompt for machine ID\r\n activateLicense(license.key, 'machine-id-here');\r\n }}\r\n onDeactivate={() => {\r\n deactivateLicense(license.key, 'machine-id-here');\r\n }}\r\n />\r\n ))}\r\n {overview.licenses.length === 0 && (\r\n <div className=\"col-span-full text-center py-8 text-gray-500\">\r\n No licenses found. Contact support to purchase a license.\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Billing Tab */}\r\n {state.activeTab === 'billing' && config.showBilling && (\r\n <div className=\"space-y-6\">\r\n {/* Subscription Info */}\r\n {state.subscription && (\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"font-semibold mb-4\">Current Subscription</h3>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div>\r\n <div className=\"text-sm text-gray-500\">Plan</div>\r\n <div className=\"font-medium\">{state.subscription.plan}</div>\r\n </div>\r\n <div>\r\n <div className=\"text-sm text-gray-500\">Status</div>\r\n <div\r\n className={`font-medium capitalize ${\r\n state.subscription.status === 'active' ? 'text-green-600' : 'text-orange-600'\r\n }`}\r\n >\r\n {state.subscription.status}\r\n </div>\r\n </div>\r\n <div>\r\n <div className=\"text-sm text-gray-500\">Current Period</div>\r\n <div className=\"font-medium\">\r\n {formatDate(state.subscription.currentPeriodStart)} -{' '}\r\n {formatDate(state.subscription.currentPeriodEnd)}\r\n </div>\r\n </div>\r\n <div>\r\n <div className=\"text-sm text-gray-500\">Seats</div>\r\n <div className=\"font-medium\">{state.subscription.seats}</div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Invoices */}\r\n <div className=\"bg-white rounded-lg border border-gray-200\">\r\n <div className=\"p-4 border-b border-gray-200\">\r\n <h3 className=\"font-semibold\">Invoices</h3>\r\n </div>\r\n <div className=\"divide-y divide-gray-100\">\r\n {state.invoices.map((invoice) => (\r\n <div key={invoice.id} className=\"p-4 flex items-center justify-between\">\r\n <div>\r\n <div className=\"font-medium\">{invoice.number}</div>\r\n <div className=\"text-sm text-gray-500\">{formatDate(invoice.issuedAt)}</div>\r\n </div>\r\n <div className=\"flex items-center gap-4\">\r\n <span\r\n className={`px-2 py-1 rounded text-sm ${\r\n invoice.status === 'paid'\r\n ? 'bg-green-100 text-green-700'\r\n : 'bg-gray-100 text-gray-700'\r\n }`}\r\n >\r\n {invoice.status}\r\n </span>\r\n <span className=\"font-medium\">\r\n {invoice.currency} {invoice.amount.toFixed(2)}\r\n </span>\r\n {invoice.downloadUrl && (\r\n <a\r\n href={invoice.downloadUrl}\r\n className=\"text-blue-500 hover:text-blue-600\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n Download\r\n </a>\r\n )}\r\n </div>\r\n </div>\r\n ))}\r\n {state.invoices.length === 0 && (\r\n <div className=\"p-4 text-gray-500 text-center\">No invoices</div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Seats Tab */}\r\n {state.activeTab === 'seats' && (\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"font-semibold mb-4\">Seat Management</h3>\r\n <p className=\"text-gray-500 mb-4\">Select a license to manage seat assignments.</p>\r\n {/* Seat management implementation */}\r\n </div>\r\n )}\r\n\r\n {/* Settings Tab */}\r\n {state.activeTab === 'settings' && (\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"font-semibold mb-4\">Portal Settings</h3>\r\n {/* Settings implementation */}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default LicensePortal;\r\n","/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — Self-Service License Activation Wizard\r\n \r\n Multi-step wizard for customers to activate licenses with\r\n hardware binding, validation, and confirmation.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport React, { useState, useCallback } from 'react';\r\n\r\nimport { generateFingerprint, generateMachineId } from '../HardwareFingerprint';\r\nimport type { LicenseInfo, LicenseKey, LicenseValidationResult } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type ActivationStep =\r\n | 'enter-key'\r\n | 'validate'\r\n | 'hardware-check'\r\n | 'terms'\r\n | 'activating'\r\n | 'success'\r\n | 'error';\r\n\r\nexport interface ActivationWizardConfig {\r\n /** API base URL */\r\n apiBaseUrl: string;\r\n /** API authentication token */\r\n authToken?: string;\r\n /** Terms of service URL */\r\n termsUrl?: string;\r\n /** Privacy policy URL */\r\n privacyUrl?: string;\r\n /** Support email */\r\n supportEmail?: string;\r\n /** Allow offline activation */\r\n allowOfflineActivation?: boolean;\r\n /** Machine name (auto-detected if not provided) */\r\n machineName?: string;\r\n /** Callback when activation succeeds */\r\n onActivationSuccess?: (license: LicenseInfo) => void;\r\n /** Callback when activation fails */\r\n onActivationError?: (error: ActivationError) => void;\r\n /** Callback when wizard is canceled */\r\n onCancel?: () => void;\r\n}\r\n\r\nexport interface ActivationError {\r\n code: string;\r\n message: string;\r\n retryable: boolean;\r\n supportRequired?: boolean;\r\n}\r\n\r\nexport interface ActivationState {\r\n step: ActivationStep;\r\n licenseKey: string;\r\n validation: LicenseValidationResult | null;\r\n machineId: string | null;\r\n fingerprint: string | null;\r\n machineName: string;\r\n termsAccepted: boolean;\r\n error: ActivationError | null;\r\n activatedLicense: LicenseInfo | null;\r\n offlineChallenge: string | null;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n ACTIVATION SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class ActivationService {\r\n private config: ActivationWizardConfig;\r\n\r\n constructor(config: ActivationWizardConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { Authorization: `Bearer ${this.config.authToken}` }),\r\n };\r\n\r\n const response = await fetch(url, { ...options, headers });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw {\r\n code: `HTTP_${response.status}`,\r\n message: error.message || 'Request failed',\r\n retryable: response.status >= 500,\r\n supportRequired: response.status === 403,\r\n } as ActivationError;\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n async validateKey(licenseKey: string): Promise<LicenseValidationResult> {\r\n return this.request<LicenseValidationResult>('/licenses/validate', {\r\n method: 'POST',\r\n body: JSON.stringify({ licenseKey }),\r\n });\r\n }\r\n\r\n async checkHardware(\r\n licenseKey: string,\r\n machineId: string,\r\n fingerprint: string,\r\n ): Promise<{ allowed: boolean; reason?: string; existingMachines?: number }> {\r\n return this.request('/licenses/hardware-check', {\r\n method: 'POST',\r\n body: JSON.stringify({ licenseKey, machineId, fingerprint }),\r\n });\r\n }\r\n\r\n async activate(\r\n licenseKey: string,\r\n machineId: string,\r\n fingerprint: string,\r\n machineName: string,\r\n ): Promise<LicenseInfo> {\r\n return this.request<LicenseInfo>(`/licenses/${encodeURIComponent(licenseKey)}/activate`, {\r\n method: 'POST',\r\n body: JSON.stringify({ machineId, fingerprint, machineName }),\r\n });\r\n }\r\n\r\n async getOfflineChallenge(licenseKey: string, machineId: string): Promise<string> {\r\n const result = await this.request<{ challenge: string }>('/licenses/offline/challenge', {\r\n method: 'POST',\r\n body: JSON.stringify({ licenseKey, machineId }),\r\n });\r\n return result.challenge;\r\n }\r\n\r\n async activateOffline(\r\n licenseKey: string,\r\n machineId: string,\r\n response: string,\r\n ): Promise<LicenseInfo> {\r\n return this.request<LicenseInfo>('/licenses/offline/activate', {\r\n method: 'POST',\r\n body: JSON.stringify({ licenseKey, machineId, response }),\r\n });\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n HELPER FUNCTIONS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nfunction formatLicenseKey(key: string): string {\r\n // Remove non-alphanumeric and format as XXXX-XXXX-XXXX-XXXX-XXXX\r\n const clean = key.replace(/[^A-Za-z0-9]/g, '').toUpperCase();\r\n const parts: string[] = [];\r\n for (let i = 0; i < clean.length; i += 4) {\r\n parts.push(clean.slice(i, i + 4));\r\n }\r\n return parts.slice(0, 5).join('-');\r\n}\r\n\r\nfunction validateKeyFormat(key: string): boolean {\r\n const pattern = /^[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/;\r\n return pattern.test(key);\r\n}\r\n\r\nasync function getDefaultMachineName(): Promise<string> {\r\n if (typeof window !== 'undefined' && 'userAgent' in navigator) {\r\n const ua = navigator.userAgent;\r\n if (ua.includes('Windows')) {\r\n return 'Windows PC';\r\n }\r\n if (ua.includes('Mac')) {\r\n return 'Mac';\r\n }\r\n if (ua.includes('Linux')) {\r\n return 'Linux Machine';\r\n }\r\n if (ua.includes('Android')) {\r\n return 'Android Device';\r\n }\r\n if (ua.includes('iOS')) {\r\n return 'iOS Device';\r\n }\r\n }\r\n return 'Unknown Device';\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT HOOK\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function useActivationWizard(config: ActivationWizardConfig) {\r\n const [state, setState] = useState<ActivationState>({\r\n step: 'enter-key',\r\n licenseKey: '',\r\n validation: null,\r\n machineId: null,\r\n fingerprint: null,\r\n machineName: config.machineName || '',\r\n termsAccepted: false,\r\n error: null,\r\n activatedLicense: null,\r\n offlineChallenge: null,\r\n });\r\n\r\n const service = React.useMemo(() => new ActivationService(config), [config]);\r\n\r\n const setLicenseKey = useCallback((key: string) => {\r\n const formatted = formatLicenseKey(key);\r\n setState((s) => ({ ...s, licenseKey: formatted, error: null }));\r\n }, []);\r\n\r\n const setMachineName = useCallback((name: string) => {\r\n setState((s) => ({ ...s, machineName: name }));\r\n }, []);\r\n\r\n const setTermsAccepted = useCallback((accepted: boolean) => {\r\n setState((s) => ({ ...s, termsAccepted: accepted }));\r\n }, []);\r\n\r\n const validateKey = useCallback(async () => {\r\n if (!validateKeyFormat(state.licenseKey)) {\r\n setState((s) => ({\r\n ...s,\r\n error: {\r\n code: 'INVALID_FORMAT',\r\n message: 'License key format is invalid. Expected format: XXXX-XXXX-XXXX-XXXX-XXXX',\r\n retryable: true,\r\n },\r\n }));\r\n return;\r\n }\r\n\r\n setState((s) => ({ ...s, step: 'validate', error: null }));\r\n\r\n try {\r\n const validation = await service.validateKey(state.licenseKey);\r\n\r\n if (!validation.valid) {\r\n setState((s) => ({\r\n ...s,\r\n step: 'error',\r\n error: {\r\n code: validation.errorCode || 'VALIDATION_FAILED',\r\n message: validation.errorMessage || 'License key validation failed',\r\n retryable: true,\r\n },\r\n }));\r\n return;\r\n }\r\n\r\n // Collect hardware info\r\n const fingerprintData = await generateFingerprint();\r\n const machineId = await generateMachineId();\r\n const machineName = state.machineName || (await getDefaultMachineName());\r\n\r\n setState((s) => ({\r\n ...s,\r\n validation,\r\n machineId,\r\n fingerprint: fingerprintData,\r\n machineName,\r\n step: 'hardware-check',\r\n }));\r\n\r\n // Check hardware binding\r\n const hwCheck = await service.checkHardware(state.licenseKey, machineId, fingerprintData);\r\n\r\n if (!hwCheck.allowed) {\r\n setState((s) => ({\r\n ...s,\r\n step: 'error',\r\n error: {\r\n code: 'HARDWARE_LIMIT',\r\n message: hwCheck.reason || 'Maximum hardware activations reached',\r\n retryable: false,\r\n supportRequired: true,\r\n },\r\n }));\r\n return;\r\n }\r\n\r\n // Move to terms acceptance\r\n setState((s) => ({ ...s, step: 'terms' }));\r\n } catch (error) {\r\n setState((s) => ({\r\n ...s,\r\n step: 'error',\r\n error: error as ActivationError,\r\n }));\r\n }\r\n }, [state.licenseKey, state.machineName, service]);\r\n\r\n const acceptTermsAndActivate = useCallback(async () => {\r\n if (!state.termsAccepted) {\r\n setState((s) => ({\r\n ...s,\r\n error: {\r\n code: 'TERMS_NOT_ACCEPTED',\r\n message: 'Please accept the terms of service to continue',\r\n retryable: true,\r\n },\r\n }));\r\n return;\r\n }\r\n\r\n setState((s) => ({ ...s, step: 'activating', error: null }));\r\n\r\n try {\r\n const license = await service.activate(\r\n state.licenseKey,\r\n state.machineId!,\r\n state.fingerprint!,\r\n state.machineName,\r\n );\r\n\r\n setState((s) => ({\r\n ...s,\r\n step: 'success',\r\n activatedLicense: license,\r\n }));\r\n\r\n config.onActivationSuccess?.(license);\r\n } catch (error) {\r\n const activationError = error as ActivationError;\r\n setState((s) => ({\r\n ...s,\r\n step: 'error',\r\n error: activationError,\r\n }));\r\n config.onActivationError?.(activationError);\r\n }\r\n }, [state, service, config]);\r\n\r\n const startOfflineActivation = useCallback(async () => {\r\n if (!config.allowOfflineActivation) {\r\n return;\r\n }\r\n\r\n try {\r\n const machineId = state.machineId || (await generateMachineId());\r\n const challenge = await service.getOfflineChallenge(state.licenseKey, machineId);\r\n setState((s) => ({\r\n ...s,\r\n machineId,\r\n offlineChallenge: challenge,\r\n }));\r\n } catch (error) {\r\n setState((s) => ({\r\n ...s,\r\n error: error as ActivationError,\r\n }));\r\n }\r\n }, [state.licenseKey, state.machineId, service, config.allowOfflineActivation]);\r\n\r\n const submitOfflineResponse = useCallback(\r\n async (response: string) => {\r\n setState((s) => ({ ...s, step: 'activating', error: null }));\r\n\r\n try {\r\n const license = await service.activateOffline(state.licenseKey, state.machineId!, response);\r\n\r\n setState((s) => ({\r\n ...s,\r\n step: 'success',\r\n activatedLicense: license,\r\n }));\r\n\r\n config.onActivationSuccess?.(license);\r\n } catch (error) {\r\n const activationError = error as ActivationError;\r\n setState((s) => ({\r\n ...s,\r\n step: 'error',\r\n error: activationError,\r\n }));\r\n config.onActivationError?.(activationError);\r\n }\r\n },\r\n [state.licenseKey, state.machineId, service, config],\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setState({\r\n step: 'enter-key',\r\n licenseKey: '',\r\n validation: null,\r\n machineId: null,\r\n fingerprint: null,\r\n machineName: config.machineName || '',\r\n termsAccepted: false,\r\n error: null,\r\n activatedLicense: null,\r\n offlineChallenge: null,\r\n });\r\n }, [config.machineName]);\r\n\r\n const goBack = useCallback(() => {\r\n setState((s) => {\r\n const stepOrder: ActivationStep[] = [\r\n 'enter-key',\r\n 'validate',\r\n 'hardware-check',\r\n 'terms',\r\n 'activating',\r\n 'success',\r\n ];\r\n const currentIndex = stepOrder.indexOf(s.step);\r\n if (currentIndex > 0) {\r\n return { ...s, step: stepOrder[currentIndex - 1], error: null };\r\n }\r\n return s;\r\n });\r\n }, []);\r\n\r\n return {\r\n state,\r\n setLicenseKey,\r\n setMachineName,\r\n setTermsAccepted,\r\n validateKey,\r\n acceptTermsAndActivate,\r\n startOfflineActivation,\r\n submitOfflineResponse,\r\n reset,\r\n goBack,\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT COMPONENTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface ActivationWizardProps extends ActivationWizardConfig {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\n/** Step indicator component */\r\nconst StepIndicator: React.FC<{ currentStep: ActivationStep }> = ({ currentStep }) => {\r\n const steps = [\r\n { id: 'enter-key', label: 'Enter Key' },\r\n { id: 'validate', label: 'Validate' },\r\n { id: 'hardware-check', label: 'Hardware' },\r\n { id: 'terms', label: 'Terms' },\r\n { id: 'activating', label: 'Activate' },\r\n { id: 'success', label: 'Done' },\r\n ];\r\n\r\n const stepOrder: ActivationStep[] = [\r\n 'enter-key',\r\n 'validate',\r\n 'hardware-check',\r\n 'terms',\r\n 'activating',\r\n 'success',\r\n ];\r\n const currentIndex = stepOrder.indexOf(currentStep);\r\n\r\n return (\r\n <div className=\"flex items-center justify-between mb-8\">\r\n {steps.map((step, index) => (\r\n <React.Fragment key={step.id}>\r\n <div className=\"flex flex-col items-center\">\r\n <div\r\n className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium ${\r\n index < currentIndex\r\n ? 'bg-green-500 text-white'\r\n : index === currentIndex\r\n ? 'bg-blue-500 text-white'\r\n : 'bg-gray-200 text-gray-500'\r\n }`}\r\n >\r\n {index < currentIndex ? '✓' : index + 1}\r\n </div>\r\n <span className=\"text-xs mt-1 text-gray-500\">{step.label}</span>\r\n </div>\r\n {index < steps.length - 1 && (\r\n <div\r\n className={`flex-1 h-0.5 mx-2 ${\r\n index < currentIndex ? 'bg-green-500' : 'bg-gray-200'\r\n }`}\r\n />\r\n )}\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\n/** Main Activation Wizard component */\r\nexport const ActivationWizard: React.FC<ActivationWizardProps> = (props) => {\r\n const { className, style, ...config } = props;\r\n const {\r\n state,\r\n setLicenseKey,\r\n setMachineName,\r\n setTermsAccepted,\r\n validateKey,\r\n acceptTermsAndActivate,\r\n startOfflineActivation,\r\n reset,\r\n goBack,\r\n } = useActivationWizard(config);\r\n\r\n const [offlineResponse, setOfflineResponse] = useState('');\r\n\r\n return (\r\n <div\r\n className={`nice-activation-wizard bg-white rounded-lg shadow-lg p-8 max-w-xl mx-auto ${className || ''}`}\r\n style={style}\r\n >\r\n {/* Header */}\r\n <div className=\"text-center mb-6\">\r\n <h1 className=\"text-2xl font-bold text-gray-900\">Activate License</h1>\r\n <p className=\"text-gray-600 mt-1\">Follow the steps to activate your Nice2Dev license</p>\r\n </div>\r\n\r\n {/* Step Indicator */}\r\n {state.step !== 'error' && <StepIndicator currentStep={state.step} />}\r\n\r\n {/* Error State */}\r\n {state.step === 'error' && state.error && (\r\n <div className=\"space-y-4\">\r\n <div className=\"bg-red-50 border border-red-200 rounded-lg p-6 text-center\">\r\n <div className=\"text-red-500 text-4xl mb-3\">⚠️</div>\r\n <h2 className=\"text-lg font-semibold text-red-800\">Activation Failed</h2>\r\n <p className=\"text-red-600 mt-2\">{state.error.message}</p>\r\n {state.error.supportRequired && config.supportEmail && (\r\n <p className=\"text-sm text-gray-600 mt-4\">\r\n Please contact support at{' '}\r\n <a href={`mailto:${config.supportEmail}`} className=\"text-blue-500 hover:underline\">\r\n {config.supportEmail}\r\n </a>\r\n </p>\r\n )}\r\n </div>\r\n <div className=\"flex gap-3 justify-center\">\r\n {state.error.retryable && (\r\n <button\r\n onClick={() => goBack()}\r\n className=\"px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600\"\r\n >\r\n Try Again\r\n </button>\r\n )}\r\n <button\r\n onClick={reset}\r\n className=\"px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n >\r\n Start Over\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Step 1: Enter License Key */}\r\n {state.step === 'enter-key' && (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">License Key</label>\r\n <input\r\n type=\"text\"\r\n value={state.licenseKey}\r\n onChange={(e) => setLicenseKey(e.target.value)}\r\n placeholder=\"XXXX-XXXX-XXXX-XXXX-XXXX\"\r\n className=\"w-full px-4 py-3 border border-gray-300 rounded-lg font-mono text-center text-lg tracking-wider focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n maxLength={29}\r\n />\r\n <p className=\"text-sm text-gray-500 mt-2\">\r\n Enter the license key you received upon purchase\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n Machine Name (optional)\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={state.machineName}\r\n onChange={(e) => setMachineName(e.target.value)}\r\n placeholder=\"My Work PC\"\r\n className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n />\r\n </div>\r\n\r\n {state.error && (\r\n <div className=\"text-red-600 text-sm bg-red-50 p-3 rounded-lg\">\r\n {state.error.message}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={validateKey}\r\n disabled={!state.licenseKey}\r\n className=\"flex-1 px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed\"\r\n >\r\n Continue\r\n </button>\r\n {config.onCancel && (\r\n <button\r\n onClick={config.onCancel}\r\n className=\"px-6 py-3 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n >\r\n Cancel\r\n </button>\r\n )}\r\n </div>\r\n\r\n {config.allowOfflineActivation && (\r\n <button\r\n onClick={startOfflineActivation}\r\n className=\"w-full text-sm text-blue-500 hover:underline\"\r\n >\r\n Activate offline →\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Step 2-3: Validating / Hardware Check */}\r\n {(state.step === 'validate' || state.step === 'hardware-check') && (\r\n <div className=\"text-center py-8\">\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto\" />\r\n <h2 className=\"text-lg font-semibold mt-4\">\r\n {state.step === 'validate' ? 'Validating License...' : 'Checking Hardware...'}\r\n </h2>\r\n <p className=\"text-gray-500 mt-2\">\r\n {state.step === 'validate'\r\n ? 'Verifying your license key with the server'\r\n : 'Collecting hardware information for activation'}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Step 4: Terms Acceptance */}\r\n {state.step === 'terms' && (\r\n <div className=\"space-y-6\">\r\n <div className=\"bg-gray-50 rounded-lg p-4\">\r\n <h3 className=\"font-semibold mb-3\">License Details</h3>\r\n {state.validation?.license && (\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div className=\"text-gray-500\">Tier:</div>\r\n <div className=\"font-medium capitalize\">{state.validation.license.tier}</div>\r\n <div className=\"text-gray-500\">Licensee:</div>\r\n <div className=\"font-medium\">{state.validation.license.licensee}</div>\r\n <div className=\"text-gray-500\">Max Machines:</div>\r\n <div className=\"font-medium\">{state.validation.license.maxMachines}</div>\r\n <div className=\"text-gray-500\">This Machine:</div>\r\n <div className=\"font-medium\">{state.machineName}</div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"border border-gray-200 rounded-lg p-4 max-h-48 overflow-y-auto text-sm text-gray-600\">\r\n <h4 className=\"font-semibold text-gray-800 mb-2\">Terms of Service</h4>\r\n <p>\r\n By activating this license, you agree to the Nice2Dev Software License Agreement. This\r\n license grants you the right to use the software on the specified number of machines\r\n according to your license tier. Unauthorized redistribution, reverse engineering, or\r\n violation of these terms may result in license revocation.\r\n </p>\r\n </div>\r\n\r\n <label className=\"flex items-start gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={state.termsAccepted}\r\n onChange={(e) => setTermsAccepted(e.target.checked)}\r\n className=\"mt-1 w-4 h-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500\"\r\n />\r\n <span className=\"text-sm text-gray-700\">\r\n I accept the{' '}\r\n {config.termsUrl ? (\r\n <a\r\n href={config.termsUrl}\r\n className=\"text-blue-500 hover:underline\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n Terms of Service\r\n </a>\r\n ) : (\r\n 'Terms of Service'\r\n )}\r\n {config.privacyUrl && (\r\n <>\r\n {' '}\r\n and{' '}\r\n <a\r\n href={config.privacyUrl}\r\n className=\"text-blue-500 hover:underline\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n Privacy Policy\r\n </a>\r\n </>\r\n )}\r\n </span>\r\n </label>\r\n\r\n {state.error && (\r\n <div className=\"text-red-600 text-sm bg-red-50 p-3 rounded-lg\">\r\n {state.error.message}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={goBack}\r\n className=\"px-6 py-3 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n >\r\n Back\r\n </button>\r\n <button\r\n onClick={acceptTermsAndActivate}\r\n disabled={!state.termsAccepted}\r\n className=\"flex-1 px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed\"\r\n >\r\n Activate License\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Step 5: Activating */}\r\n {state.step === 'activating' && (\r\n <div className=\"text-center py-8\">\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto\" />\r\n <h2 className=\"text-lg font-semibold mt-4\">Activating License...</h2>\r\n <p className=\"text-gray-500 mt-2\">Please wait while we activate your license</p>\r\n </div>\r\n )}\r\n\r\n {/* Step 6: Success */}\r\n {state.step === 'success' && state.activatedLicense && (\r\n <div className=\"text-center space-y-6\">\r\n <div className=\"text-green-500 text-6xl\">✓</div>\r\n <div>\r\n <h2 className=\"text-xl font-bold text-gray-900\">License Activated!</h2>\r\n <p className=\"text-gray-600 mt-2\">\r\n Your license has been successfully activated on this machine.\r\n </p>\r\n </div>\r\n\r\n <div className=\"bg-green-50 rounded-lg p-4 text-left\">\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div className=\"text-gray-500\">License Key:</div>\r\n <div className=\"font-mono\">{state.activatedLicense.key}</div>\r\n <div className=\"text-gray-500\">Tier:</div>\r\n <div className=\"capitalize\">{state.activatedLicense.tier}</div>\r\n <div className=\"text-gray-500\">Machine:</div>\r\n <div>{state.machineName}</div>\r\n {state.activatedLicense.expiresAt && (\r\n <>\r\n <div className=\"text-gray-500\">Expires:</div>\r\n <div>{new Date(state.activatedLicense.expiresAt).toLocaleDateString()}</div>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <button\r\n onClick={() => {\r\n reset();\r\n config.onCancel?.();\r\n }}\r\n className=\"px-8 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600\"\r\n >\r\n Done\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Offline Activation Modal */}\r\n {state.offlineChallenge && (\r\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50\">\r\n <div className=\"bg-white rounded-lg p-6 max-w-md w-full\">\r\n <h3 className=\"text-lg font-semibold mb-4\">Offline Activation</h3>\r\n\r\n <div className=\"space-y-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\r\n Challenge Code (send this to support):\r\n </label>\r\n <textarea\r\n readOnly\r\n value={state.offlineChallenge}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded font-mono text-xs h-20\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\r\n Response Code (from support):\r\n </label>\r\n <textarea\r\n value={offlineResponse}\r\n onChange={(e) => setOfflineResponse(e.target.value)}\r\n placeholder=\"Paste the response code here...\"\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded font-mono text-xs h-20\"\r\n />\r\n </div>\r\n\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={() => {\r\n /* submitOfflineResponse would go here */\r\n }}\r\n disabled={!offlineResponse}\r\n className=\"flex-1 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-300\"\r\n >\r\n Activate\r\n </button>\r\n <button\r\n onClick={() => {\r\n setOfflineResponse('');\r\n }}\r\n className=\"px-4 py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300\"\r\n >\r\n Cancel\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default ActivationWizard;\r\n","/* eslint-disable jsx-a11y/click-events-have-key-events -- modal overlay backdrops (Esc-on-parent provides keyboard close), selection rows in .map() accompanied by visible cursor:pointer styling and sibling buttons; full keyboard migration via useAccessibleClick + extracted subcomponents tracked in TODO_1.0.10 A2.3 */\r\n/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — License Transfer System\r\n \r\n Workflow for transferring licenses between users/organizations\r\n with validation, notifications, and audit trail.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport React, { useState, useCallback } from 'react';\r\n\r\nimport type { LicenseInfo, LicenseKey } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type TransferStatus =\r\n | 'pending'\r\n | 'pending_approval'\r\n | 'approved'\r\n | 'rejected'\r\n | 'completed'\r\n | 'cancelled'\r\n | 'expired';\r\n\r\nexport interface TransferRequest {\r\n id: string;\r\n licenseKey: LicenseKey;\r\n license: LicenseInfo;\r\n fromOrganization: TransferParty;\r\n toOrganization: TransferParty;\r\n status: TransferStatus;\r\n createdAt: string;\r\n updatedAt: string;\r\n expiresAt: string;\r\n notes?: string;\r\n approvalRequired: boolean;\r\n approvedBy?: string;\r\n approvedAt?: string;\r\n rejectionReason?: string;\r\n transferToken?: string;\r\n notificationsSent: TransferNotification[];\r\n}\r\n\r\nexport interface TransferParty {\r\n id: string;\r\n name: string;\r\n email: string;\r\n organizationId?: string;\r\n organizationName?: string;\r\n}\r\n\r\nexport interface TransferNotification {\r\n type: 'initiated' | 'pending_approval' | 'approved' | 'rejected' | 'completed' | 'reminder';\r\n sentAt: string;\r\n recipient: string;\r\n delivered: boolean;\r\n}\r\n\r\nexport interface TransferConfig {\r\n apiBaseUrl: string;\r\n authToken?: string;\r\n /** Require admin approval for transfers */\r\n requireApproval?: boolean;\r\n /** Days before pending transfer expires */\r\n expirationDays?: number;\r\n /** Allow transfers to external organizations */\r\n allowExternalTransfers?: boolean;\r\n /** Notification settings */\r\n notifications?: {\r\n email: boolean;\r\n inApp: boolean;\r\n slack?: string;\r\n };\r\n onTransferComplete?: (transfer: TransferRequest) => void;\r\n onError?: (error: TransferError) => void;\r\n}\r\n\r\nexport interface TransferError {\r\n code: string;\r\n message: string;\r\n}\r\n\r\nexport type TransferStep =\r\n | 'select-license'\r\n | 'enter-recipient'\r\n | 'review'\r\n | 'confirmation'\r\n | 'processing'\r\n | 'complete';\r\n\r\nexport interface TransferFormData {\r\n licenseKey: string;\r\n recipientEmail: string;\r\n recipientName: string;\r\n notes: string;\r\n transferReason: 'employee_change' | 'department_transfer' | 'organization_sale' | 'other';\r\n confirmDeactivation: boolean;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TRANSFER SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class LicenseTransferService {\r\n private config: TransferConfig;\r\n\r\n constructor(config: TransferConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { Authorization: `Bearer ${this.config.authToken}` }),\r\n };\r\n\r\n const response = await fetch(url, { ...options, headers });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw {\r\n code: `HTTP_${response.status}`,\r\n message: error.message || 'Request failed',\r\n } as TransferError;\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /** Get transferable licenses */\r\n async getTransferableLicenses(): Promise<LicenseInfo[]> {\r\n return this.request<LicenseInfo[]>('/licenses/transferable');\r\n }\r\n\r\n /** Validate recipient email/organization */\r\n async validateRecipient(email: string): Promise<{\r\n valid: boolean;\r\n recipientInfo?: TransferParty;\r\n isExternal: boolean;\r\n warnings?: string[];\r\n }> {\r\n return this.request('/transfers/validate-recipient', {\r\n method: 'POST',\r\n body: JSON.stringify({ email }),\r\n });\r\n }\r\n\r\n /** Initiate transfer */\r\n async initiateTransfer(data: {\r\n licenseKey: string;\r\n recipientEmail: string;\r\n recipientName: string;\r\n notes?: string;\r\n reason: string;\r\n }): Promise<TransferRequest> {\r\n return this.request<TransferRequest>('/transfers', {\r\n method: 'POST',\r\n body: JSON.stringify(data),\r\n });\r\n }\r\n\r\n /** Get transfer by ID */\r\n async getTransfer(transferId: string): Promise<TransferRequest> {\r\n return this.request<TransferRequest>(`/transfers/${transferId}`);\r\n }\r\n\r\n /** Get pending transfers */\r\n async getPendingTransfers(): Promise<TransferRequest[]> {\r\n return this.request<TransferRequest[]>('/transfers?status=pending,pending_approval');\r\n }\r\n\r\n /** Get transfer history */\r\n async getTransferHistory(licenseKey?: string): Promise<TransferRequest[]> {\r\n const params = licenseKey ? `?licenseKey=${encodeURIComponent(licenseKey)}` : '';\r\n return this.request<TransferRequest[]>(`/transfers/history${params}`);\r\n }\r\n\r\n /** Cancel transfer */\r\n async cancelTransfer(transferId: string, reason?: string): Promise<TransferRequest> {\r\n return this.request<TransferRequest>(`/transfers/${transferId}/cancel`, {\r\n method: 'POST',\r\n body: JSON.stringify({ reason }),\r\n });\r\n }\r\n\r\n /** Accept transfer (as recipient) */\r\n async acceptTransfer(transferId: string, token: string): Promise<TransferRequest> {\r\n return this.request<TransferRequest>(`/transfers/${transferId}/accept`, {\r\n method: 'POST',\r\n body: JSON.stringify({ token }),\r\n });\r\n }\r\n\r\n /** Approve transfer (admin) */\r\n async approveTransfer(transferId: string): Promise<TransferRequest> {\r\n return this.request<TransferRequest>(`/transfers/${transferId}/approve`, {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /** Reject transfer (admin) */\r\n async rejectTransfer(transferId: string, reason: string): Promise<TransferRequest> {\r\n return this.request<TransferRequest>(`/transfers/${transferId}/reject`, {\r\n method: 'POST',\r\n body: JSON.stringify({ reason }),\r\n });\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n HELPERS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function getTransferStatusColor(status: TransferStatus): string {\r\n const colors: Record<TransferStatus, string> = {\r\n pending: '#f59e0b',\r\n pending_approval: '#8b5cf6',\r\n approved: '#3b82f6',\r\n rejected: '#ef4444',\r\n completed: '#22c55e',\r\n cancelled: '#6b7280',\r\n expired: '#9ca3af',\r\n };\r\n return colors[status];\r\n}\r\n\r\nexport function getTransferStatusLabel(status: TransferStatus): string {\r\n const labels: Record<TransferStatus, string> = {\r\n pending: 'Pending Acceptance',\r\n pending_approval: 'Awaiting Approval',\r\n approved: 'Approved',\r\n rejected: 'Rejected',\r\n completed: 'Completed',\r\n cancelled: 'Cancelled',\r\n expired: 'Expired',\r\n };\r\n return labels[status];\r\n}\r\n\r\nconst TRANSFER_REASONS = [\r\n { value: 'employee_change', label: 'Employee leaving/joining' },\r\n { value: 'department_transfer', label: 'Department transfer' },\r\n { value: 'organization_sale', label: 'Organization sale/merger' },\r\n { value: 'other', label: 'Other' },\r\n] as const;\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT HOOK\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function useLicenseTransfer(config: TransferConfig) {\r\n const [step, setStep] = useState<TransferStep>('select-license');\r\n const [licenses, setLicenses] = useState<LicenseInfo[]>([]);\r\n const [formData, setFormData] = useState<TransferFormData>({\r\n licenseKey: '',\r\n recipientEmail: '',\r\n recipientName: '',\r\n notes: '',\r\n transferReason: 'employee_change',\r\n confirmDeactivation: false,\r\n });\r\n const [selectedLicense, setSelectedLicense] = useState<LicenseInfo | null>(null);\r\n const [recipientValidation, setRecipientValidation] = useState<{\r\n valid: boolean;\r\n isExternal: boolean;\r\n warnings?: string[];\r\n } | null>(null);\r\n const [transfer, setTransfer] = useState<TransferRequest | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n const [error, setError] = useState<TransferError | null>(null);\r\n\r\n const service = React.useMemo(() => new LicenseTransferService(config), [config]);\r\n\r\n const loadLicenses = useCallback(async () => {\r\n setLoading(true);\r\n setError(null);\r\n try {\r\n const data = await service.getTransferableLicenses();\r\n setLicenses(data);\r\n } catch (err) {\r\n setError(err as TransferError);\r\n config.onError?.(err as TransferError);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [service, config]);\r\n\r\n const selectLicense = useCallback((license: LicenseInfo) => {\r\n setSelectedLicense(license);\r\n setFormData((f) => ({ ...f, licenseKey: license.key }));\r\n setStep('enter-recipient');\r\n }, []);\r\n\r\n const validateRecipient = useCallback(async () => {\r\n if (!formData.recipientEmail) {\r\n return;\r\n }\r\n\r\n setLoading(true);\r\n try {\r\n const result = await service.validateRecipient(formData.recipientEmail);\r\n setRecipientValidation({\r\n valid: result.valid,\r\n isExternal: result.isExternal,\r\n warnings: result.warnings,\r\n });\r\n if (result.valid && result.recipientInfo) {\r\n setFormData((f) => ({\r\n ...f,\r\n recipientName: result.recipientInfo?.name || f.recipientName,\r\n }));\r\n }\r\n } catch (err) {\r\n setError(err as TransferError);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [formData.recipientEmail, service]);\r\n\r\n const proceedToReview = useCallback(() => {\r\n if (recipientValidation?.valid && formData.recipientEmail) {\r\n setStep('review');\r\n }\r\n }, [recipientValidation, formData.recipientEmail]);\r\n\r\n const initiateTransfer = useCallback(async () => {\r\n if (!formData.confirmDeactivation) {\r\n setError({ code: 'CONFIRMATION_REQUIRED', message: 'Please confirm license deactivation' });\r\n return;\r\n }\r\n\r\n setStep('processing');\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const result = await service.initiateTransfer({\r\n licenseKey: formData.licenseKey,\r\n recipientEmail: formData.recipientEmail,\r\n recipientName: formData.recipientName,\r\n notes: formData.notes,\r\n reason: formData.transferReason,\r\n });\r\n setTransfer(result);\r\n setStep('complete');\r\n config.onTransferComplete?.(result);\r\n } catch (err) {\r\n setError(err as TransferError);\r\n setStep('review');\r\n config.onError?.(err as TransferError);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [formData, service, config]);\r\n\r\n const reset = useCallback(() => {\r\n setStep('select-license');\r\n setFormData({\r\n licenseKey: '',\r\n recipientEmail: '',\r\n recipientName: '',\r\n notes: '',\r\n transferReason: 'employee_change',\r\n confirmDeactivation: false,\r\n });\r\n setSelectedLicense(null);\r\n setRecipientValidation(null);\r\n setTransfer(null);\r\n setError(null);\r\n }, []);\r\n\r\n return {\r\n step,\r\n setStep,\r\n licenses,\r\n formData,\r\n setFormData,\r\n selectedLicense,\r\n recipientValidation,\r\n transfer,\r\n loading,\r\n error,\r\n loadLicenses,\r\n selectLicense,\r\n validateRecipient,\r\n proceedToReview,\r\n initiateTransfer,\r\n reset,\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT COMPONENTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface LicenseTransferProps extends TransferConfig {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\n/** Transfer Status Badge */\r\nexport const TransferStatusBadge: React.FC<{ status: TransferStatus }> = ({ status }) => (\r\n <span\r\n className=\"inline-flex items-center px-2.5 py-1 rounded-full text-sm font-medium\"\r\n style={{\r\n backgroundColor: `${getTransferStatusColor(status)}20`,\r\n color: getTransferStatusColor(status),\r\n }}\r\n >\r\n {getTransferStatusLabel(status)}\r\n </span>\r\n);\r\n\r\n/** License Transfer Wizard */\r\nexport const LicenseTransfer: React.FC<LicenseTransferProps> = (props) => {\r\n const { className, style, ...config } = props;\r\n const {\r\n step,\r\n licenses,\r\n formData,\r\n setFormData,\r\n selectedLicense,\r\n recipientValidation,\r\n transfer,\r\n loading,\r\n error,\r\n loadLicenses,\r\n selectLicense,\r\n validateRecipient,\r\n proceedToReview,\r\n initiateTransfer,\r\n reset,\r\n setStep,\r\n } = useLicenseTransfer(config);\r\n\r\n React.useEffect(() => {\r\n loadLicenses();\r\n }, [loadLicenses]);\r\n\r\n return (\r\n <div\r\n className={`nice-license-transfer bg-white rounded-lg shadow-lg p-8 max-w-2xl mx-auto ${className || ''}`}\r\n style={style}\r\n >\r\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">Transfer License</h1>\r\n <p className=\"text-gray-600 mb-6\">Transfer a license to another user or organization</p>\r\n\r\n {/* Error Display */}\r\n {error && (\r\n <div className=\"mb-6 p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-700\">{error.message}</p>\r\n </div>\r\n )}\r\n\r\n {/* Step 1: Select License */}\r\n {step === 'select-license' && (\r\n <div className=\"space-y-4\">\r\n <h2 className=\"text-lg font-semibold\">Select a license to transfer</h2>\r\n\r\n {loading ? (\r\n <div className=\"text-center py-8\">\r\n <div className=\"animate-spin h-8 w-8 border-b-2 border-blue-500 rounded-full mx-auto\" />\r\n </div>\r\n ) : licenses.length === 0 ? (\r\n <div className=\"text-center py-8 text-gray-500\">No transferable licenses found</div>\r\n ) : (\r\n <div className=\"grid gap-4\">\r\n {licenses.map((license) => (\r\n <div\r\n key={license.key}\r\n className=\"p-4 border border-gray-200 rounded-lg hover:border-blue-500 cursor-pointer transition-colors\"\r\n onClick={() => selectLicense(license)}\r\n >\r\n <div className=\"flex justify-between items-start\">\r\n <div>\r\n <div className=\"font-mono text-sm text-gray-500\">{license.key}</div>\r\n <div className=\"font-medium mt-1\">{license.licensee}</div>\r\n </div>\r\n <span className=\"px-2 py-1 bg-blue-100 text-blue-700 rounded text-sm capitalize\">\r\n {license.tier}\r\n </span>\r\n </div>\r\n <div className=\"mt-2 text-sm text-gray-500\">\r\n {license.activeSeats}/{license.maxSeats ?? '∞'} seats used\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Step 2: Enter Recipient */}\r\n {step === 'enter-recipient' && selectedLicense && (\r\n <div className=\"space-y-6\">\r\n <div className=\"p-4 bg-gray-50 rounded-lg\">\r\n <div className=\"text-sm text-gray-500\">Transferring license:</div>\r\n <div className=\"font-mono\">{selectedLicense.key}</div>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">Recipient Email</label>\r\n <div className=\"flex gap-2\">\r\n <input\r\n type=\"email\"\r\n value={formData.recipientEmail}\r\n onChange={(e) => setFormData((f) => ({ ...f, recipientEmail: e.target.value }))}\r\n onBlur={validateRecipient}\r\n placeholder=\"recipient@company.com\"\r\n className=\"flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500\"\r\n />\r\n <button\r\n onClick={validateRecipient}\r\n disabled={!formData.recipientEmail || loading}\r\n className=\"px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 disabled:opacity-50\"\r\n >\r\n Validate\r\n </button>\r\n </div>\r\n\r\n {recipientValidation && (\r\n <div\r\n className={`mt-2 text-sm ${recipientValidation.valid ? 'text-green-600' : 'text-red-600'}`}\r\n >\r\n {recipientValidation.valid ? '✓ Valid recipient' : '✗ Invalid recipient'}\r\n {recipientValidation.isExternal && (\r\n <span className=\"ml-2 text-orange-600\">(External organization)</span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {recipientValidation?.warnings?.map((warning, i) => (\r\n <div key={i} className=\"mt-1 text-sm text-orange-600\">\r\n ⚠ {warning}\r\n </div>\r\n ))}\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">Recipient Name</label>\r\n <input\r\n type=\"text\"\r\n value={formData.recipientName}\r\n onChange={(e) => setFormData((f) => ({ ...f, recipientName: e.target.value }))}\r\n placeholder=\"John Doe\"\r\n className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">Transfer Reason</label>\r\n <select\r\n value={formData.transferReason}\r\n onChange={(e) =>\r\n setFormData((f) => ({\r\n ...f,\r\n transferReason: e.target.value as TransferFormData['transferReason'],\r\n }))\r\n }\r\n className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500\"\r\n >\r\n {TRANSFER_REASONS.map((reason) => (\r\n <option key={reason.value} value={reason.value}>\r\n {reason.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">Notes (optional)</label>\r\n <textarea\r\n value={formData.notes}\r\n onChange={(e) => setFormData((f) => ({ ...f, notes: e.target.value }))}\r\n placeholder=\"Any additional information...\"\r\n rows={3}\r\n className=\"w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500\"\r\n />\r\n </div>\r\n\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={() => setStep('select-license')}\r\n className=\"px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n >\r\n Back\r\n </button>\r\n <button\r\n onClick={proceedToReview}\r\n disabled={!recipientValidation?.valid || !formData.recipientName}\r\n className=\"flex-1 px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:bg-gray-300\"\r\n >\r\n Review Transfer\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Step 3: Review */}\r\n {step === 'review' && selectedLicense && (\r\n <div className=\"space-y-6\">\r\n <h2 className=\"text-lg font-semibold\">Review Transfer Details</h2>\r\n\r\n <div className=\"bg-gray-50 rounded-lg p-4 space-y-3\">\r\n <div className=\"grid grid-cols-2 gap-2 text-sm\">\r\n <div className=\"text-gray-500\">License Key:</div>\r\n <div className=\"font-mono\">{selectedLicense.key}</div>\r\n\r\n <div className=\"text-gray-500\">Current Licensee:</div>\r\n <div>{selectedLicense.licensee}</div>\r\n\r\n <div className=\"text-gray-500\">Tier:</div>\r\n <div className=\"capitalize\">{selectedLicense.tier}</div>\r\n\r\n <div className=\"text-gray-500\">Transfer To:</div>\r\n <div>{formData.recipientName}</div>\r\n\r\n <div className=\"text-gray-500\">Recipient Email:</div>\r\n <div>{formData.recipientEmail}</div>\r\n\r\n <div className=\"text-gray-500\">Reason:</div>\r\n <div>{TRANSFER_REASONS.find((r) => r.value === formData.transferReason)?.label}</div>\r\n </div>\r\n\r\n {formData.notes && (\r\n <div className=\"pt-3 border-t border-gray-200\">\r\n <div className=\"text-sm text-gray-500 mb-1\">Notes:</div>\r\n <div className=\"text-sm\">{formData.notes}</div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"p-4 bg-orange-50 border border-orange-200 rounded-lg\">\r\n <h3 className=\"font-semibold text-orange-800 mb-2\">⚠ Important</h3>\r\n <p className=\"text-sm text-orange-700\">\r\n Once the transfer is completed, this license will be deactivated from all your\r\n machines and the new owner will need to activate it.\r\n </p>\r\n </div>\r\n\r\n <label className=\"flex items-start gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={formData.confirmDeactivation}\r\n onChange={(e) =>\r\n setFormData((f) => ({ ...f, confirmDeactivation: e.target.checked }))\r\n }\r\n className=\"mt-1 w-4 h-4 rounded border-gray-300 text-blue-500 focus:ring-blue-500\"\r\n />\r\n <span className=\"text-sm text-gray-700\">\r\n I understand that this license will be deactivated and transferred to the recipient.\r\n This action cannot be undone without admin intervention.\r\n </span>\r\n </label>\r\n\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={() => setStep('enter-recipient')}\r\n className=\"px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n >\r\n Back\r\n </button>\r\n <button\r\n onClick={initiateTransfer}\r\n disabled={!formData.confirmDeactivation || loading}\r\n className=\"flex-1 px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:bg-gray-300\"\r\n >\r\n {loading ? 'Processing...' : 'Initiate Transfer'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Step 4: Processing */}\r\n {step === 'processing' && (\r\n <div className=\"text-center py-12\">\r\n <div className=\"animate-spin h-12 w-12 border-b-2 border-blue-500 rounded-full mx-auto\" />\r\n <h2 className=\"text-lg font-semibold mt-4\">Processing Transfer...</h2>\r\n <p className=\"text-gray-500\">Please wait while we process your transfer request</p>\r\n </div>\r\n )}\r\n\r\n {/* Step 5: Complete */}\r\n {step === 'complete' && transfer && (\r\n <div className=\"text-center space-y-6\">\r\n <div className=\"text-green-500 text-6xl\">✓</div>\r\n <div>\r\n <h2 className=\"text-xl font-bold\">Transfer Initiated</h2>\r\n <p className=\"text-gray-600 mt-2\">\r\n {transfer.approvalRequired\r\n ? 'Your transfer request has been submitted for approval.'\r\n : 'An email has been sent to the recipient with instructions to accept the transfer.'}\r\n </p>\r\n </div>\r\n\r\n <div className=\"bg-gray-50 rounded-lg p-4 text-left\">\r\n <div className=\"text-sm grid grid-cols-2 gap-2\">\r\n <div className=\"text-gray-500\">Transfer ID:</div>\r\n <div className=\"font-mono\">{transfer.id}</div>\r\n <div className=\"text-gray-500\">Status:</div>\r\n <div>\r\n <TransferStatusBadge status={transfer.status} />\r\n </div>\r\n <div className=\"text-gray-500\">Expires:</div>\r\n <div>{new Date(transfer.expiresAt).toLocaleDateString()}</div>\r\n </div>\r\n </div>\r\n\r\n <button\r\n onClick={reset}\r\n className=\"px-8 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600\"\r\n >\r\n Done\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default LicenseTransfer;\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// `any` casts in this file target untyped third-party browser globals\r\n// (Paddle.js loaded via <script>, Stripe optional peer dep) and Stripe's\r\n// loosely-typed `redirectToCheckout` callback. Real types live in the\r\n// upstream packages once the consumer installs them.\r\n/* ────────────────────────────────────────────────────────────────\r\n \r\n Integration with payment providers (Stripe, Paddle) for\r\n subscription management, one-time purchases, and invoicing.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseTier, LicenseKey, LicenseInfo } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type PaymentProvider = 'stripe' | 'paddle' | 'paypal';\r\nexport type BillingInterval = 'monthly' | 'yearly' | 'once';\r\nexport type SubscriptionStatus =\r\n | 'active'\r\n | 'past_due'\r\n | 'unpaid'\r\n | 'canceled'\r\n | 'incomplete'\r\n | 'trialing'\r\n | 'paused';\r\n\r\nexport interface BillingConfig {\r\n /** Stripe publishable key */\r\n stripePublishableKey?: string;\r\n /** Paddle vendor ID */\r\n paddleVendorId?: string;\r\n /** Paddle environment */\r\n paddleEnvironment?: 'sandbox' | 'production';\r\n /** API base URL for billing operations */\r\n apiBaseUrl: string;\r\n /** Authentication token */\r\n authToken?: string;\r\n /** Default currency */\r\n defaultCurrency?: string;\r\n /** Supported currencies */\r\n supportedCurrencies?: string[];\r\n /** Tax handling */\r\n taxHandling?: 'inclusive' | 'exclusive';\r\n /** Webhooks enabled */\r\n webhooksEnabled?: boolean;\r\n}\r\n\r\nexport interface PricingPlan {\r\n id: string;\r\n name: string;\r\n description: string;\r\n tier: LicenseTier;\r\n features: string[];\r\n /** Monthly price in cents */\r\n monthlyPrice: number;\r\n /** Yearly price in cents (with discount) */\r\n yearlyPrice: number;\r\n /** One-time price in cents (perpetual) */\r\n perpetualPrice?: number;\r\n currency: string;\r\n /** Seats included */\r\n seatsIncluded: number;\r\n /** Price per additional seat (monthly) */\r\n seatPriceMonthly?: number;\r\n /** Price per additional seat (yearly) */\r\n seatPriceYearly?: number;\r\n /** Trial days */\r\n trialDays?: number;\r\n /** Is highlighted/recommended */\r\n recommended?: boolean;\r\n /** Stripe price IDs */\r\n stripePriceIds?: {\r\n monthly?: string;\r\n yearly?: string;\r\n perpetual?: string;\r\n };\r\n /** Paddle product IDs */\r\n paddleProductIds?: {\r\n monthly?: string;\r\n yearly?: string;\r\n perpetual?: string;\r\n };\r\n}\r\n\r\nexport interface Subscription {\r\n id: string;\r\n customerId: string;\r\n status: SubscriptionStatus;\r\n plan: PricingPlan;\r\n currentPeriodStart: string;\r\n currentPeriodEnd: string;\r\n cancelAtPeriodEnd: boolean;\r\n canceledAt?: string;\r\n trialStart?: string;\r\n trialEnd?: string;\r\n seats: number;\r\n amount: number;\r\n currency: string;\r\n interval: BillingInterval;\r\n provider: PaymentProvider;\r\n providerSubscriptionId: string;\r\n licenseKeys: LicenseKey[];\r\n paymentMethod?: PaymentMethod;\r\n latestInvoice?: Invoice;\r\n}\r\n\r\nexport interface PaymentMethod {\r\n id: string;\r\n type: 'card' | 'bank_account' | 'paypal' | 'sepa_debit';\r\n brand?: string;\r\n last4: string;\r\n expiryMonth?: number;\r\n expiryYear?: number;\r\n isDefault: boolean;\r\n}\r\n\r\nexport interface Invoice {\r\n id: string;\r\n number: string;\r\n status: 'draft' | 'open' | 'paid' | 'void' | 'uncollectible';\r\n amount: number;\r\n amountPaid: number;\r\n amountDue: number;\r\n currency: string;\r\n createdAt: string;\r\n dueDate: string;\r\n paidAt?: string;\r\n periodStart: string;\r\n periodEnd: string;\r\n lineItems: InvoiceLineItem[];\r\n pdfUrl?: string;\r\n hostedUrl?: string;\r\n}\r\n\r\nexport interface InvoiceLineItem {\r\n description: string;\r\n quantity: number;\r\n unitPrice: number;\r\n amount: number;\r\n taxAmount?: number;\r\n}\r\n\r\nexport interface CheckoutSession {\r\n id: string;\r\n url: string;\r\n provider: PaymentProvider;\r\n expiresAt: string;\r\n}\r\n\r\nexport interface BillingPortalSession {\r\n id: string;\r\n url: string;\r\n provider: PaymentProvider;\r\n}\r\n\r\nexport interface ProratedAmount {\r\n dueNow: number;\r\n credit: number;\r\n newRecurring: number;\r\n effectiveDate: string;\r\n}\r\n\r\nexport interface UsageRecord {\r\n subscriptionId: string;\r\n metricId: string;\r\n quantity: number;\r\n recordedAt: string;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n BILLING SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class BillingService {\r\n private config: BillingConfig;\r\n\r\n constructor(config: BillingConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { Authorization: `Bearer ${this.config.authToken}` }),\r\n };\r\n\r\n const response = await fetch(url, { ...options, headers });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw new Error(error.message || `Request failed: ${response.status}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n PRICING & PLANS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Get all pricing plans */\r\n async getPlans(currency?: string): Promise<PricingPlan[]> {\r\n const params = currency ? `?currency=${currency}` : '';\r\n return this.request<PricingPlan[]>(`/billing/plans${params}`);\r\n }\r\n\r\n /** Get plan by ID */\r\n async getPlan(planId: string): Promise<PricingPlan> {\r\n return this.request<PricingPlan>(`/billing/plans/${planId}`);\r\n }\r\n\r\n /** Compare plans (for upgrade/downgrade) */\r\n async comparePlans(\r\n currentPlanId: string,\r\n targetPlanId: string,\r\n seats?: number,\r\n ): Promise<{\r\n currentPlan: PricingPlan;\r\n targetPlan: PricingPlan;\r\n proration: ProratedAmount;\r\n isUpgrade: boolean;\r\n }> {\r\n return this.request('/billing/plans/compare', {\r\n method: 'POST',\r\n body: JSON.stringify({ currentPlanId, targetPlanId, seats }),\r\n });\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n SUBSCRIPTIONS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Get current subscription */\r\n async getSubscription(): Promise<Subscription | null> {\r\n try {\r\n return await this.request<Subscription>('/billing/subscription');\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /** Get subscription by ID */\r\n async getSubscriptionById(subscriptionId: string): Promise<Subscription> {\r\n return this.request<Subscription>(`/billing/subscriptions/${subscriptionId}`);\r\n }\r\n\r\n /** Create checkout session for new subscription */\r\n async createCheckoutSession(options: {\r\n planId: string;\r\n interval: BillingInterval;\r\n seats?: number;\r\n successUrl: string;\r\n cancelUrl: string;\r\n provider?: PaymentProvider;\r\n couponCode?: string;\r\n metadata?: Record<string, string>;\r\n }): Promise<CheckoutSession> {\r\n const provider = options.provider || this.detectPreferredProvider();\r\n return this.request<CheckoutSession>('/billing/checkout', {\r\n method: 'POST',\r\n body: JSON.stringify({ ...options, provider }),\r\n });\r\n }\r\n\r\n /** Create billing portal session */\r\n async createPortalSession(returnUrl: string): Promise<BillingPortalSession> {\r\n return this.request<BillingPortalSession>('/billing/portal', {\r\n method: 'POST',\r\n body: JSON.stringify({ returnUrl }),\r\n });\r\n }\r\n\r\n /** Update subscription (change plan, seats) */\r\n async updateSubscription(options: {\r\n planId?: string;\r\n seats?: number;\r\n interval?: BillingInterval;\r\n prorate?: boolean;\r\n }): Promise<Subscription> {\r\n return this.request<Subscription>('/billing/subscription', {\r\n method: 'PATCH',\r\n body: JSON.stringify(options),\r\n });\r\n }\r\n\r\n /** Cancel subscription */\r\n async cancelSubscription(options?: {\r\n atPeriodEnd?: boolean;\r\n reason?: string;\r\n feedback?: string;\r\n }): Promise<Subscription> {\r\n return this.request<Subscription>('/billing/subscription/cancel', {\r\n method: 'POST',\r\n body: JSON.stringify(options || { atPeriodEnd: true }),\r\n });\r\n }\r\n\r\n /** Resume canceled subscription */\r\n async resumeSubscription(): Promise<Subscription> {\r\n return this.request<Subscription>('/billing/subscription/resume', {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /** Pause subscription (Paddle only) */\r\n async pauseSubscription(): Promise<Subscription> {\r\n return this.request<Subscription>('/billing/subscription/pause', {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n PAYMENT METHODS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Get saved payment methods */\r\n async getPaymentMethods(): Promise<PaymentMethod[]> {\r\n return this.request<PaymentMethod[]>('/billing/payment-methods');\r\n }\r\n\r\n /** Add payment method (redirect to Stripe/Paddle) */\r\n async addPaymentMethod(returnUrl: string): Promise<{ url: string }> {\r\n return this.request('/billing/payment-methods/add', {\r\n method: 'POST',\r\n body: JSON.stringify({ returnUrl }),\r\n });\r\n }\r\n\r\n /** Remove payment method */\r\n async removePaymentMethod(paymentMethodId: string): Promise<void> {\r\n await this.request(`/billing/payment-methods/${paymentMethodId}`, {\r\n method: 'DELETE',\r\n });\r\n }\r\n\r\n /** Set default payment method */\r\n async setDefaultPaymentMethod(paymentMethodId: string): Promise<void> {\r\n await this.request(`/billing/payment-methods/${paymentMethodId}/default`, {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n INVOICES\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Get invoices */\r\n async getInvoices(options?: {\r\n limit?: number;\r\n offset?: number;\r\n status?: Invoice['status'];\r\n }): Promise<{ invoices: Invoice[]; total: number }> {\r\n const params = new URLSearchParams();\r\n if (options?.limit) {\r\n params.set('limit', String(options.limit));\r\n }\r\n if (options?.offset) {\r\n params.set('offset', String(options.offset));\r\n }\r\n if (options?.status) {\r\n params.set('status', options.status);\r\n }\r\n return this.request(`/billing/invoices?${params}`);\r\n }\r\n\r\n /** Get upcoming invoice preview */\r\n async getUpcomingInvoice(): Promise<Invoice | null> {\r\n try {\r\n return await this.request<Invoice>('/billing/invoices/upcoming');\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /** Download invoice PDF */\r\n async downloadInvoice(invoiceId: string): Promise<Blob> {\r\n const response = await fetch(`${this.config.apiBaseUrl}/billing/invoices/${invoiceId}/pdf`, {\r\n headers: {\r\n Authorization: this.config.authToken ? `Bearer ${this.config.authToken}` : '',\r\n },\r\n });\r\n return response.blob();\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n COUPONS & PROMOTIONS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Validate coupon code */\r\n async validateCoupon(\r\n code: string,\r\n planId?: string,\r\n ): Promise<{\r\n valid: boolean;\r\n coupon?: {\r\n id: string;\r\n code: string;\r\n percentOff?: number;\r\n amountOff?: number;\r\n duration: 'once' | 'forever' | 'repeating';\r\n durationInMonths?: number;\r\n applicablePlans?: string[];\r\n };\r\n error?: string;\r\n }> {\r\n return this.request('/billing/coupons/validate', {\r\n method: 'POST',\r\n body: JSON.stringify({ code, planId }),\r\n });\r\n }\r\n\r\n /** Apply coupon to subscription */\r\n async applyCoupon(code: string): Promise<Subscription> {\r\n return this.request<Subscription>('/billing/subscription/coupon', {\r\n method: 'POST',\r\n body: JSON.stringify({ code }),\r\n });\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n USAGE-BASED BILLING\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Report usage */\r\n async reportUsage(records: UsageRecord[]): Promise<void> {\r\n await this.request('/billing/usage', {\r\n method: 'POST',\r\n body: JSON.stringify({ records }),\r\n });\r\n }\r\n\r\n /** Get usage summary */\r\n async getUsageSummary(\r\n startDate: string,\r\n endDate: string,\r\n ): Promise<{\r\n metrics: {\r\n id: string;\r\n name: string;\r\n usage: number;\r\n limit?: number;\r\n cost: number;\r\n }[];\r\n totalCost: number;\r\n }> {\r\n return this.request(`/billing/usage/summary?start=${startDate}&end=${endDate}`);\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n UTILITIES\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n private detectPreferredProvider(): PaymentProvider {\r\n if (this.config.stripePublishableKey) {\r\n return 'stripe';\r\n }\r\n if (this.config.paddleVendorId) {\r\n return 'paddle';\r\n }\r\n return 'stripe';\r\n }\r\n\r\n /** Format price for display */\r\n formatPrice(amount: number, currency: string = 'USD'): string {\r\n return new Intl.NumberFormat('en-US', {\r\n style: 'currency',\r\n currency,\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 2,\r\n }).format(amount / 100);\r\n }\r\n\r\n /** Calculate savings for yearly billing */\r\n calculateYearlySavings(plan: PricingPlan): {\r\n monthlyTotal: number;\r\n yearlyTotal: number;\r\n savings: number;\r\n savingsPercent: number;\r\n } {\r\n const monthlyTotal = plan.monthlyPrice * 12;\r\n const yearlyTotal = plan.yearlyPrice;\r\n const savings = monthlyTotal - yearlyTotal;\r\n const savingsPercent = Math.round((savings / monthlyTotal) * 100);\r\n return { monthlyTotal, yearlyTotal, savings, savingsPercent };\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n STRIPE INTEGRATION HELPERS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface StripeConfig {\r\n publishableKey: string;\r\n locale?: string;\r\n}\r\n\r\nexport async function initStripe(config: StripeConfig): Promise<unknown> {\r\n if (typeof window === 'undefined') {\r\n return null;\r\n }\r\n\r\n // Dynamically import Stripe.js\r\n const { loadStripe } = await import('@stripe/stripe-js');\r\n return loadStripe(config.publishableKey, {\r\n locale: config.locale as any,\r\n });\r\n}\r\n\r\nexport function createStripeCheckout(\r\n stripe: unknown,\r\n sessionId: string,\r\n): Promise<{ error?: { message: string } }> {\r\n return (stripe as any).redirectToCheckout({ sessionId });\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n PADDLE INTEGRATION HELPERS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface PaddleConfig {\r\n vendorId: string;\r\n environment: 'sandbox' | 'production';\r\n}\r\n\r\nexport function initPaddle(config: PaddleConfig): void {\r\n if (typeof window === 'undefined') {\r\n return;\r\n }\r\n\r\n // Paddle.js initialization\r\n const Paddle = (window as any).Paddle;\r\n if (Paddle) {\r\n Paddle.Environment.set(config.environment);\r\n Paddle.Setup({ vendor: parseInt(config.vendorId, 10) });\r\n }\r\n}\r\n\r\nexport function openPaddleCheckout(options: {\r\n product: string;\r\n email?: string;\r\n successCallback?: (data: any) => void;\r\n closeCallback?: () => void;\r\n}): void {\r\n const Paddle = (window as any).Paddle;\r\n if (Paddle) {\r\n Paddle.Checkout.open(options);\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n EXPORTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function createBillingService(config: BillingConfig): BillingService {\r\n return new BillingService(config);\r\n}\r\n","/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — Usage Analytics Dashboard\r\n \r\n Analytics dashboard for tracking license usage, feature adoption,\r\n user engagement, and business metrics.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport React, { useState, useEffect, useCallback, useMemo } from 'react';\r\n\r\nimport type { LicenseTier, FeatureId } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type TimeRange = '24h' | '7d' | '30d' | '90d' | '1y' | 'all';\r\nexport type MetricGranularity = 'hour' | 'day' | 'week' | 'month';\r\n\r\nexport interface AnalyticsConfig {\r\n apiBaseUrl: string;\r\n authToken?: string;\r\n /** Organization/customer ID */\r\n organizationId?: string;\r\n /** Refresh interval in ms (0 = no auto-refresh) */\r\n refreshInterval?: number;\r\n /** Enable real-time updates */\r\n realtime?: boolean;\r\n /** Default time range */\r\n defaultTimeRange?: TimeRange;\r\n /** Features to track */\r\n trackedFeatures?: FeatureId[];\r\n}\r\n\r\nexport interface OverviewMetrics {\r\n /** Total active licenses */\r\n activeLicenses: number;\r\n activeLicensesChange: number;\r\n /** Total active users */\r\n activeUsers: number;\r\n activeUsersChange: number;\r\n /** Total feature uses */\r\n featureUses: number;\r\n featureUsesChange: number;\r\n /** Average session duration (minutes) */\r\n avgSessionDuration: number;\r\n avgSessionDurationChange: number;\r\n /** License utilization rate */\r\n utilizationRate: number;\r\n utilizationRateChange: number;\r\n}\r\n\r\nexport interface TimeSeriesDataPoint {\r\n timestamp: string;\r\n value: number;\r\n label?: string;\r\n}\r\n\r\nexport interface FeatureUsageData {\r\n featureId: FeatureId;\r\n featureName: string;\r\n category?: string;\r\n totalUses: number;\r\n uniqueUsers: number;\r\n avgUsesPerUser: number;\r\n trend: number;\r\n history: TimeSeriesDataPoint[];\r\n}\r\n\r\nexport interface UserActivityData {\r\n userId: string;\r\n email: string;\r\n displayName?: string;\r\n licenseKey: string;\r\n tier: LicenseTier;\r\n lastActive: string;\r\n sessionCount: number;\r\n totalDuration: number;\r\n featuresUsed: number;\r\n topFeatures: { featureId: string; uses: number }[];\r\n}\r\n\r\nexport interface LicenseUtilizationData {\r\n licenseKey: string;\r\n tier: LicenseTier;\r\n licensee: string;\r\n totalSeats: number;\r\n usedSeats: number;\r\n utilizationPercent: number;\r\n lastActivity: string;\r\n activeUsersLast30d: number;\r\n}\r\n\r\nexport interface GeographicData {\r\n country: string;\r\n countryCode: string;\r\n users: number;\r\n sessions: number;\r\n avgDuration: number;\r\n}\r\n\r\nexport interface TrendData {\r\n metric: string;\r\n current: number;\r\n previous: number;\r\n change: number;\r\n changePercent: number;\r\n trend: 'up' | 'down' | 'stable';\r\n}\r\n\r\nexport interface CohortData {\r\n cohort: string;\r\n retained: number[];\r\n total: number;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n ANALYTICS SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class UsageAnalyticsService {\r\n private config: AnalyticsConfig;\r\n\r\n constructor(config: AnalyticsConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { Authorization: `Bearer ${this.config.authToken}` }),\r\n };\r\n\r\n const response = await fetch(url, { ...options, headers });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw new Error(error.message || `Request failed: ${response.status}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n private getTimeParams(range: TimeRange, granularity?: MetricGranularity): string {\r\n const params = new URLSearchParams({ range });\r\n if (granularity) {\r\n params.set('granularity', granularity);\r\n }\r\n if (this.config.organizationId) {\r\n params.set('org', this.config.organizationId);\r\n }\r\n return params.toString();\r\n }\r\n\r\n /** Get overview metrics */\r\n async getOverview(range: TimeRange = '30d'): Promise<OverviewMetrics> {\r\n return this.request<OverviewMetrics>(`/analytics/overview?${this.getTimeParams(range)}`);\r\n }\r\n\r\n /** Get license activity over time */\r\n async getLicenseActivity(\r\n range: TimeRange = '30d',\r\n granularity: MetricGranularity = 'day',\r\n ): Promise<TimeSeriesDataPoint[]> {\r\n return this.request<TimeSeriesDataPoint[]>(\r\n `/analytics/licenses/activity?${this.getTimeParams(range, granularity)}`,\r\n );\r\n }\r\n\r\n /** Get user activity over time */\r\n async getUserActivity(\r\n range: TimeRange = '30d',\r\n granularity: MetricGranularity = 'day',\r\n ): Promise<TimeSeriesDataPoint[]> {\r\n return this.request<TimeSeriesDataPoint[]>(\r\n `/analytics/users/activity?${this.getTimeParams(range, granularity)}`,\r\n );\r\n }\r\n\r\n /** Get feature usage data */\r\n async getFeatureUsage(\r\n range: TimeRange = '30d',\r\n features?: FeatureId[],\r\n ): Promise<FeatureUsageData[]> {\r\n const params = this.getTimeParams(range);\r\n const featuresParam = features ? `&features=${features.join(',')}` : '';\r\n return this.request<FeatureUsageData[]>(`/analytics/features?${params}${featuresParam}`);\r\n }\r\n\r\n /** Get top users by activity */\r\n async getTopUsers(range: TimeRange = '30d', limit = 20): Promise<UserActivityData[]> {\r\n return this.request<UserActivityData[]>(\r\n `/analytics/users/top?${this.getTimeParams(range)}&limit=${limit}`,\r\n );\r\n }\r\n\r\n /** Get license utilization */\r\n async getLicenseUtilization(): Promise<LicenseUtilizationData[]> {\r\n const params = this.config.organizationId ? `?org=${this.config.organizationId}` : '';\r\n return this.request<LicenseUtilizationData[]>(`/analytics/licenses/utilization${params}`);\r\n }\r\n\r\n /** Get geographic distribution */\r\n async getGeographicData(range: TimeRange = '30d'): Promise<GeographicData[]> {\r\n return this.request<GeographicData[]>(`/analytics/geo?${this.getTimeParams(range)}`);\r\n }\r\n\r\n /** Get trends for key metrics */\r\n async getTrends(range: TimeRange = '30d'): Promise<TrendData[]> {\r\n return this.request<TrendData[]>(`/analytics/trends?${this.getTimeParams(range)}`);\r\n }\r\n\r\n /** Get retention cohorts */\r\n async getRetentionCohorts(months = 6): Promise<CohortData[]> {\r\n const params = this.config.organizationId\r\n ? `?org=${this.config.organizationId}&months=${months}`\r\n : `?months=${months}`;\r\n return this.request<CohortData[]>(`/analytics/retention${params}`);\r\n }\r\n\r\n /** Export analytics data */\r\n async exportData(range: TimeRange, format: 'csv' | 'json' | 'xlsx'): Promise<Blob> {\r\n const response = await fetch(\r\n `${this.config.apiBaseUrl}/analytics/export?${this.getTimeParams(range)}&format=${format}`,\r\n {\r\n headers: {\r\n Authorization: this.config.authToken ? `Bearer ${this.config.authToken}` : '',\r\n },\r\n },\r\n );\r\n return response.blob();\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT HOOK\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface AnalyticsState {\r\n loading: boolean;\r\n error: string | null;\r\n timeRange: TimeRange;\r\n overview: OverviewMetrics | null;\r\n licenseActivity: TimeSeriesDataPoint[];\r\n userActivity: TimeSeriesDataPoint[];\r\n featureUsage: FeatureUsageData[];\r\n topUsers: UserActivityData[];\r\n licenseUtilization: LicenseUtilizationData[];\r\n geoData: GeographicData[];\r\n trends: TrendData[];\r\n retentionCohorts: CohortData[];\r\n}\r\n\r\nexport function useUsageAnalytics(config: AnalyticsConfig) {\r\n const [state, setState] = useState<AnalyticsState>({\r\n loading: true,\r\n error: null,\r\n timeRange: config.defaultTimeRange || '30d',\r\n overview: null,\r\n licenseActivity: [],\r\n userActivity: [],\r\n featureUsage: [],\r\n topUsers: [],\r\n licenseUtilization: [],\r\n geoData: [],\r\n trends: [],\r\n retentionCohorts: [],\r\n });\r\n\r\n const service = useMemo(() => new UsageAnalyticsService(config), [config]);\r\n\r\n const loadData = useCallback(\r\n async (range: TimeRange = state.timeRange) => {\r\n setState((s) => ({ ...s, loading: true, error: null, timeRange: range }));\r\n\r\n try {\r\n const [\r\n overview,\r\n licenseActivity,\r\n userActivity,\r\n featureUsage,\r\n topUsers,\r\n licenseUtilization,\r\n geoData,\r\n trends,\r\n retentionCohorts,\r\n ] = await Promise.all([\r\n service.getOverview(range),\r\n service.getLicenseActivity(range),\r\n service.getUserActivity(range),\r\n service.getFeatureUsage(range),\r\n service.getTopUsers(range),\r\n service.getLicenseUtilization(),\r\n service.getGeographicData(range),\r\n service.getTrends(range),\r\n service.getRetentionCohorts(),\r\n ]);\r\n\r\n setState((s) => ({\r\n ...s,\r\n loading: false,\r\n overview,\r\n licenseActivity,\r\n userActivity,\r\n featureUsage,\r\n topUsers,\r\n licenseUtilization,\r\n geoData,\r\n trends,\r\n retentionCohorts,\r\n }));\r\n } catch (error) {\r\n setState((s) => ({\r\n ...s,\r\n loading: false,\r\n error: (error as Error).message,\r\n }));\r\n }\r\n },\r\n [service, state.timeRange],\r\n );\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (config.refreshInterval && config.refreshInterval > 0) {\r\n const interval = setInterval(() => loadData(), config.refreshInterval);\r\n return () => clearInterval(interval);\r\n }\r\n }, [config.refreshInterval, loadData]);\r\n\r\n const setTimeRange = useCallback(\r\n (range: TimeRange) => {\r\n loadData(range);\r\n },\r\n [loadData],\r\n );\r\n\r\n const exportData = useCallback(\r\n async (format: 'csv' | 'json' | 'xlsx') => {\r\n const blob = await service.exportData(state.timeRange, format);\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = `analytics-${state.timeRange}.${format}`;\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n },\r\n [service, state.timeRange],\r\n );\r\n\r\n return {\r\n state,\r\n setTimeRange,\r\n refresh: loadData,\r\n exportData,\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REACT COMPONENTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface UsageAnalyticsDashboardProps extends AnalyticsConfig {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\n/** Metric Card Component */\r\nconst MetricCard: React.FC<{\r\n title: string;\r\n value: string | number;\r\n change?: number;\r\n suffix?: string;\r\n loading?: boolean;\r\n}> = ({ title, value, change, suffix, loading }) => (\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-4\">\r\n <div className=\"text-sm text-gray-500 mb-1\">{title}</div>\r\n {loading ? (\r\n <div className=\"h-8 bg-gray-100 rounded animate-pulse\" />\r\n ) : (\r\n <>\r\n <div className=\"text-2xl font-bold\">\r\n {typeof value === 'number' ? value.toLocaleString() : value}\r\n {suffix && <span className=\"text-sm font-normal text-gray-500 ml-1\">{suffix}</span>}\r\n </div>\r\n {change !== undefined && (\r\n <div className={`text-sm mt-1 ${change >= 0 ? 'text-green-600' : 'text-red-600'}`}>\r\n {change >= 0 ? '↑' : '↓'} {Math.abs(change).toFixed(1)}%\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n);\r\n\r\n/** Time Range Selector */\r\nconst TimeRangeSelector: React.FC<{\r\n value: TimeRange;\r\n onChange: (range: TimeRange) => void;\r\n}> = ({ value, onChange }) => {\r\n const options: { value: TimeRange; label: string }[] = [\r\n { value: '24h', label: '24 Hours' },\r\n { value: '7d', label: '7 Days' },\r\n { value: '30d', label: '30 Days' },\r\n { value: '90d', label: '90 Days' },\r\n { value: '1y', label: '1 Year' },\r\n { value: 'all', label: 'All Time' },\r\n ];\r\n\r\n return (\r\n <div className=\"flex gap-1 bg-gray-100 rounded-lg p-1\">\r\n {options.map((opt) => (\r\n <button\r\n key={opt.value}\r\n onClick={() => onChange(opt.value)}\r\n className={`px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${\r\n value === opt.value\r\n ? 'bg-white text-gray-900 shadow-sm'\r\n : 'text-gray-600 hover:text-gray-900'\r\n }`}\r\n >\r\n {opt.label}\r\n </button>\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\n/** Feature Usage Table */\r\nconst FeatureUsageTable: React.FC<{\r\n data: FeatureUsageData[];\r\n loading?: boolean;\r\n}> = ({ data, loading }) => (\r\n <div className=\"bg-white rounded-lg border border-gray-200 overflow-hidden\">\r\n <div className=\"p-4 border-b border-gray-200\">\r\n <h3 className=\"font-semibold\">Feature Usage</h3>\r\n </div>\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-gray-50\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">\r\n Feature\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Total Uses\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Users\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Avg/User\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Trend\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-gray-100\">\r\n {loading ? (\r\n <tr>\r\n <td colSpan={5} className=\"px-4 py-8 text-center text-gray-500\">\r\n Loading...\r\n </td>\r\n </tr>\r\n ) : data.length === 0 ? (\r\n <tr>\r\n <td colSpan={5} className=\"px-4 py-8 text-center text-gray-500\">\r\n No data available\r\n </td>\r\n </tr>\r\n ) : (\r\n data.map((feature) => (\r\n <tr key={feature.featureId} className=\"hover:bg-gray-50\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"font-medium\">{feature.featureName}</div>\r\n {feature.category && (\r\n <div className=\"text-xs text-gray-500\">{feature.category}</div>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">\r\n {feature.totalUses.toLocaleString()}\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">\r\n {feature.uniqueUsers.toLocaleString()}\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">\r\n {feature.avgUsesPerUser.toFixed(1)}\r\n </td>\r\n <td className=\"px-4 py-3 text-right\">\r\n <span\r\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\r\n feature.trend > 0\r\n ? 'bg-green-100 text-green-800'\r\n : feature.trend < 0\r\n ? 'bg-red-100 text-red-800'\r\n : 'bg-gray-100 text-gray-800'\r\n }`}\r\n >\r\n {feature.trend > 0 ? '+' : ''}\r\n {feature.trend.toFixed(1)}%\r\n </span>\r\n </td>\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n);\r\n\r\n/** Top Users Table */\r\nconst TopUsersTable: React.FC<{\r\n data: UserActivityData[];\r\n loading?: boolean;\r\n}> = ({ data, loading }) => (\r\n <div className=\"bg-white rounded-lg border border-gray-200 overflow-hidden\">\r\n <div className=\"p-4 border-b border-gray-200\">\r\n <h3 className=\"font-semibold\">Top Active Users</h3>\r\n </div>\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-gray-50\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">\r\n User\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Sessions\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Duration\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase\">\r\n Features\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">\r\n Last Active\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-gray-100\">\r\n {loading ? (\r\n <tr>\r\n <td colSpan={5} className=\"px-4 py-8 text-center text-gray-500\">\r\n Loading...\r\n </td>\r\n </tr>\r\n ) : (\r\n data.map((user) => (\r\n <tr key={user.userId} className=\"hover:bg-gray-50\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"font-medium\">{user.displayName || user.email}</div>\r\n <div className=\"text-xs text-gray-500 capitalize\">{user.tier}</div>\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">\r\n {user.sessionCount.toLocaleString()}\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">\r\n {Math.round(user.totalDuration / 60)}h\r\n </td>\r\n <td className=\"px-4 py-3 text-right font-mono\">{user.featuresUsed}</td>\r\n <td className=\"px-4 py-3 text-sm text-gray-500\">\r\n {new Date(user.lastActive).toLocaleDateString()}\r\n </td>\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n);\r\n\r\n/** License Utilization Chart */\r\nconst LicenseUtilizationChart: React.FC<{\r\n data: LicenseUtilizationData[];\r\n loading?: boolean;\r\n}> = ({ data, loading }) => (\r\n <div className=\"bg-white rounded-lg border border-gray-200\">\r\n <div className=\"p-4 border-b border-gray-200\">\r\n <h3 className=\"font-semibold\">License Utilization</h3>\r\n </div>\r\n <div className=\"p-4 space-y-4\">\r\n {loading ? (\r\n <div className=\"text-center text-gray-500\">Loading...</div>\r\n ) : data.length === 0 ? (\r\n <div className=\"text-center text-gray-500\">No licenses</div>\r\n ) : (\r\n data.map((license) => (\r\n <div key={license.licenseKey}>\r\n <div className=\"flex justify-between text-sm mb-1\">\r\n <span className=\"font-medium truncate max-w-[200px]\">{license.licensee}</span>\r\n <span className=\"text-gray-500\">\r\n {license.usedSeats}/{license.totalSeats} seats\r\n </span>\r\n </div>\r\n <div className=\"h-2 bg-gray-100 rounded-full overflow-hidden\">\r\n <div\r\n className={`h-full rounded-full ${\r\n license.utilizationPercent >= 90\r\n ? 'bg-red-500'\r\n : license.utilizationPercent >= 70\r\n ? 'bg-yellow-500'\r\n : 'bg-green-500'\r\n }`}\r\n style={{ width: `${license.utilizationPercent}%` }}\r\n />\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n);\r\n\r\n/** Main Dashboard Component */\r\nexport const UsageAnalyticsDashboard: React.FC<UsageAnalyticsDashboardProps> = (props) => {\r\n const { className, style, ...config } = props;\r\n const { state, setTimeRange, refresh, exportData } = useUsageAnalytics(config);\r\n\r\n return (\r\n <div className={`nice-usage-analytics ${className || ''}`} style={style}>\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-gray-900\">Usage Analytics</h1>\r\n <p className=\"text-gray-600\">Monitor license usage and feature adoption</p>\r\n </div>\r\n <div className=\"flex items-center gap-4\">\r\n <TimeRangeSelector value={state.timeRange} onChange={setTimeRange} />\r\n <button\r\n onClick={() => refresh()}\r\n className=\"p-2 text-gray-500 hover:text-gray-700 rounded-lg hover:bg-gray-100\"\r\n title=\"Refresh\"\r\n >\r\n ↻\r\n </button>\r\n <div className=\"relative\">\r\n <button\r\n className=\"px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300\"\r\n onClick={() => exportData('csv')}\r\n >\r\n Export\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Error State */}\r\n {state.error && (\r\n <div className=\"mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700\">\r\n {state.error}\r\n </div>\r\n )}\r\n\r\n {/* Overview Metrics */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4 mb-6\">\r\n <MetricCard\r\n title=\"Active Licenses\"\r\n value={state.overview?.activeLicenses ?? 0}\r\n change={state.overview?.activeLicensesChange}\r\n loading={state.loading}\r\n />\r\n <MetricCard\r\n title=\"Active Users\"\r\n value={state.overview?.activeUsers ?? 0}\r\n change={state.overview?.activeUsersChange}\r\n loading={state.loading}\r\n />\r\n <MetricCard\r\n title=\"Feature Uses\"\r\n value={state.overview?.featureUses ?? 0}\r\n change={state.overview?.featureUsesChange}\r\n loading={state.loading}\r\n />\r\n <MetricCard\r\n title=\"Avg Session\"\r\n value={state.overview?.avgSessionDuration?.toFixed(1) ?? '0'}\r\n suffix=\"min\"\r\n change={state.overview?.avgSessionDurationChange}\r\n loading={state.loading}\r\n />\r\n <MetricCard\r\n title=\"Utilization\"\r\n value={`${state.overview?.utilizationRate?.toFixed(0) ?? 0}%`}\r\n change={state.overview?.utilizationRateChange}\r\n loading={state.loading}\r\n />\r\n </div>\r\n\r\n {/* Charts Grid */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6\">\r\n <div className=\"lg:col-span-2\">\r\n <FeatureUsageTable data={state.featureUsage} loading={state.loading} />\r\n </div>\r\n <div>\r\n <LicenseUtilizationChart data={state.licenseUtilization} loading={state.loading} />\r\n </div>\r\n </div>\r\n\r\n {/* Top Users */}\r\n <div className=\"mb-6\">\r\n <TopUsersTable data={state.topUsers} loading={state.loading} />\r\n </div>\r\n\r\n {/* Geographic Distribution */}\r\n {state.geoData.length > 0 && (\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-4\">\r\n <h3 className=\"font-semibold mb-4\">Geographic Distribution</h3>\r\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4\">\r\n {state.geoData.slice(0, 6).map((geo) => (\r\n <div key={geo.countryCode} className=\"text-center\">\r\n <div className=\"text-2xl mb-1\">{getCountryFlag(geo.countryCode)}</div>\r\n <div className=\"text-sm font-medium\">{geo.country}</div>\r\n <div className=\"text-xs text-gray-500\">{geo.users} users</div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nfunction getCountryFlag(countryCode: string): string {\r\n const codePoints = countryCode\r\n .toUpperCase()\r\n .split('')\r\n .map((char) => 127397 + char.charCodeAt(0));\r\n return String.fromCodePoint(...codePoints);\r\n}\r\n\r\nexport default UsageAnalyticsDashboard;\r\n","/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — Refund & Revocation System\r\n \r\n System for handling license refunds, revocations, and\r\n subscription cancellations with audit trail.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport type { LicenseKey, LicenseInfo, LicenseTier } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type RefundReason =\r\n | 'product_not_as_described'\r\n | 'technical_issues'\r\n | 'accidental_purchase'\r\n | 'no_longer_needed'\r\n | 'found_alternative'\r\n | 'pricing_concerns'\r\n | 'customer_service'\r\n | 'other';\r\n\r\nexport type RefundStatus =\r\n | 'pending'\r\n | 'approved'\r\n | 'rejected'\r\n | 'processing'\r\n | 'completed'\r\n | 'failed'\r\n | 'cancelled';\r\n\r\nexport type RevocationReason =\r\n | 'refund'\r\n | 'chargeback'\r\n | 'fraud'\r\n | 'violation'\r\n | 'breach_of_terms'\r\n | 'payment_failure'\r\n | 'admin_action'\r\n | 'license_transfer';\r\n\r\nexport interface RefundRequest {\r\n id: string;\r\n customerId: string;\r\n customerEmail: string;\r\n customerName: string;\r\n licenseKey: LicenseKey;\r\n license: LicenseInfo;\r\n orderId: string;\r\n invoiceId?: string;\r\n amount: number;\r\n currency: string;\r\n reason: RefundReason;\r\n reasonDetails?: string;\r\n status: RefundStatus;\r\n createdAt: string;\r\n updatedAt: string;\r\n processedAt?: string;\r\n processedBy?: string;\r\n refundMethod: 'original_payment' | 'store_credit' | 'manual';\r\n refundTransactionId?: string;\r\n rejectionReason?: string;\r\n notes?: string;\r\n attachments?: RefundAttachment[];\r\n autoApproved: boolean;\r\n withinRefundPeriod: boolean;\r\n daysFromPurchase: number;\r\n}\r\n\r\nexport interface RefundAttachment {\r\n id: string;\r\n filename: string;\r\n mimeType: string;\r\n size: number;\r\n uploadedAt: string;\r\n url: string;\r\n}\r\n\r\nexport interface RevocationRecord {\r\n id: string;\r\n licenseKey: LicenseKey;\r\n license: LicenseInfo;\r\n reason: RevocationReason;\r\n reasonDetails?: string;\r\n revokedAt: string;\r\n revokedBy: string;\r\n refundRequestId?: string;\r\n permanent: boolean;\r\n reactivatable: boolean;\r\n previousStatus: string;\r\n affectedSeats: number;\r\n affectedMachines: string[];\r\n notificationsSent: boolean;\r\n}\r\n\r\nexport interface RefundPolicy {\r\n /** Days after purchase when refund is allowed */\r\n refundPeriodDays: number;\r\n /** Tiers eligible for automatic refund */\r\n autoApprovalTiers: LicenseTier[];\r\n /** Max amount for auto-approval */\r\n autoApprovalMaxAmount: number;\r\n /** Max refunds per customer per year */\r\n maxRefundsPerYear: number;\r\n /** Requires reason to be provided */\r\n requireReason: boolean;\r\n /** Requires detailed explanation */\r\n requireDetails: boolean;\r\n /** Percentage refund after usage (0-100) */\r\n usageBasedRefundPercent?: number;\r\n /** Days where full refund applies */\r\n fullRefundDays: number;\r\n /** Partial refund after full refund period */\r\n partialRefundPercent?: number;\r\n /** Excluded tiers from refund */\r\n excludedTiers?: LicenseTier[];\r\n /** Custom rules per tier */\r\n tierRules?: Record<LicenseTier, { refundPeriodDays: number; maxRefundPercent: number }>;\r\n}\r\n\r\nexport interface RefundConfig {\r\n apiBaseUrl: string;\r\n authToken?: string;\r\n policy: RefundPolicy;\r\n /** Notification configuration */\r\n notifications?: {\r\n customerEmail: boolean;\r\n adminEmail: boolean;\r\n slackWebhook?: string;\r\n };\r\n /** Callback when refund is processed */\r\n onRefundProcessed?: (request: RefundRequest) => void;\r\n /** Callback when license is revoked */\r\n onLicenseRevoked?: (record: RevocationRecord) => void;\r\n}\r\n\r\nexport interface RefundEligibility {\r\n eligible: boolean;\r\n reason?: string;\r\n maxRefundAmount: number;\r\n refundPercent: number;\r\n withinPeriod: boolean;\r\n daysRemaining: number;\r\n previousRefunds: number;\r\n requiresApproval: boolean;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n REFUND SERVICE\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class RefundService {\r\n private config: RefundConfig;\r\n\r\n constructor(config: RefundConfig) {\r\n this.config = config;\r\n }\r\n\r\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\r\n const url = `${this.config.apiBaseUrl}${endpoint}`;\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { Authorization: `Bearer ${this.config.authToken}` }),\r\n };\r\n\r\n const response = await fetch(url, { ...options, headers });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({}));\r\n throw new Error(error.message || `Request failed: ${response.status}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n REFUND ELIGIBILITY\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Check if license is eligible for refund */\r\n async checkEligibility(licenseKey: LicenseKey): Promise<RefundEligibility> {\r\n return this.request<RefundEligibility>(\r\n `/refunds/eligibility/${encodeURIComponent(licenseKey)}`,\r\n );\r\n }\r\n\r\n /** Calculate refund amount */\r\n calculateRefundAmount(\r\n originalAmount: number,\r\n daysSincePurchase: number,\r\n ): { amount: number; percent: number } {\r\n const policy = this.config.policy;\r\n\r\n // Not eligible if outside refund period\r\n if (daysSincePurchase > policy.refundPeriodDays) {\r\n return { amount: 0, percent: 0 };\r\n }\r\n\r\n // Full refund within full refund period\r\n if (daysSincePurchase <= policy.fullRefundDays) {\r\n return { amount: originalAmount, percent: 100 };\r\n }\r\n\r\n // Partial refund if configured\r\n if (policy.partialRefundPercent) {\r\n const amount = Math.round(originalAmount * (policy.partialRefundPercent / 100));\r\n return { amount, percent: policy.partialRefundPercent };\r\n }\r\n\r\n // Usage-based prorated refund\r\n if (policy.usageBasedRefundPercent !== undefined) {\r\n const usedDays = daysSincePurchase - policy.fullRefundDays;\r\n const remainingDays = policy.refundPeriodDays - policy.fullRefundDays;\r\n const usagePercent = Math.min(100, (usedDays / remainingDays) * 100);\r\n const refundPercent = Math.max(0, policy.usageBasedRefundPercent - usagePercent);\r\n const amount = Math.round(originalAmount * (refundPercent / 100));\r\n return { amount, percent: refundPercent };\r\n }\r\n\r\n return { amount: originalAmount, percent: 100 };\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n REFUND REQUESTS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Create refund request */\r\n async createRefundRequest(data: {\r\n licenseKey: LicenseKey;\r\n reason: RefundReason;\r\n reasonDetails?: string;\r\n preferredMethod?: RefundRequest['refundMethod'];\r\n }): Promise<RefundRequest> {\r\n return this.request<RefundRequest>('/refunds', {\r\n method: 'POST',\r\n body: JSON.stringify(data),\r\n });\r\n }\r\n\r\n /** Get refund request by ID */\r\n async getRefundRequest(requestId: string): Promise<RefundRequest> {\r\n return this.request<RefundRequest>(`/refunds/${requestId}`);\r\n }\r\n\r\n /** Get refund requests for customer */\r\n async getCustomerRefundRequests(customerId?: string): Promise<RefundRequest[]> {\r\n const endpoint = customerId ? `/refunds?customerId=${customerId}` : '/refunds';\r\n return this.request<RefundRequest[]>(endpoint);\r\n }\r\n\r\n /** Get pending refund requests (admin) */\r\n async getPendingRequests(\r\n limit = 50,\r\n offset = 0,\r\n ): Promise<{ requests: RefundRequest[]; total: number }> {\r\n return this.request(`/refunds/pending?limit=${limit}&offset=${offset}`);\r\n }\r\n\r\n /** Cancel refund request (customer) */\r\n async cancelRefundRequest(requestId: string): Promise<RefundRequest> {\r\n return this.request<RefundRequest>(`/refunds/${requestId}/cancel`, {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /** Add attachment to refund request */\r\n async addAttachment(requestId: string, file: File): Promise<RefundAttachment> {\r\n const formData = new FormData();\r\n formData.append('file', file);\r\n\r\n const response = await fetch(`${this.config.apiBaseUrl}/refunds/${requestId}/attachments`, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: this.config.authToken ? `Bearer ${this.config.authToken}` : '',\r\n },\r\n body: formData,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to upload attachment');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n ADMIN OPERATIONS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Approve refund request (admin) */\r\n async approveRefund(\r\n requestId: string,\r\n options?: {\r\n adjustedAmount?: number;\r\n notes?: string;\r\n refundMethod?: RefundRequest['refundMethod'];\r\n },\r\n ): Promise<RefundRequest> {\r\n return this.request<RefundRequest>(`/refunds/${requestId}/approve`, {\r\n method: 'POST',\r\n body: JSON.stringify(options || {}),\r\n });\r\n }\r\n\r\n /** Reject refund request (admin) */\r\n async rejectRefund(requestId: string, reason: string): Promise<RefundRequest> {\r\n return this.request<RefundRequest>(`/refunds/${requestId}/reject`, {\r\n method: 'POST',\r\n body: JSON.stringify({ reason }),\r\n });\r\n }\r\n\r\n /** Process refund (trigger payment refund) */\r\n async processRefund(requestId: string): Promise<RefundRequest> {\r\n const result = await this.request<RefundRequest>(`/refunds/${requestId}/process`, {\r\n method: 'POST',\r\n });\r\n this.config.onRefundProcessed?.(result);\r\n return result;\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n LICENSE REVOCATION\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Revoke license */\r\n async revokeLicense(\r\n licenseKey: LicenseKey,\r\n reason: RevocationReason,\r\n options?: {\r\n reasonDetails?: string;\r\n permanent?: boolean;\r\n notifyCustomer?: boolean;\r\n refundRequestId?: string;\r\n },\r\n ): Promise<RevocationRecord> {\r\n const result = await this.request<RevocationRecord>('/revocations', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n licenseKey,\r\n reason,\r\n ...options,\r\n }),\r\n });\r\n this.config.onLicenseRevoked?.(result);\r\n return result;\r\n }\r\n\r\n /** Get revocation history */\r\n async getRevocationHistory(licenseKey?: LicenseKey): Promise<RevocationRecord[]> {\r\n const endpoint = licenseKey\r\n ? `/revocations?licenseKey=${encodeURIComponent(licenseKey)}`\r\n : '/revocations';\r\n return this.request<RevocationRecord[]>(endpoint);\r\n }\r\n\r\n /** Reactivate revoked license (if allowed) */\r\n async reactivateLicense(\r\n revocationId: string,\r\n reason: string,\r\n ): Promise<{ success: boolean; license?: LicenseInfo }> {\r\n return this.request(`/revocations/${revocationId}/reactivate`, {\r\n method: 'POST',\r\n body: JSON.stringify({ reason }),\r\n });\r\n }\r\n\r\n /* ─────────────────────────────────────────────────────────────\r\n STATISTICS\r\n ───────────────────────────────────────────────────────────── */\r\n\r\n /** Get refund statistics */\r\n async getRefundStats(\r\n startDate: string,\r\n endDate: string,\r\n ): Promise<{\r\n totalRequests: number;\r\n totalRefunded: number;\r\n totalRejected: number;\r\n totalAmount: number;\r\n averageAmount: number;\r\n byReason: Record<RefundReason, number>;\r\n byStatus: Record<RefundStatus, number>;\r\n averageProcessingTime: number;\r\n autoApprovalRate: number;\r\n }> {\r\n return this.request(`/refunds/stats?start=${startDate}&end=${endDate}`);\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n HELPERS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function getRefundReasonLabel(reason: RefundReason): string {\r\n const labels: Record<RefundReason, string> = {\r\n product_not_as_described: 'Product not as described',\r\n technical_issues: 'Technical issues',\r\n accidental_purchase: 'Accidental purchase',\r\n no_longer_needed: 'No longer needed',\r\n found_alternative: 'Found alternative',\r\n pricing_concerns: 'Pricing concerns',\r\n customer_service: 'Customer service issues',\r\n other: 'Other',\r\n };\r\n return labels[reason];\r\n}\r\n\r\nexport function getRefundStatusColor(status: RefundStatus): string {\r\n const colors: Record<RefundStatus, string> = {\r\n pending: '#f59e0b',\r\n approved: '#3b82f6',\r\n rejected: '#ef4444',\r\n processing: '#8b5cf6',\r\n completed: '#22c55e',\r\n failed: '#dc2626',\r\n cancelled: '#6b7280',\r\n };\r\n return colors[status];\r\n}\r\n\r\nexport function getRevocationReasonLabel(reason: RevocationReason): string {\r\n const labels: Record<RevocationReason, string> = {\r\n refund: 'Refund processed',\r\n chargeback: 'Payment chargeback',\r\n fraud: 'Fraud detected',\r\n violation: 'Terms violation',\r\n breach_of_terms: 'Breach of terms',\r\n payment_failure: 'Payment failure',\r\n admin_action: 'Administrative action',\r\n license_transfer: 'License transferred',\r\n };\r\n return labels[reason];\r\n}\r\n\r\nexport const DEFAULT_REFUND_POLICY: RefundPolicy = {\r\n refundPeriodDays: 30,\r\n autoApprovalTiers: ['trial', 'personal'],\r\n autoApprovalMaxAmount: 10000, // $100\r\n maxRefundsPerYear: 3,\r\n requireReason: true,\r\n requireDetails: false,\r\n fullRefundDays: 14,\r\n partialRefundPercent: 50,\r\n};\r\n\r\nexport function createRefundService(config: RefundConfig): RefundService {\r\n return new RefundService(config);\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n All types are exported at their declaration points above.\r\n══════════════════════════════════════════════════════════════ */\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// `any` is intentional for bundler integration: webpack `Compiler` /\r\n// `Compilation` and the Vite/Rollup plugin object shapes are pulled in\r\n// only when the consumer installs the corresponding bundler. Avoiding a\r\n// hard peer dependency keeps the licensing package framework-agnostic.\r\n/* ────────────────────────────────────────────────────────────────\r\n \r\n Build-time license verification plugin for webpack, Vite, Rollup,\r\n and other bundlers. Ensures enterprise features require valid license.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport {\r\n validateKeyFormat,\r\n extractKeyMetadata,\r\n tierMeetsRequirement,\r\n} from '../LicenseKeyGenerator';\r\nimport type { LicenseKey, LicenseTier, FeatureId, LicenseInfo } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface BuildLicenseConfig {\r\n /** License key (can be from env var) */\r\n licenseKey?: LicenseKey;\r\n /** Environment variable name for license key */\r\n licenseKeyEnvVar?: string;\r\n /** License server URL for online validation */\r\n licenseServerUrl?: string;\r\n /** Fail build if license is invalid */\r\n failOnInvalid?: boolean;\r\n /** Fail build if license is expired */\r\n failOnExpired?: boolean;\r\n /** Required tier for build */\r\n requiredTier?: LicenseTier;\r\n /** Required features for build */\r\n requiredFeatures?: FeatureId[];\r\n /** Allow offline license (cached) */\r\n allowOffline?: boolean;\r\n /** Cache directory for offline license */\r\n cacheDir?: string;\r\n /** Silent mode (no console output) */\r\n silent?: boolean;\r\n /** Custom validation endpoint */\r\n validationEndpoint?: string;\r\n /** Timeout for license validation (ms) */\r\n validationTimeout?: number;\r\n}\r\n\r\nexport interface BuildLicenseResult {\r\n valid: boolean;\r\n licenseKey?: LicenseKey;\r\n tier?: LicenseTier;\r\n licensee?: string;\r\n features?: FeatureId[];\r\n expiresAt?: string;\r\n daysRemaining?: number;\r\n warnings: string[];\r\n errors: string[];\r\n}\r\n\r\nexport interface LicenseFeatureGate {\r\n featureId: FeatureId;\r\n requiredTier: LicenseTier;\r\n requiredFeature?: FeatureId;\r\n files: string[];\r\n replacement?: string;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n BUILD LICENSE VALIDATOR\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport class BuildLicenseValidator {\r\n private config: BuildLicenseConfig;\r\n private licenseInfo: LicenseInfo | null = null;\r\n private validationResult: BuildLicenseResult | null = null;\r\n\r\n constructor(config: BuildLicenseConfig = {}) {\r\n this.config = {\r\n failOnInvalid: true,\r\n failOnExpired: true,\r\n allowOffline: true,\r\n validationTimeout: 10000,\r\n ...config,\r\n };\r\n }\r\n\r\n /** Get license key from config or environment */\r\n private getLicenseKey(): LicenseKey | null {\r\n if (this.config.licenseKey) {\r\n return this.config.licenseKey;\r\n }\r\n\r\n const envVar = this.config.licenseKeyEnvVar || 'NICE2DEV_LICENSE_KEY';\r\n return process.env[envVar] || null;\r\n }\r\n\r\n /** Log message (unless silent) */\r\n private log(message: string, type: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (this.config.silent) {\r\n return;\r\n }\r\n\r\n const prefix = '[nice2dev/license]';\r\n switch (type) {\r\n case 'warn':\r\n console.warn(`${prefix} ⚠ ${message}`);\r\n break;\r\n case 'error':\r\n console.error(`${prefix} ✗ ${message}`);\r\n break;\r\n default:\r\n console.log(`${prefix} ${message}`);\r\n }\r\n }\r\n\r\n /** Validate license online */\r\n private async validateOnline(licenseKey: LicenseKey): Promise<LicenseInfo | null> {\r\n if (!this.config.licenseServerUrl) {\r\n return null;\r\n }\r\n\r\n const endpoint = this.config.validationEndpoint || '/api/licenses/validate';\r\n const url = `${this.config.licenseServerUrl}${endpoint}`;\r\n\r\n try {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), this.config.validationTimeout);\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ licenseKey }),\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeout);\r\n\r\n if (!response.ok) {\r\n this.log(`Online validation failed: ${response.status}`, 'warn');\r\n return null;\r\n }\r\n\r\n const result = await response.json();\r\n return result.license || null;\r\n } catch (error) {\r\n this.log(`Online validation error: ${(error as Error).message}`, 'warn');\r\n return null;\r\n }\r\n }\r\n\r\n /** Load cached license */\r\n private async loadCachedLicense(licenseKey: LicenseKey): Promise<LicenseInfo | null> {\r\n if (!this.config.allowOffline || !this.config.cacheDir) {\r\n return null;\r\n }\r\n\r\n const fs = await import('fs').then((m) => m.promises).catch(() => null);\r\n if (!fs) {\r\n return null;\r\n }\r\n\r\n const cacheFile = `${this.config.cacheDir}/.license-cache.json`;\r\n\r\n try {\r\n const content = await fs.readFile(cacheFile, 'utf-8');\r\n const cached = JSON.parse(content);\r\n if (cached.licenseKey === licenseKey && cached.license) {\r\n return cached.license;\r\n }\r\n } catch {\r\n // Cache doesn't exist or is invalid\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** Save license to cache */\r\n private async saveLicenseCache(licenseKey: LicenseKey, license: LicenseInfo): Promise<void> {\r\n if (!this.config.cacheDir) {\r\n return;\r\n }\r\n\r\n const fs = await import('fs').then((m) => m.promises).catch(() => null);\r\n const path = await import('path').catch(() => null);\r\n if (!fs || !path) {\r\n return;\r\n }\r\n\r\n try {\r\n await fs.mkdir(this.config.cacheDir, { recursive: true });\r\n const cacheFile = `${this.config.cacheDir}/.license-cache.json`;\r\n await fs.writeFile(\r\n cacheFile,\r\n JSON.stringify({ licenseKey, license, cachedAt: new Date().toISOString() }),\r\n );\r\n } catch {\r\n // Ignore cache write errors\r\n }\r\n }\r\n\r\n /** Validate license (main entry point) */\r\n async validate(): Promise<BuildLicenseResult> {\r\n const result: BuildLicenseResult = {\r\n valid: false,\r\n warnings: [],\r\n errors: [],\r\n };\r\n\r\n const licenseKey = this.getLicenseKey();\r\n\r\n // No license key provided\r\n if (!licenseKey) {\r\n if (this.config.failOnInvalid) {\r\n result.errors.push(\r\n 'No license key provided. Set NICE2DEV_LICENSE_KEY or pass licenseKey option.',\r\n );\r\n } else {\r\n result.warnings.push('No license key provided. Some features may be disabled.');\r\n result.valid = true; // Allow build to continue\r\n }\r\n this.validationResult = result;\r\n return result;\r\n }\r\n\r\n // Validate key format\r\n if (!validateKeyFormat(licenseKey)) {\r\n result.errors.push('Invalid license key format.');\r\n this.validationResult = result;\r\n return result;\r\n }\r\n\r\n // Extract basic metadata from key\r\n const metadata = extractKeyMetadata(licenseKey);\r\n result.licenseKey = licenseKey;\r\n result.tier = metadata?.tier;\r\n\r\n // Try online validation first\r\n let license = await this.validateOnline(licenseKey);\r\n\r\n // Fall back to cached license\r\n if (!license && this.config.allowOffline) {\r\n license = await this.loadCachedLicense(licenseKey);\r\n if (license) {\r\n result.warnings.push('Using cached license (offline mode).');\r\n }\r\n }\r\n\r\n // No valid license found\r\n if (!license) {\r\n // Use key metadata as fallback\r\n this.log('Could not validate license online, using key metadata.', 'warn');\r\n result.warnings.push('License could not be validated online.');\r\n\r\n // Check if required tier is met based on key metadata\r\n if (this.config.requiredTier && metadata?.tier) {\r\n if (!tierMeetsRequirement(metadata.tier, this.config.requiredTier)) {\r\n result.errors.push(\r\n `License tier \"${metadata.tier}\" does not meet required tier \"${this.config.requiredTier}\".`,\r\n );\r\n this.validationResult = result;\r\n return result;\r\n }\r\n }\r\n\r\n result.valid = !this.config.failOnInvalid;\r\n this.validationResult = result;\r\n return result;\r\n }\r\n\r\n // Save to cache for offline use\r\n await this.saveLicenseCache(licenseKey, license);\r\n\r\n this.licenseInfo = license;\r\n result.licensee = license.licensee;\r\n result.tier = license.tier;\r\n result.features = license.features;\r\n result.expiresAt = license.expiresAt || undefined;\r\n\r\n // Check expiration\r\n if (license.expiresAt) {\r\n const expiresAt = new Date(license.expiresAt);\r\n const now = new Date();\r\n const daysRemaining = Math.ceil(\r\n (expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24),\r\n );\r\n result.daysRemaining = daysRemaining;\r\n\r\n if (daysRemaining <= 0) {\r\n if (this.config.failOnExpired) {\r\n result.errors.push('License has expired.');\r\n this.validationResult = result;\r\n return result;\r\n } else {\r\n result.warnings.push('License has expired. Some features may be disabled.');\r\n }\r\n } else if (daysRemaining <= 30) {\r\n result.warnings.push(`License expires in ${daysRemaining} days.`);\r\n }\r\n }\r\n\r\n // Check required tier\r\n if (this.config.requiredTier) {\r\n if (!tierMeetsRequirement(license.tier, this.config.requiredTier)) {\r\n result.errors.push(\r\n `License tier \"${license.tier}\" does not meet required tier \"${this.config.requiredTier}\".`,\r\n );\r\n this.validationResult = result;\r\n return result;\r\n }\r\n }\r\n\r\n // Check required features\r\n if (this.config.requiredFeatures?.length) {\r\n const missingFeatures = this.config.requiredFeatures.filter(\r\n (f) => !license.features.includes(f),\r\n );\r\n if (missingFeatures.length > 0) {\r\n result.errors.push(`License missing required features: ${missingFeatures.join(', ')}`);\r\n this.validationResult = result;\r\n return result;\r\n }\r\n }\r\n\r\n result.valid = true;\r\n this.validationResult = result;\r\n\r\n // Log success\r\n this.log(`License validated: ${license.licensee} (${license.tier})`);\r\n\r\n return result;\r\n }\r\n\r\n /** Get validation result */\r\n getResult(): BuildLicenseResult | null {\r\n return this.validationResult;\r\n }\r\n\r\n /** Get license info */\r\n getLicenseInfo(): LicenseInfo | null {\r\n return this.licenseInfo;\r\n }\r\n\r\n /** Check if feature is available */\r\n hasFeature(featureId: FeatureId): boolean {\r\n return this.licenseInfo?.features.includes(featureId) ?? false;\r\n }\r\n\r\n /** Check if tier meets requirement */\r\n meetsTier(requiredTier: LicenseTier): boolean {\r\n return this.licenseInfo ? tierMeetsRequirement(this.licenseInfo.tier, requiredTier) : false;\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n WEBPACK PLUGIN\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface Nice2DevLicenseWebpackPluginOptions extends BuildLicenseConfig {\r\n /** Feature gates to apply */\r\n featureGates?: LicenseFeatureGate[];\r\n}\r\n\r\nexport class Nice2DevLicenseWebpackPlugin {\r\n private validator: BuildLicenseValidator;\r\n private options: Nice2DevLicenseWebpackPluginOptions;\r\n private validated = false;\r\n\r\n constructor(options: Nice2DevLicenseWebpackPluginOptions = {}) {\r\n this.options = options;\r\n this.validator = new BuildLicenseValidator(options);\r\n }\r\n\r\n apply(compiler: any): void {\r\n compiler.hooks.beforeRun.tapPromise('Nice2DevLicensePlugin', async () => {\r\n if (this.validated) {\r\n return;\r\n }\r\n\r\n const result = await this.validator.validate();\r\n this.validated = true;\r\n\r\n // Log warnings\r\n result.warnings.forEach((w) => console.warn(`[nice2dev] ⚠ ${w}`));\r\n\r\n // Fail build on errors\r\n if (result.errors.length > 0 && this.options.failOnInvalid !== false) {\r\n result.errors.forEach((e) => console.error(`[nice2dev] ✗ ${e}`));\r\n throw new Error('License validation failed');\r\n }\r\n });\r\n\r\n // Define plugin for feature flags\r\n compiler.hooks.compilation.tap('Nice2DevLicensePlugin', (compilation: any) => {\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const DefinePlugin = compiler.webpack?.DefinePlugin || require('webpack').DefinePlugin;\r\n const license = this.validator.getLicenseInfo();\r\n\r\n new DefinePlugin({\r\n 'process.env.NICE2DEV_LICENSE_VALID': JSON.stringify(\r\n this.validator.getResult()?.valid ?? false,\r\n ),\r\n 'process.env.NICE2DEV_LICENSE_TIER': JSON.stringify(license?.tier ?? 'trial'),\r\n 'process.env.NICE2DEV_LICENSE_FEATURES': JSON.stringify(license?.features ?? []),\r\n }).apply(compiler);\r\n });\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n VITE PLUGIN\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport interface Nice2DevLicenseVitePluginOptions extends BuildLicenseConfig {\r\n featureGates?: LicenseFeatureGate[];\r\n}\r\n\r\nexport function nice2devLicenseVitePlugin(options: Nice2DevLicenseVitePluginOptions = {}): any {\r\n const validator = new BuildLicenseValidator(options);\r\n let validated = false;\r\n\r\n return {\r\n name: 'nice2dev-license',\r\n\r\n async buildStart() {\r\n if (validated) {\r\n return;\r\n }\r\n\r\n const result = await validator.validate();\r\n validated = true;\r\n\r\n result.warnings.forEach((w) => this.warn(w));\r\n\r\n if (result.errors.length > 0 && options.failOnInvalid !== false) {\r\n result.errors.forEach((e) => this.error(e));\r\n throw new Error('License validation failed');\r\n }\r\n },\r\n\r\n config() {\r\n const license = validator.getLicenseInfo();\r\n return {\r\n define: {\r\n 'import.meta.env.NICE2DEV_LICENSE_VALID': JSON.stringify(\r\n validator.getResult()?.valid ?? false,\r\n ),\r\n 'import.meta.env.NICE2DEV_LICENSE_TIER': JSON.stringify(license?.tier ?? 'trial'),\r\n 'import.meta.env.NICE2DEV_LICENSE_FEATURES': JSON.stringify(license?.features ?? []),\r\n },\r\n };\r\n },\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n ROLLUP PLUGIN\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function nice2devLicenseRollupPlugin(options: BuildLicenseConfig = {}): any {\r\n const validator = new BuildLicenseValidator(options);\r\n let validated = false;\r\n\r\n return {\r\n name: 'nice2dev-license',\r\n\r\n async buildStart() {\r\n if (validated) {\r\n return;\r\n }\r\n\r\n const result = await validator.validate();\r\n validated = true;\r\n\r\n result.warnings.forEach((w) => this.warn(w));\r\n\r\n if (result.errors.length > 0 && options.failOnInvalid !== false) {\r\n throw new Error(result.errors.join('\\n'));\r\n }\r\n },\r\n };\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n EXPORTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\n// BuildLicenseValidator is already exported at declaration (line 66)\r\nexport default Nice2DevLicenseWebpackPlugin;\r\n","/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — CI/CD License Check Step\r\n \r\n CI/CD pipeline integration for license validation.\r\n Supports GitHub Actions, Azure DevOps, GitLab CI, Jenkins, CircleCI.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\nimport {\r\n validateKeyFormat,\r\n extractKeyMetadata,\r\n tierMeetsRequirement,\r\n} from '../LicenseKeyGenerator';\r\nimport type { LicenseKey, LicenseTier, FeatureId, LicenseInfo } from '../types';\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n TYPES\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport type CIPlatform =\r\n | 'github-actions'\r\n | 'azure-devops'\r\n | 'gitlab-ci'\r\n | 'jenkins'\r\n | 'circleci'\r\n | 'bitbucket-pipelines'\r\n | 'travis-ci'\r\n | 'unknown';\r\n\r\nexport interface CILicenseCheckOptions {\r\n /** License key */\r\n licenseKey?: LicenseKey;\r\n /** Environment variable containing license key */\r\n licenseKeyEnvVar?: string;\r\n /** License server URL */\r\n licenseServerUrl?: string;\r\n /** Required minimum tier */\r\n requiredTier?: LicenseTier;\r\n /** Required features */\r\n requiredFeatures?: FeatureId[];\r\n /** Fail pipeline if invalid */\r\n failOnInvalid?: boolean;\r\n /** Fail pipeline if expired */\r\n failOnExpired?: boolean;\r\n /** Skip validation for PRs from forks */\r\n skipForForks?: boolean;\r\n /** Grace period days after expiration */\r\n expirationGraceDays?: number;\r\n /** Output format */\r\n outputFormat?: 'human' | 'json' | 'ci-annotations';\r\n /** Set CI environment variables with license info */\r\n setEnvVars?: boolean;\r\n}\r\n\r\nexport interface CILicenseCheckResult {\r\n success: boolean;\r\n platform: CIPlatform;\r\n exitCode: number;\r\n message: string;\r\n license?: {\r\n key: LicenseKey;\r\n tier: LicenseTier;\r\n licensee?: string;\r\n features: FeatureId[];\r\n expiresAt?: string;\r\n daysRemaining?: number;\r\n };\r\n warnings: string[];\r\n errors: string[];\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n CI PLATFORM DETECTION\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function detectCIPlatform(): CIPlatform {\r\n const env = process.env;\r\n\r\n if (env.GITHUB_ACTIONS === 'true') {\r\n return 'github-actions';\r\n }\r\n if (env.TF_BUILD === 'True') {\r\n return 'azure-devops';\r\n }\r\n if (env.GITLAB_CI === 'true') {\r\n return 'gitlab-ci';\r\n }\r\n if (env.JENKINS_URL) {\r\n return 'jenkins';\r\n }\r\n if (env.CIRCLECI === 'true') {\r\n return 'circleci';\r\n }\r\n if (env.BITBUCKET_BUILD_NUMBER) {\r\n return 'bitbucket-pipelines';\r\n }\r\n if (env.TRAVIS === 'true') {\r\n return 'travis-ci';\r\n }\r\n\r\n return 'unknown';\r\n}\r\n\r\nexport function isForkPR(): boolean {\r\n const env = process.env;\r\n const platform = detectCIPlatform();\r\n\r\n switch (platform) {\r\n case 'github-actions':\r\n return (\r\n env.GITHUB_EVENT_NAME === 'pull_request' &&\r\n env.GITHUB_HEAD_REF !== undefined &&\r\n env.GITHUB_REPOSITORY !== env.GITHUB_HEAD_REPOSITORY\r\n );\r\n case 'gitlab-ci':\r\n return env.CI_MERGE_REQUEST_SOURCE_PROJECT_PATH !== env.CI_PROJECT_PATH;\r\n case 'azure-devops':\r\n return env.BUILD_REASON === 'PullRequest' && env.SYSTEM_PULLREQUEST_ISFORK === 'True';\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n CI OUTPUT FORMATTING\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nclass CIOutputFormatter {\r\n private platform: CIPlatform;\r\n private outputFormat: 'human' | 'json' | 'ci-annotations';\r\n\r\n constructor(platform: CIPlatform, format: 'human' | 'json' | 'ci-annotations' = 'human') {\r\n this.platform = platform;\r\n this.outputFormat = format;\r\n }\r\n\r\n info(message: string): void {\r\n if (this.outputFormat === 'json') {\r\n return;\r\n }\r\n console.log(`ℹ️ ${message}`);\r\n }\r\n\r\n success(message: string): void {\r\n if (this.outputFormat === 'json') {\r\n return;\r\n }\r\n\r\n switch (this.platform) {\r\n case 'github-actions':\r\n console.log(`::notice::${message}`);\r\n break;\r\n case 'azure-devops':\r\n console.log(`##[section]${message}`);\r\n break;\r\n default:\r\n console.log(`✅ ${message}`);\r\n }\r\n }\r\n\r\n warning(message: string): void {\r\n if (this.outputFormat === 'json') {\r\n return;\r\n }\r\n\r\n switch (this.platform) {\r\n case 'github-actions':\r\n console.log(`::warning::${message}`);\r\n break;\r\n case 'azure-devops':\r\n console.log(`##[warning]${message}`);\r\n break;\r\n case 'gitlab-ci':\r\n console.warn(`\\x1b[33mWarning: ${message}\\x1b[0m`);\r\n break;\r\n default:\r\n console.warn(`⚠️ ${message}`);\r\n }\r\n }\r\n\r\n error(message: string): void {\r\n if (this.outputFormat === 'json') {\r\n return;\r\n }\r\n\r\n switch (this.platform) {\r\n case 'github-actions':\r\n console.log(`::error::${message}`);\r\n break;\r\n case 'azure-devops':\r\n console.log(`##[error]${message}`);\r\n break;\r\n case 'gitlab-ci':\r\n console.error(`\\x1b[31mError: ${message}\\x1b[0m`);\r\n break;\r\n default:\r\n console.error(`❌ ${message}`);\r\n }\r\n }\r\n\r\n setOutput(name: string, value: string): void {\r\n switch (this.platform) {\r\n case 'github-actions':\r\n // Requires GITHUB_OUTPUT file\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const fs = require('fs');\r\n const outputFile = process.env.GITHUB_OUTPUT;\r\n if (outputFile) {\r\n fs.appendFileSync(outputFile, `${name}=${value}\\n`);\r\n }\r\n break;\r\n case 'azure-devops':\r\n console.log(`##vso[task.setvariable variable=${name}]${value}`);\r\n break;\r\n case 'gitlab-ci':\r\n // GitLab uses artifacts for outputs\r\n break;\r\n }\r\n }\r\n\r\n setEnvVar(name: string, value: string): void {\r\n switch (this.platform) {\r\n case 'github-actions':\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const fs = require('fs');\r\n const envFile = process.env.GITHUB_ENV;\r\n if (envFile) {\r\n fs.appendFileSync(envFile, `${name}=${value}\\n`);\r\n }\r\n break;\r\n case 'azure-devops':\r\n console.log(`##vso[task.setvariable variable=${name}]${value}`);\r\n break;\r\n default:\r\n // Other platforms don't support runtime env var setting\r\n break;\r\n }\r\n }\r\n\r\n group(name: string, content: () => void): void {\r\n switch (this.platform) {\r\n case 'github-actions':\r\n console.log(`::group::${name}`);\r\n content();\r\n console.log('::endgroup::');\r\n break;\r\n case 'azure-devops':\r\n console.log(`##[group]${name}`);\r\n content();\r\n console.log('##[endgroup]');\r\n break;\r\n default:\r\n console.log(`\\n--- ${name} ---`);\r\n content();\r\n console.log('');\r\n }\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n LICENSE VALIDATION\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nasync function validateLicenseOnline(\r\n licenseKey: LicenseKey,\r\n serverUrl: string,\r\n): Promise<LicenseInfo | null> {\r\n try {\r\n const response = await fetch(`${serverUrl}/api/licenses/validate`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ licenseKey, context: 'ci' }),\r\n });\r\n\r\n if (!response.ok) {\r\n return null;\r\n }\r\n\r\n const data = await response.json();\r\n return data.license || null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n MAIN LICENSE CHECK\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport async function runCILicenseCheck(\r\n options: CILicenseCheckOptions = {},\r\n): Promise<CILicenseCheckResult> {\r\n const platform = detectCIPlatform();\r\n const formatter = new CIOutputFormatter(platform, options.outputFormat);\r\n\r\n const result: CILicenseCheckResult = {\r\n success: false,\r\n platform,\r\n exitCode: 0,\r\n message: '',\r\n warnings: [],\r\n errors: [],\r\n };\r\n\r\n // Check if we should skip for forks\r\n if (options.skipForForks && isForkPR()) {\r\n formatter.info('Skipping license check for fork PR');\r\n result.success = true;\r\n result.message = 'License check skipped for fork PR';\r\n return result;\r\n }\r\n\r\n // Get license key\r\n const licenseKey =\r\n options.licenseKey || process.env[options.licenseKeyEnvVar || 'NICE2DEV_LICENSE_KEY'];\r\n\r\n if (!licenseKey) {\r\n const error =\r\n 'No license key found. Set NICE2DEV_LICENSE_KEY secret or pass licenseKey option.';\r\n formatter.error(error);\r\n result.errors.push(error);\r\n result.message = error;\r\n result.exitCode = options.failOnInvalid !== false ? 1 : 0;\r\n result.success = options.failOnInvalid === false;\r\n return result;\r\n }\r\n\r\n // Mask license key in logs\r\n formatter.info(`Validating license: ${licenseKey.substring(0, 12)}...`);\r\n\r\n // Validate format\r\n if (!validateKeyFormat(licenseKey)) {\r\n const error = 'Invalid license key format';\r\n formatter.error(error);\r\n result.errors.push(error);\r\n result.message = error;\r\n result.exitCode = 1;\r\n return result;\r\n }\r\n\r\n // Extract metadata from key\r\n const metadata = extractKeyMetadata(licenseKey);\r\n const license = {\r\n key: licenseKey,\r\n tier: metadata?.tier || ('trial' as LicenseTier),\r\n features: [] as string[],\r\n licensee: undefined as string | undefined,\r\n expiresAt: undefined as string | undefined,\r\n daysRemaining: undefined as number | undefined,\r\n };\r\n result.license = license;\r\n\r\n // Try online validation\r\n if (options.licenseServerUrl) {\r\n const onlineLicense = await validateLicenseOnline(licenseKey, options.licenseServerUrl);\r\n\r\n if (onlineLicense) {\r\n license.licensee = onlineLicense.licensee;\r\n license.tier = onlineLicense.tier;\r\n license.features = onlineLicense.features;\r\n license.expiresAt = onlineLicense.expiresAt || undefined;\r\n\r\n formatter.success(`License validated for: ${onlineLicense.licensee} (${onlineLicense.tier})`);\r\n } else {\r\n const warning = 'Could not validate license online, using key metadata';\r\n formatter.warning(warning);\r\n result.warnings.push(warning);\r\n }\r\n }\r\n\r\n // Check expiration\r\n if (license.expiresAt) {\r\n const expiresAt = new Date(license.expiresAt);\r\n const now = new Date();\r\n const daysRemaining = Math.ceil((expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));\r\n license.daysRemaining = daysRemaining;\r\n\r\n const graceDays = options.expirationGraceDays ?? 0;\r\n\r\n if (daysRemaining < -graceDays) {\r\n const error = `License expired ${Math.abs(daysRemaining)} days ago`;\r\n if (options.failOnExpired !== false) {\r\n formatter.error(error);\r\n result.errors.push(error);\r\n result.exitCode = 1;\r\n result.message = error;\r\n return result;\r\n } else {\r\n formatter.warning(error);\r\n result.warnings.push(error);\r\n }\r\n } else if (daysRemaining <= 0) {\r\n const warning = `License expired but within grace period (${graceDays} days)`;\r\n formatter.warning(warning);\r\n result.warnings.push(warning);\r\n } else if (daysRemaining <= 30) {\r\n const warning = `License expires in ${daysRemaining} days`;\r\n formatter.warning(warning);\r\n result.warnings.push(warning);\r\n }\r\n }\r\n\r\n // Check tier requirement\r\n if (options.requiredTier) {\r\n if (!tierMeetsRequirement(license.tier, options.requiredTier)) {\r\n const error = `License tier \"${license.tier}\" does not meet required tier \"${options.requiredTier}\"`;\r\n formatter.error(error);\r\n result.errors.push(error);\r\n result.exitCode = 1;\r\n result.message = error;\r\n return result;\r\n }\r\n formatter.info(`Tier check passed: ${license.tier} >= ${options.requiredTier}`);\r\n }\r\n\r\n // Check feature requirements\r\n if (options.requiredFeatures?.length) {\r\n const missingFeatures = options.requiredFeatures.filter((f) => !license.features.includes(f));\r\n if (missingFeatures.length > 0) {\r\n const error = `Missing required features: ${missingFeatures.join(', ')}`;\r\n formatter.error(error);\r\n result.errors.push(error);\r\n result.exitCode = 1;\r\n result.message = error;\r\n return result;\r\n }\r\n formatter.info(`Feature check passed: ${options.requiredFeatures.join(', ')}`);\r\n }\r\n\r\n // Set environment variables\r\n if (options.setEnvVars !== false) {\r\n formatter.setEnvVar('NICE2DEV_LICENSE_VALID', 'true');\r\n formatter.setEnvVar('NICE2DEV_LICENSE_TIER', license.tier);\r\n formatter.setOutput('license-valid', 'true');\r\n formatter.setOutput('license-tier', license.tier);\r\n }\r\n\r\n // Success\r\n result.success = true;\r\n result.message = `License validated successfully (${license.tier})`;\r\n formatter.success(result.message);\r\n\r\n // JSON output\r\n if (options.outputFormat === 'json') {\r\n console.log(JSON.stringify(result, null, 2));\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n CLI WRAPPER\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport async function main(): Promise<void> {\r\n const args = process.argv.slice(2);\r\n const options: CILicenseCheckOptions = {};\r\n\r\n // Parse CLI arguments\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const getValue = () => args[++i];\r\n\r\n switch (arg) {\r\n case '--license-key':\r\n case '-k':\r\n options.licenseKey = getValue();\r\n break;\r\n case '--server':\r\n case '-s':\r\n options.licenseServerUrl = getValue();\r\n break;\r\n case '--required-tier':\r\n case '-t':\r\n options.requiredTier = getValue() as LicenseTier;\r\n break;\r\n case '--required-features':\r\n case '-f':\r\n options.requiredFeatures = getValue().split(',') as FeatureId[];\r\n break;\r\n case '--skip-for-forks':\r\n options.skipForForks = true;\r\n break;\r\n case '--no-fail':\r\n options.failOnInvalid = false;\r\n break;\r\n case '--grace-days':\r\n case '-g':\r\n options.expirationGraceDays = parseInt(getValue(), 10);\r\n break;\r\n case '--json':\r\n options.outputFormat = 'json';\r\n break;\r\n case '--help':\r\n case '-h':\r\n printHelp();\r\n return;\r\n }\r\n }\r\n\r\n const result = await runCILicenseCheck(options);\r\n process.exit(result.exitCode);\r\n}\r\n\r\nfunction printHelp(): void {\r\n console.log(`\r\nNice2Dev License Check - CI/CD Pipeline Integration\r\n\r\nUsage: nice2dev-license-check [options]\r\n\r\nOptions:\r\n -k, --license-key <key> License key (or use NICE2DEV_LICENSE_KEY env var)\r\n -s, --server <url> License server URL for online validation\r\n -t, --required-tier <tier> Required minimum tier (trial|personal|team|enterprise|site|oem)\r\n -f, --required-features Required features (comma-separated)\r\n --skip-for-forks Skip check for PRs from forks\r\n --no-fail Don't fail pipeline on invalid license\r\n -g, --grace-days <days> Grace period after expiration\r\n --json Output results as JSON\r\n -h, --help Show this help message\r\n\r\nEnvironment Variables:\r\n NICE2DEV_LICENSE_KEY License key\r\n NICE2DEV_LICENSE_SERVER License server URL\r\n\r\nExamples:\r\n # Basic check\r\n nice2dev-license-check\r\n\r\n # With server validation and tier requirement\r\n nice2dev-license-check -s https://license.nice2dev.com -t team\r\n\r\n # Skip for forks (safe for open source)\r\n nice2dev-license-check --skip-for-forks\r\n`);\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n GITHUB ACTION WORKFLOW GENERATOR\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function generateGitHubActionsWorkflow(options: {\r\n requiredTier?: LicenseTier;\r\n requiredFeatures?: FeatureId[];\r\n skipForForks?: boolean;\r\n}): string {\r\n return `name: License Check\r\n\r\non:\r\n pull_request:\r\n push:\r\n branches: [main, master]\r\n\r\njobs:\r\n license-check:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n \r\n - name: Setup Node.js\r\n uses: actions/setup-node@v4\r\n with:\r\n node-version: '20'\r\n \r\n - name: Install dependencies\r\n run: npm ci\r\n \r\n - name: Validate License\r\n run: npx nice2dev-license-check${options.requiredTier ? ` -t ${options.requiredTier}` : ''}${options.skipForForks ? ' --skip-for-forks' : ''}\r\n env:\r\n NICE2DEV_LICENSE_KEY: \\${{ secrets.NICE2DEV_LICENSE_KEY }}\r\n`;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n AZURE DEVOPS PIPELINE GENERATOR\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function generateAzureDevOpsPipeline(options: { requiredTier?: LicenseTier }): string {\r\n return `trigger:\r\n - main\r\n - master\r\n\r\npool:\r\n vmImage: 'ubuntu-latest'\r\n\r\nsteps:\r\n- task: NodeTool@0\r\n inputs:\r\n versionSpec: '20.x'\r\n displayName: 'Install Node.js'\r\n\r\n- script: npm ci\r\n displayName: 'Install dependencies'\r\n\r\n- script: npx nice2dev-license-check${options.requiredTier ? ` -t ${options.requiredTier}` : ''}\r\n displayName: 'Validate License'\r\n env:\r\n NICE2DEV_LICENSE_KEY: $(NICE2DEV_LICENSE_KEY)\r\n`;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n GITLAB CI PIPELINE GENERATOR\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport function generateGitLabCIPipeline(options: { requiredTier?: LicenseTier }): string {\r\n return `stages:\r\n - validate\r\n\r\nlicense-check:\r\n stage: validate\r\n image: node:20\r\n script:\r\n - npm ci\r\n - npx nice2dev-license-check${options.requiredTier ? ` -t ${options.requiredTier}` : ''}\r\n variables:\r\n NICE2DEV_LICENSE_KEY: $NICE2DEV_LICENSE_KEY\r\n`;\r\n}\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n EXPORTS\r\n══════════════════════════════════════════════════════════════ */\r\n\r\nexport { CIOutputFormatter, validateLicenseOnline };\r\n","/* ────────────────────────────────────────────────────────────────\r\n @nice2dev/licensing — Enterprise Licensing System\r\n \r\n License key generation, validation, hardware fingerprinting,\r\n seat management and feature gating for Nice2Dev components.\r\n──────────────────────────────────────────────────────────────── */\r\n\r\n// Types\r\nexport type {\r\n LicenseTier,\r\n LicenseStatus,\r\n FeatureId,\r\n LicenseKey,\r\n HardwareFingerprint,\r\n MachineId,\r\n LicenseInfo,\r\n LicenseKeyOptions,\r\n LicenseValidationResult,\r\n LicenseErrorCode,\r\n HardwareFingerprintData,\r\n OfflineChallenge,\r\n OfflineResponse,\r\n SeatInfo,\r\n TelemetryEvent,\r\n LicenseServerConfig,\r\n FeatureDefinition,\r\n LicensePlan,\r\n LicenseState,\r\n} from './types';\r\n\r\n// License Key Generator\r\nexport {\r\n generateLicenseKey,\r\n validateKeyFormat,\r\n extractKeyMetadata,\r\n generateLicenseInfo,\r\n getDefaultFeatures,\r\n getDefaultSeats,\r\n getDefaultMachines,\r\n compareTiers,\r\n tierMeetsRequirement,\r\n maskLicenseKey,\r\n normalizeLicenseKey,\r\n} from './LicenseKeyGenerator';\r\n\r\n// Hardware Fingerprint\r\nexport {\r\n collectFingerprintData,\r\n generateFingerprint,\r\n generateMachineId,\r\n compareFingerprintsData,\r\n storeFingerprint,\r\n getStoredFingerprint,\r\n getOrGenerateFingerprint,\r\n} from './HardwareFingerprint';\r\n\r\n// License Validator\r\nexport {\r\n LicenseValidator,\r\n getValidator,\r\n validateLicense,\r\n isFeatureLicensed,\r\n} from './LicenseValidator';\r\n\r\n// Seat Manager\r\nexport {\r\n SeatManager,\r\n FloatingLicenseManager,\r\n createSeatManager,\r\n createFloatingLicenseManager,\r\n} from './SeatManager';\r\n\r\n// Feature Gate\r\nexport {\r\n registerFeature,\r\n registerFeatures,\r\n getFeature,\r\n getAllFeatures,\r\n getFeaturesByCategory,\r\n registerPlan,\r\n registerPlans,\r\n getPlan,\r\n getAllPlans,\r\n hasFeature,\r\n hasTier,\r\n getAvailableFeatures,\r\n getMissingFeatures,\r\n checkFeatureAccess,\r\n initializeDefaults,\r\n} from './FeatureGate';\r\nexport type { FeatureCheckResult } from './FeatureGate';\r\n\r\n// Usage Telemetry\r\nexport { UsageTelemetry, createTelemetry, hashLicenseKey } from './UsageTelemetry';\r\nexport type { UsageTelemetryConfig } from './UsageTelemetry';\r\n\r\n// Source Access Control\r\nexport {\r\n registerProtectedModule,\r\n registerProtectedModules,\r\n getAllProtectedModules,\r\n getProtectedModule,\r\n isModuleAccessible,\r\n getInaccessibleModules,\r\n getAccessibleModules,\r\n generateBundleTags,\r\n generateProtectionManifest,\r\n} from './SourceAccessControl';\r\nexport type { SourceAccessLevel, ProtectedModuleEntry, BundleTag } from './SourceAccessControl';\r\n\r\n// API Rate Limiter\r\nexport {\r\n RateLimiter,\r\n ApiRateLimiter,\r\n createApiRateLimiter,\r\n DEFAULT_RATE_LIMITS,\r\n} from './ApiRateLimiter';\r\nexport type { TierRateLimit, RateLimitConfig, RateLimitResult } from './ApiRateLimiter';\r\n\r\n// White-labeling\r\nexport { WhiteLabelManager, createWhiteLabelManager } from './WhiteLabel';\r\nexport type { WhiteLabelConfig } from './WhiteLabel';\r\n\r\n// SLA Tracking\r\nexport { SlaTracker, createSlaTracker, DEFAULT_SLA_CONFIGS } from './SlaTracker';\r\nexport type { SlaTierConfig, SupportChannel, SlaEvent, SlaReport } from './SlaTracker';\r\n\r\n// Audit Trail\r\nexport { AuditTrail, createAuditTrail, hashKeyForAudit } from './AuditTrail';\r\nexport type {\r\n AuditEventType,\r\n AuditEntry,\r\n AuditActor,\r\n AuditQuery,\r\n AuditExportFormat,\r\n} from './AuditTrail';\r\n\r\n// License Portal\r\nexport {\r\n LicensePortalService,\r\n useLicensePortal,\r\n LicenseStatusBadge,\r\n LicenseTierBadge,\r\n LicenseCard,\r\n LicensePortal,\r\n} from './portal/LicensePortal';\r\nexport type {\r\n LicensePortalConfig,\r\n CustomerLicenseOverview,\r\n LicenseAction,\r\n} from './portal/LicensePortal';\r\n\r\n// Activation Wizard\r\nexport {\r\n ActivationService,\r\n useActivationWizard,\r\n ActivationWizard,\r\n} from './portal/ActivationWizard';\r\nexport type {\r\n ActivationStep,\r\n ActivationState,\r\n ActivationWizardConfig,\r\n} from './portal/ActivationWizard';\r\n\r\n// License Transfer\r\nexport {\r\n LicenseTransferService,\r\n useLicenseTransfer,\r\n TransferStatusBadge,\r\n LicenseTransfer,\r\n} from './portal/LicenseTransfer';\r\nexport type { TransferRequest, TransferStatus, TransferConfig } from './portal/LicenseTransfer';\r\n\r\n// Billing Integration\r\nexport { BillingService, createBillingService } from './billing/BillingIntegration';\r\nexport type {\r\n PaymentProvider,\r\n PricingPlan,\r\n Subscription,\r\n Invoice,\r\n PaymentMethod,\r\n CheckoutSession,\r\n BillingConfig,\r\n} from './billing/BillingIntegration';\r\n\r\n// Usage Analytics\r\nexport {\r\n UsageAnalyticsService,\r\n useUsageAnalytics,\r\n UsageAnalyticsDashboard,\r\n} from './analytics/UsageAnalyticsDashboard';\r\nexport type {\r\n OverviewMetrics,\r\n FeatureUsageData,\r\n UserActivityData,\r\n AnalyticsConfig,\r\n} from './analytics/UsageAnalyticsDashboard';\r\n\r\n// Refund System\r\nexport { RefundService, createRefundService, DEFAULT_REFUND_POLICY } from './refunds/RefundSystem';\r\nexport type {\r\n RefundPolicy,\r\n RefundRequest,\r\n RefundStatus,\r\n RefundReason,\r\n RevocationRecord,\r\n RefundConfig,\r\n} from './refunds/RefundSystem';\r\n\r\n// Build Plugin\r\nexport {\r\n BuildLicenseValidator,\r\n Nice2DevLicenseWebpackPlugin,\r\n nice2devLicenseVitePlugin,\r\n nice2devLicenseRollupPlugin,\r\n} from './build/LicenseBuildPlugin';\r\nexport type {\r\n BuildLicenseConfig,\r\n BuildLicenseResult,\r\n LicenseFeatureGate,\r\n Nice2DevLicenseWebpackPluginOptions,\r\n Nice2DevLicenseVitePluginOptions,\r\n} from './build/LicenseBuildPlugin';\r\n\r\n// CI/CD License Check\r\nexport {\r\n detectCIPlatform,\r\n isForkPR,\r\n runCILicenseCheck,\r\n generateGitHubActionsWorkflow,\r\n generateAzureDevOpsPipeline,\r\n generateGitLabCIPipeline,\r\n} from './ci/CILicenseCheck';\r\nexport type { CIPlatform, CILicenseCheckOptions, CILicenseCheckResult } from './ci/CILicenseCheck';\r\n\r\n// Version\r\nexport const VERSION = '1.1.0';\r\n"],"names":["generateMachineId","tierRank","useState","useCallback","useEffect","jsxs","jsx","Fragment","generateFingerprint","_a","useMemo","validateKeyFormat","extractKeyMetadata","tierMeetsRequirement"],"mappings":"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"}