@prosdevlab/experience-sdk 0.1.1 → 0.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/memory.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/cookie.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/localStorage.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/sessionStorage.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/storage.ts","../../plugins/src/banner/banner.ts","../../plugins/src/debug/debug.ts","../../plugins/src/frequency/frequency.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/util/deep-merge.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/config.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/emitter.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/expose.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/namespace.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/sdk.ts","../src/runtime.ts","../src/singleton.ts"],"names":["MemoryBackend","key","value","_options","CookieBackend","defaultOptions","name","cookies","cookie","error","options","opts","parts","expires","eqPos","testKey","supported","LocalStorageBackend","SessionStorageBackend","storagePlugin","plugin","instance","config","getBackendType","getNamespace","getDefaultTTL","getCookieDefaults","backends","getBackend","type","buildKey","namespace","ns","isExpired","stored","set","backendType","backend","namespacedKey","ttl","serialized","get","remove","clear","storage","prefix","keysToRemove","i","trimmed","eqIndex","encodedKey","isSupported","bannerPlugin","activeBanners","createBannerElement","experience","content","position","dismissable","zIndex","isDarkMode","bgColor","textColor","borderColor","shadowColor","banner","styleId","style","contentDiv","title","message","buttonContainer","createButton","buttonConfig","button","variant","bg","hoverBg","border","closeButton","closeColor","show","experienceId","id","isShowing","payload","items","item","typedItem","decision","debugPlugin","isEnabled","shouldLogConsole","shouldEmitWindow","log","data","logData","event","frequencyPlugin","experienceFrequencyMap","getStorageBackend","per","getStorageKey","getImpressionData","raw","saveImpressionData","getTimeWindow","getImpressionCount","hasReachedCap","max","timeWindow","now","timestamp","recordImpression","sevenDaysAgo","ts","freqStep","t","deepMerge","target","source","result","sourceValue","targetValue","isPlainObject","Config","initialConfig","path","keys","current","lastKey","Emitter","handler","subscription","sub","args","err","pattern","withWildcards","str","Expose","sdk","api","Namespace","SDK","pluginFn","expose","requiredNamespaces","ExperienceRuntime","exp","context","startTime","evalContext","buildContext","matchedExperience","allReasons","allTrace","evaluateExperience","freqStart","hasReached","count","sortedExperiences","a","b","priorityA","decisions","expStartTime","reasons","trace","matchedDecisions","d","matchedExperiences","index","partial","matched","urlStart","urlMatch","evaluateUrlRule","rule","url","createInstance","defaultInstance","init","register","evaluate","evaluateAll","explain","getState","on","destroy","experiences"],"mappings":"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","file":"experience-sdk.global.js","sourcesContent":["/**\n * Memory Storage Backend\n *\n * In-memory storage fallback when other storage mechanisms are unavailable.\n * Data is lost when the page is refreshed.\n */\n\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class MemoryBackend implements StorageBackend {\n private storage = new Map<string, string>();\n\n get(key: string): string | null {\n return this.storage.get(key) ?? null;\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n this.storage.set(key, value);\n }\n\n remove(key: string): void {\n this.storage.delete(key);\n }\n\n clear(): void {\n this.storage.clear();\n }\n\n isSupported(): boolean {\n // Memory storage is always supported\n return true;\n }\n}\n","/**\n * Cookie Storage Backend\n *\n * Stores data in browser cookies with support for domain, path, secure, and sameSite options.\n * Falls back to memory storage if cookies are unavailable.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class CookieBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n private defaultOptions: StorageBackendOptions;\n\n constructor(defaultOptions: StorageBackendOptions = {}) {\n this.defaultOptions = {\n path: '/',\n sameSite: 'lax',\n ...defaultOptions,\n };\n }\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n const name = `${encodeURIComponent(key)}=`;\n const cookies = document.cookie.split(';');\n\n for (let cookie of cookies) {\n cookie = cookie.trim();\n if (cookie.startsWith(name)) {\n return decodeURIComponent(cookie.substring(name.length));\n }\n }\n\n return null;\n } catch (error) {\n console.warn('Cookie get failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n const opts = { ...this.defaultOptions, ...options };\n const parts: string[] = [`${encodeURIComponent(key)}=${encodeURIComponent(value)}`];\n\n // Add expiration if TTL is provided\n if (opts.ttl) {\n const expires = new Date();\n expires.setTime(expires.getTime() + opts.ttl * 1000);\n parts.push(`expires=${expires.toUTCString()}`);\n }\n\n if (opts.path) {\n parts.push(`path=${opts.path}`);\n }\n\n if (opts.domain) {\n parts.push(`domain=${opts.domain}`);\n }\n\n if (opts.secure) {\n parts.push('secure');\n }\n\n if (opts.sameSite) {\n parts.push(`samesite=${opts.sameSite}`);\n }\n\n document.cookie = parts.join('; ');\n } catch (error) {\n console.warn('Cookie set failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n // Set cookie with past expiration date to delete it\n const opts = this.defaultOptions;\n const parts: string[] = [\n `${encodeURIComponent(key)}=`,\n 'expires=Thu, 01 Jan 1970 00:00:00 UTC',\n ];\n\n if (opts.path) {\n parts.push(`path=${opts.path}`);\n }\n\n if (opts.domain) {\n parts.push(`domain=${opts.domain}`);\n }\n\n document.cookie = parts.join('; ');\n } catch (error) {\n console.warn('Cookie remove failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n // Get all cookie names and delete them\n const cookies = document.cookie.split(';');\n\n for (let cookie of cookies) {\n cookie = cookie.trim();\n const eqPos = cookie.indexOf('=');\n const name = eqPos > -1 ? cookie.substring(0, eqPos) : cookie;\n this.remove(decodeURIComponent(name));\n }\n } catch (error) {\n console.warn('Cookie clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n // Check if cookies are enabled\n if (typeof document === 'undefined' || !document.cookie) {\n return false;\n }\n\n // Try to set and remove a test cookie\n const testKey = '__cookie_test__';\n document.cookie = `${testKey}=test; path=/`;\n const supported = document.cookie.indexOf(testKey) !== -1;\n\n // Clean up test cookie\n document.cookie = `${testKey}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n return supported;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * LocalStorage Backend\n *\n * Persistent storage that survives page refreshes and browser restarts.\n * Falls back to memory storage if localStorage is unavailable or quota is exceeded.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class LocalStorageBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n return localStorage.getItem(key);\n } catch (error) {\n console.warn('localStorage.getItem failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n localStorage.setItem(key, value);\n } catch (error) {\n // Quota exceeded or other error\n console.warn('localStorage.setItem failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n localStorage.removeItem(key);\n } catch (error) {\n console.warn('localStorage.removeItem failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n localStorage.clear();\n } catch (error) {\n console.warn('localStorage.clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n const testKey = '__storage_test__';\n localStorage.setItem(testKey, 'test');\n localStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * SessionStorage Backend\n *\n * Session-scoped storage that persists only for the duration of the page session.\n * Data is cleared when the tab/window is closed.\n * Falls back to memory storage if sessionStorage is unavailable.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class SessionStorageBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n return sessionStorage.getItem(key);\n } catch (error) {\n console.warn('sessionStorage.getItem failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n sessionStorage.setItem(key, value);\n } catch (error) {\n console.warn('sessionStorage.setItem failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n sessionStorage.removeItem(key);\n } catch (error) {\n console.warn('sessionStorage.removeItem failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n sessionStorage.clear();\n } catch (error) {\n console.warn('sessionStorage.clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n const testKey = '__storage_test__';\n sessionStorage.setItem(testKey, 'test');\n sessionStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * Storage Plugin\n *\n * Universal storage abstraction with support for:\n * - Multiple backends (localStorage, sessionStorage, cookie, memory)\n * - TTL/expiration\n * - Namespace isolation\n * - JSON serialization\n * - Automatic fallback\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\nimport { CookieBackend } from './backends/cookie';\nimport { LocalStorageBackend } from './backends/localStorage';\nimport { MemoryBackend } from './backends/memory';\nimport { SessionStorageBackend } from './backends/sessionStorage';\nimport type { StorageBackend, StorageBackendOptions } from './backends/types';\n\nexport type StorageBackendType = 'localStorage' | 'sessionStorage' | 'cookie' | 'memory';\n\nexport interface StoragePluginConfig {\n storage?: {\n backend?: StorageBackendType;\n namespace?: string;\n ttl?: number;\n // Cookie-specific defaults\n domain?: string;\n path?: string;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n };\n}\n\nexport interface StorageOptions extends StorageBackendOptions {\n backend?: StorageBackendType;\n namespace?: string;\n}\n\nexport interface StoragePlugin {\n set(key: string, value: unknown, options?: StorageOptions): void;\n get<T = unknown>(key: string, options?: Pick<StorageOptions, 'backend'>): T | null;\n remove(key: string, options?: Pick<StorageOptions, 'backend'>): void;\n clear(options?: Pick<StorageOptions, 'backend'>): void;\n}\n\ninterface StoredValue<T> {\n value: T;\n expires?: number; // Timestamp in milliseconds\n}\n\n/**\n * Storage Plugin\n *\n * Provides a universal storage API with automatic backend selection and fallback.\n *\n * @example\n * ```typescript\n * const sdk = new SDK({ storage: { backend: 'localStorage', namespace: 'myapp' } });\n * sdk.use(storagePlugin);\n *\n * sdk.storage.set('user', { id: 123, name: 'Alice' });\n * const user = sdk.storage.get('user');\n * ```\n */\nexport const storagePlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('storage');\n\n // Set default config\n plugin.defaults({\n storage: {\n backend: 'localStorage',\n namespace: '',\n path: '/',\n sameSite: 'lax',\n },\n });\n\n // Get config values\n const getBackendType = (): StorageBackendType => config.get('storage.backend') ?? 'localStorage';\n const getNamespace = (): string => config.get('storage.namespace') ?? '';\n const getDefaultTTL = (): number | undefined => config.get('storage.ttl');\n const getCookieDefaults = (): StorageBackendOptions => ({\n domain: config.get('storage.domain'),\n path: config.get('storage.path') ?? '/',\n secure: config.get('storage.secure'),\n sameSite: config.get('storage.sameSite') ?? 'lax',\n });\n\n // Backend instances (lazy-initialized)\n const backends: Partial<Record<StorageBackendType, StorageBackend>> = {};\n\n /**\n * Get or create a backend instance\n */\n function getBackend(type: StorageBackendType): StorageBackend {\n if (!backends[type]) {\n switch (type) {\n case 'localStorage':\n backends[type] = new LocalStorageBackend();\n break;\n case 'sessionStorage':\n backends[type] = new SessionStorageBackend();\n break;\n case 'cookie':\n backends[type] = new CookieBackend(getCookieDefaults());\n break;\n case 'memory':\n backends[type] = new MemoryBackend();\n break;\n }\n }\n return backends[type] as StorageBackend;\n }\n\n /**\n * Build a namespaced key\n */\n function buildKey(key: string, namespace?: string): string {\n const ns = namespace ?? getNamespace();\n return ns ? `${ns}:${key}` : key;\n }\n\n /**\n * Check if a stored value has expired\n */\n function isExpired(stored: StoredValue<any>): boolean {\n if (!stored.expires) {\n return false;\n }\n return Date.now() > stored.expires;\n }\n\n /**\n * Set a value in storage\n */\n function set<T>(key: string, value: T, options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n // Wrap value with expiration metadata\n const stored: StoredValue<T> = { value };\n const ttl = options?.ttl ?? getDefaultTTL();\n\n if (ttl) {\n stored.expires = Date.now() + ttl * 1000;\n }\n\n // Serialize to JSON\n const serialized = JSON.stringify(stored);\n\n // Store using backend\n backend.set(namespacedKey, serialized, options);\n\n // Emit event\n plugin.emit('storage:set', { key, value, backend: backendType });\n }\n\n /**\n * Get a value from storage\n */\n function get<T>(key: string, options?: StorageOptions): T | null {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n // Get from backend\n const serialized = backend.get(namespacedKey);\n\n if (!serialized) {\n return null;\n }\n\n try {\n // Deserialize from JSON\n const stored: StoredValue<T> = JSON.parse(serialized);\n\n // Check expiration\n if (isExpired(stored)) {\n // Remove expired value\n backend.remove(namespacedKey);\n plugin.emit('storage:expired', { key, backend: backendType });\n return null;\n }\n\n plugin.emit('storage:get', { key, backend: backendType });\n return stored.value;\n } catch (error) {\n console.warn('Failed to parse stored value:', error);\n // Remove corrupted value\n backend.remove(namespacedKey);\n return null;\n }\n }\n\n /**\n * Remove a value from storage\n */\n function remove(key: string, options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n backend.remove(namespacedKey);\n plugin.emit('storage:remove', { key, backend: backendType });\n }\n\n /**\n * Clear all values from storage\n *\n * If a namespace is provided, only clears values with that namespace prefix.\n * Otherwise, clears all values in the backend.\n */\n function clear(options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespace = options?.namespace;\n\n // If no namespace specified, clear everything\n if (!namespace) {\n backend.clear();\n plugin.emit('storage:clear', { backend: backendType });\n return;\n }\n\n // Namespace-specific clearing: iterate through all keys and remove matching ones\n if (backendType === 'localStorage' || backendType === 'sessionStorage') {\n const storage = backendType === 'localStorage' ? localStorage : sessionStorage;\n const prefix = `${namespace}:`;\n const keysToRemove: string[] = [];\n\n // Collect keys to remove\n for (let i = 0; i < storage.length; i++) {\n const key = storage.key(i);\n if (key?.startsWith(prefix)) {\n keysToRemove.push(key);\n }\n }\n\n // Remove them\n for (const key of keysToRemove) {\n backend.remove(key);\n }\n } else if (backendType === 'cookie') {\n // For cookies, parse document.cookie and remove matching keys\n const prefix = `${namespace}:`;\n const cookies = document.cookie.split(';');\n\n for (const cookie of cookies) {\n const trimmed = cookie.trim();\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n\n const encodedKey = trimmed.substring(0, eqIndex);\n const key = decodeURIComponent(encodedKey);\n\n if (key.startsWith(prefix)) {\n backend.remove(key);\n }\n }\n } else {\n // For memory backend, just clear everything (it's in-memory anyway)\n backend.clear();\n }\n\n plugin.emit('storage:clear', { backend: backendType, namespace });\n }\n\n /**\n * Check if a backend is supported\n */\n function isSupported(backendType?: StorageBackendType): boolean {\n const type = backendType ?? getBackendType();\n const backend = getBackend(type);\n return backend.isSupported();\n }\n\n // Expose public API\n plugin.expose({\n storage: {\n set,\n get,\n remove,\n clear,\n isSupported,\n },\n });\n\n // Log initialization\n instance.on('sdk:ready', () => {\n const backendType = getBackendType();\n const backend = getBackend(backendType);\n const supported = backend.isSupported();\n\n if (!supported) {\n console.warn(\n `Storage backend '${backendType}' is not supported, falling back to memory storage`\n );\n }\n });\n};\n\nexport { CookieBackend } from './backends/cookie';\nexport { LocalStorageBackend } from './backends/localStorage';\nexport { MemoryBackend } from './backends/memory';\nexport { SessionStorageBackend } from './backends/sessionStorage';\n// Export types and backends for testing\nexport type { StorageBackend, StorageBackendOptions } from './backends/types';\n","/**\n * Banner Plugin\n *\n * Renders banner experiences at the top or bottom of the page.\n * Auto-shows banners when experiences are evaluated.\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\nimport type { BannerContent, Decision, Experience } from '../types';\n\nexport interface BannerPluginConfig {\n banner?: {\n position?: 'top' | 'bottom';\n dismissable?: boolean;\n zIndex?: number;\n };\n}\n\nexport interface BannerPlugin {\n show(experience: Experience): void;\n remove(): void;\n isShowing(): boolean;\n}\n\n/**\n * Banner Plugin\n *\n * Automatically renders banner experiences when they are evaluated.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { bannerPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ banner: { position: 'top', dismissable: true } });\n * sdk.use(bannerPlugin);\n * ```\n */\nexport const bannerPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('banner');\n\n // Set defaults\n plugin.defaults({\n banner: {\n position: 'top',\n dismissable: true,\n zIndex: 10000,\n },\n });\n\n // Track multiple active banners by experience ID\n const activeBanners = new Map<string, HTMLElement>();\n\n /**\n * Create banner DOM element\n */\n function createBannerElement(experience: Experience): HTMLElement {\n const content = experience.content as BannerContent;\n // Allow per-experience position override, fall back to global config\n const position = content.position ?? config.get('banner.position') ?? 'top';\n const dismissable = content.dismissable ?? config.get('banner.dismissable') ?? true;\n const zIndex = config.get('banner.zIndex') ?? 10000;\n\n // Detect dark mode\n const isDarkMode = document.documentElement.classList.contains('dark');\n\n // Theme-aware colors - professional subtle style\n const bgColor = isDarkMode ? '#1f2937' : '#f9fafb';\n const textColor = isDarkMode ? '#f3f4f6' : '#111827';\n const borderColor = isDarkMode ? '#374151' : '#e5e7eb';\n const shadowColor = isDarkMode ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.05)';\n\n // Create banner container\n const banner = document.createElement('div');\n banner.setAttribute('data-experience-id', experience.id);\n\n // Add responsive media query styles\n const styleId = `banner-responsive-${experience.id}`;\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @media (max-width: 640px) {\n [data-experience-id=\"${experience.id}\"] {\n flex-direction: column !important;\n align-items: flex-start !important;\n }\n [data-experience-id=\"${experience.id}\"] > div:last-child {\n width: 100%;\n flex-direction: column !important;\n }\n [data-experience-id=\"${experience.id}\"] button {\n width: 100%;\n }\n }\n `;\n document.head.appendChild(style);\n }\n\n banner.style.cssText = `\n position: fixed;\n ${position}: 0;\n left: 0;\n right: 0;\n background: ${bgColor};\n color: ${textColor};\n padding: 16px 20px;\n border-${position === 'top' ? 'bottom' : 'top'}: 1px solid ${borderColor};\n box-shadow: 0 ${position === 'top' ? '1' : '-1'}px 3px 0 ${shadowColor};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n z-index: ${zIndex};\n display: flex;\n align-items: center;\n justify-content: space-between;\n box-sizing: border-box;\n `;\n\n // Create content container\n const contentDiv = document.createElement('div');\n contentDiv.style.cssText = 'flex: 1; margin-right: 20px;';\n\n // Add title if present\n if (content.title) {\n const title = document.createElement('div');\n title.textContent = content.title;\n title.style.cssText = 'font-weight: 600; margin-bottom: 4px;';\n contentDiv.appendChild(title);\n }\n\n // Add message\n const message = document.createElement('div');\n message.textContent = content.message;\n contentDiv.appendChild(message);\n\n banner.appendChild(contentDiv);\n\n // Create button container for actions and/or dismiss\n const buttonContainer = document.createElement('div');\n buttonContainer.style.cssText = `\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n `;\n\n // Helper function to create button with variant styling\n function createButton(buttonConfig: {\n text: string;\n action?: string;\n url?: string;\n variant?: 'primary' | 'secondary' | 'link';\n metadata?: Record<string, unknown>;\n }): HTMLButtonElement {\n const button = document.createElement('button');\n button.textContent = buttonConfig.text;\n\n const variant = buttonConfig.variant || 'primary';\n\n // Variant-based styling\n let bg: string, hoverBg: string, textColor: string, border: string;\n\n if (variant === 'primary') {\n bg = isDarkMode ? '#3b82f6' : '#2563eb';\n hoverBg = isDarkMode ? '#2563eb' : '#1d4ed8';\n textColor = '#ffffff';\n border = 'none';\n } else if (variant === 'secondary') {\n bg = isDarkMode ? '#374151' : '#ffffff';\n hoverBg = isDarkMode ? '#4b5563' : '#f9fafb';\n textColor = isDarkMode ? '#f3f4f6' : '#374151';\n border = isDarkMode ? '1px solid #4b5563' : '1px solid #d1d5db';\n } else {\n // 'link'\n bg = 'transparent';\n hoverBg = isDarkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.05)';\n textColor = isDarkMode ? '#93c5fd' : '#2563eb';\n border = 'none';\n }\n\n button.style.cssText = `\n background: ${bg};\n border: ${border};\n color: ${textColor};\n padding: ${variant === 'link' ? '4px 8px' : '8px 16px'};\n font-size: 14px;\n font-weight: ${variant === 'link' ? '400' : '500'};\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n text-decoration: ${variant === 'link' ? 'underline' : 'none'};\n `;\n\n button.addEventListener('mouseenter', () => {\n button.style.background = hoverBg;\n });\n\n button.addEventListener('mouseleave', () => {\n button.style.background = bg;\n });\n\n button.addEventListener('click', () => {\n // Emit action event\n instance.emit('experiences:action', {\n experienceId: experience.id,\n type: 'banner',\n action: buttonConfig.action,\n url: buttonConfig.url,\n metadata: buttonConfig.metadata,\n variant: variant,\n timestamp: Date.now(),\n });\n\n // Navigate if URL provided\n if (buttonConfig.url) {\n window.location.href = buttonConfig.url;\n }\n });\n\n return button;\n }\n\n // Add buttons from buttons array\n if (content.buttons && content.buttons.length > 0) {\n content.buttons.forEach((buttonConfig) => {\n const button = createButton(buttonConfig);\n buttonContainer.appendChild(button);\n });\n }\n\n // Add dismiss button if dismissable\n if (dismissable) {\n const closeButton = document.createElement('button');\n closeButton.innerHTML = '&times;';\n closeButton.setAttribute('aria-label', 'Close banner');\n\n const closeColor = isDarkMode ? '#9ca3af' : '#6b7280';\n\n closeButton.style.cssText = `\n background: transparent;\n border: none;\n color: ${closeColor};\n font-size: 24px;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n margin: 0;\n opacity: 0.7;\n transition: opacity 0.2s;\n `;\n\n closeButton.addEventListener('mouseenter', () => {\n closeButton.style.opacity = '1';\n });\n\n closeButton.addEventListener('mouseleave', () => {\n closeButton.style.opacity = '0.7';\n });\n\n closeButton.addEventListener('click', () => {\n remove(experience.id);\n instance.emit('experiences:dismissed', {\n experienceId: experience.id,\n type: 'banner',\n });\n });\n\n buttonContainer.appendChild(closeButton);\n }\n\n banner.appendChild(buttonContainer);\n\n return banner;\n }\n\n /**\n * Show a banner experience\n */\n function show(experience: Experience): void {\n // If banner already showing for this experience, skip\n if (activeBanners.has(experience.id)) {\n return;\n }\n\n // Only show if we're in a browser environment\n if (typeof document === 'undefined') {\n return;\n }\n\n const banner = createBannerElement(experience);\n document.body.appendChild(banner);\n activeBanners.set(experience.id, banner);\n\n instance.emit('experiences:shown', {\n experienceId: experience.id,\n type: 'banner',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Remove a banner by experience ID (or all if no ID provided)\n */\n function remove(experienceId?: string): void {\n if (experienceId) {\n // Remove specific banner\n const banner = activeBanners.get(experienceId);\n if (banner?.parentNode) {\n banner.parentNode.removeChild(banner);\n }\n activeBanners.delete(experienceId);\n } else {\n // Remove all banners\n for (const [id, banner] of activeBanners.entries()) {\n if (banner?.parentNode) {\n banner.parentNode.removeChild(banner);\n }\n activeBanners.delete(id);\n }\n }\n }\n\n /**\n * Check if any banner is currently showing\n */\n function isShowing(): boolean {\n return activeBanners.size > 0;\n }\n\n // Expose banner API\n plugin.expose({\n banner: {\n show,\n remove,\n isShowing,\n },\n });\n\n // Auto-show banner on experiences:evaluated event\n instance.on('experiences:evaluated', (payload: unknown) => {\n // Handle both single decision and array of decisions\n // evaluate() emits: { decision, experience }\n // evaluateAll() emits: [{ decision, experience }, ...]\n const items = Array.isArray(payload) ? payload : [payload];\n\n for (const item of items) {\n // Item is { decision, experience }\n const typedItem = item as { decision?: Decision; experience?: Experience };\n const decision = typedItem.decision;\n const experience = typedItem.experience;\n\n // Only handle banner-type experiences\n if (experience?.type === 'banner') {\n if (decision?.show) {\n show(experience);\n } else if (experience.id && activeBanners.has(experience.id)) {\n // Hide specific banner if decision says don't show\n remove(experience.id);\n }\n }\n }\n });\n\n // Cleanup on destroy\n instance.on('sdk:destroy', () => {\n remove();\n });\n};\n","/**\n * Debug Plugin\n *\n * Emits structured debug events to window and optionally logs to console.\n * Useful for debugging and Chrome extension integration.\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\n\nexport interface DebugPluginConfig {\n debug?: {\n enabled?: boolean;\n console?: boolean;\n window?: boolean;\n };\n}\n\nexport interface DebugPlugin {\n log(message: string, data?: unknown): void;\n isEnabled(): boolean;\n}\n\n/**\n * Debug Plugin\n *\n * Listens to all SDK events and emits them as window events for debugging.\n * Also optionally logs to console.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { debugPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ debug: { enabled: true, console: true } });\n * sdk.use(debugPlugin);\n * ```\n */\nexport const debugPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('debug');\n\n // Set defaults\n plugin.defaults({\n debug: {\n enabled: false,\n console: false,\n window: true,\n },\n });\n\n // Helper to check if debug is enabled\n const isEnabled = (): boolean => config.get('debug.enabled') ?? false;\n const shouldLogConsole = (): boolean => config.get('debug.console') ?? false;\n const shouldEmitWindow = (): boolean => config.get('debug.window') ?? true;\n\n // Log function\n const log = (message: string, data?: unknown): void => {\n if (!isEnabled()) return;\n\n const timestamp = new Date().toISOString();\n const logData = {\n timestamp,\n message,\n data,\n };\n\n // Console logging\n if (shouldLogConsole()) {\n console.log(`[experiences] ${message}`, data || '');\n }\n\n // Window event emission\n if (shouldEmitWindow() && typeof window !== 'undefined') {\n const event = new CustomEvent('experience-sdk:debug', {\n detail: logData,\n });\n window.dispatchEvent(event);\n }\n };\n\n // Expose debug API\n plugin.expose({\n debug: {\n log,\n isEnabled,\n },\n });\n\n // If debug is enabled, listen to all events\n if (isEnabled()) {\n // Listen to experiences:* events\n instance.on('experiences:ready', () => {\n if (!isEnabled()) return;\n log('SDK initialized and ready');\n });\n\n instance.on('experiences:registered', (payload) => {\n if (!isEnabled()) return;\n log('Experience registered', payload);\n });\n\n instance.on('experiences:evaluated', (payload) => {\n if (!isEnabled()) return;\n log('Experience evaluated', payload);\n });\n }\n};\n","/**\n * Frequency Capping Plugin\n *\n * Tracks experience impressions and enforces frequency caps.\n * Uses sdk-kit's storage plugin for persistence.\n */\n\nimport type { PluginFunction, SDK } from '@lytics/sdk-kit';\nimport { type StoragePlugin, storagePlugin } from '@lytics/sdk-kit-plugins';\nimport type { Decision, TraceStep } from '../types';\n\nexport interface FrequencyPluginConfig {\n frequency?: {\n enabled?: boolean;\n namespace?: string;\n };\n}\n\nexport interface FrequencyPlugin {\n getImpressionCount(experienceId: string): number;\n hasReachedCap(experienceId: string, max: number, per: 'session' | 'day' | 'week'): boolean;\n recordImpression(experienceId: string): void;\n}\n\ninterface ImpressionData {\n count: number;\n lastImpression: number;\n impressions: number[];\n per?: 'session' | 'day' | 'week'; // Track which storage type this uses\n}\n\n/**\n * Frequency Capping Plugin\n *\n * Automatically tracks impressions and enforces frequency caps.\n * Requires storage plugin for persistence.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ frequency: { enabled: true } });\n * sdk.use(frequencyPlugin);\n * ```\n */\nexport const frequencyPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('frequency');\n\n // Set defaults\n plugin.defaults({\n frequency: {\n enabled: true,\n namespace: 'experiences:frequency',\n },\n });\n\n // Track experience frequency configs\n const experienceFrequencyMap = new Map<string, 'session' | 'day' | 'week'>();\n\n // Auto-load storage plugin if not already loaded\n if (!(instance as SDK & { storage?: StoragePlugin }).storage) {\n instance.use(storagePlugin);\n }\n\n const isEnabled = (): boolean => config.get('frequency.enabled') ?? true;\n const getNamespace = (): string => config.get('frequency.namespace') ?? 'experiences:frequency';\n\n // Helper to get the right storage backend based on frequency type\n const getStorageBackend = (per: 'session' | 'day' | 'week'): Storage => {\n return per === 'session' ? sessionStorage : localStorage;\n };\n\n // Helper to get storage key\n const getStorageKey = (experienceId: string): string => {\n return `${getNamespace()}:${experienceId}`;\n };\n\n // Helper to get impression data\n const getImpressionData = (\n experienceId: string,\n per: 'session' | 'day' | 'week'\n ): ImpressionData => {\n const storage = getStorageBackend(per);\n const key = getStorageKey(experienceId);\n const raw = storage.getItem(key);\n\n if (!raw) {\n return {\n count: 0,\n lastImpression: 0,\n impressions: [],\n per,\n };\n }\n\n try {\n return JSON.parse(raw) as ImpressionData;\n } catch {\n return {\n count: 0,\n lastImpression: 0,\n impressions: [],\n per,\n };\n }\n };\n\n // Helper to save impression data\n const saveImpressionData = (experienceId: string, data: ImpressionData): void => {\n const per = data.per || 'session'; // Default to session if not specified\n const storage = getStorageBackend(per);\n const key = getStorageKey(experienceId);\n storage.setItem(key, JSON.stringify(data));\n };\n\n // Get time window in milliseconds\n const getTimeWindow = (per: 'session' | 'day' | 'week'): number => {\n switch (per) {\n case 'session':\n return Number.POSITIVE_INFINITY; // Session storage handles this\n case 'day':\n return 24 * 60 * 60 * 1000; // 24 hours\n case 'week':\n return 7 * 24 * 60 * 60 * 1000; // 7 days\n }\n };\n\n /**\n * Get impression count for an experience\n */\n const getImpressionCount = (\n experienceId: string,\n per: 'session' | 'day' | 'week' = 'session'\n ): number => {\n if (!isEnabled()) return 0;\n const data = getImpressionData(experienceId, per);\n return data.count;\n };\n\n /**\n * Check if an experience has reached its frequency cap\n */\n const hasReachedCap = (\n experienceId: string,\n max: number,\n per: 'session' | 'day' | 'week'\n ): boolean => {\n if (!isEnabled()) return false;\n\n const data = getImpressionData(experienceId, per);\n const timeWindow = getTimeWindow(per);\n const now = Date.now();\n\n // For session caps, just check total count\n if (per === 'session') {\n return data.count >= max;\n }\n\n // For time-based caps, count impressions within the window\n const recentImpressions = data.impressions.filter((timestamp) => now - timestamp < timeWindow);\n\n return recentImpressions.length >= max;\n };\n\n /**\n * Record an impression for an experience\n */\n const recordImpression = (\n experienceId: string,\n per: 'session' | 'day' | 'week' = 'session'\n ): void => {\n if (!isEnabled()) return;\n\n const data = getImpressionData(experienceId, per);\n const now = Date.now();\n\n // Update count and add timestamp\n data.count += 1;\n data.lastImpression = now;\n data.impressions.push(now);\n data.per = per; // Store the frequency type\n\n // Keep only recent impressions (last 7 days)\n const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;\n data.impressions = data.impressions.filter((ts) => ts > sevenDaysAgo);\n\n // Save updated data\n saveImpressionData(experienceId, data);\n\n // Emit event\n instance.emit('experiences:impression-recorded', {\n experienceId,\n count: data.count,\n timestamp: now,\n });\n };\n\n // Expose frequency API\n plugin.expose({\n frequency: {\n getImpressionCount,\n hasReachedCap,\n recordImpression,\n // Internal method to register experience frequency config\n _registerExperience: (experienceId: string, per: 'session' | 'day' | 'week') => {\n experienceFrequencyMap.set(experienceId, per);\n },\n },\n });\n\n // Listen to evaluation events and record impressions\n if (isEnabled()) {\n instance.on('experiences:evaluated', (payload: unknown) => {\n // Handle both single decision and array of decisions\n // evaluate() emits: { decision, experience }\n // evaluateAll() emits: [{ decision, experience }, ...]\n const items = Array.isArray(payload) ? payload : [payload];\n\n for (const item of items) {\n // Item is { decision, experience }\n const decision = (item as { decision?: Decision }).decision;\n\n // Only record if experience was shown\n if (decision?.show && decision.experienceId) {\n // Try to get the 'per' value from our map, fall back to checking the input in trace\n let per: 'session' | 'day' | 'week' =\n experienceFrequencyMap.get(decision.experienceId) || 'session';\n\n // If not in map, try to infer from the decision trace\n if (!experienceFrequencyMap.has(decision.experienceId)) {\n const freqStep = decision.trace.find(\n (t: TraceStep) => t.step === 'check-frequency-cap'\n );\n if (freqStep?.input && typeof freqStep.input === 'object' && 'per' in freqStep.input) {\n per = (freqStep.input as { per: 'session' | 'day' | 'week' }).per;\n // Cache it for next time\n experienceFrequencyMap.set(decision.experienceId, per);\n }\n }\n\n recordImpression(decision.experienceId, per);\n }\n }\n });\n }\n};\n","/**\n * Deep merge utility with \"underwrite\" pattern.\n *\n * Recursively merges source into target, where **target values take precedence**.\n * This is the opposite of typical deep merge where source wins.\n *\n * This \"underwrite\" pattern is used for config defaults:\n * - User config (target) always wins\n * - Defaults (source) only fill in missing values\n *\n * @param target - Target object (takes precedence)\n * @param source - Source object (provides defaults)\n * @returns New merged object (does not mutate inputs)\n *\n * @example\n * ```typescript\n * const userConfig = { api: { timeout: 5000 } };\n * const defaults = { api: { timeout: 3000, retries: 3 }, debug: false };\n *\n * const result = deepMerge(target, source);\n * // Result: {\n * // api: { timeout: 5000, retries: 3 }, // timeout from user, retries from defaults\n * // debug: false // debug from defaults\n * // }\n * ```\n */\nexport function deepMerge(\n target: Record<string, any>,\n source: Record<string, any>\n): Record<string, any> {\n // Create a new object to avoid mutation\n const result: Record<string, any> = { ...target };\n\n for (const key in source) {\n if (!Object.hasOwn(source, key)) {\n continue;\n }\n\n const sourceValue = source[key];\n const targetValue = result[key];\n\n // If target has no value for this key, use source value\n if (targetValue === undefined) {\n result[key] = sourceValue;\n continue;\n }\n\n // If both are plain objects, recursively merge\n if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n }\n\n // Otherwise, target value wins (underwrite pattern)\n // result[key] is already set from { ...target }\n }\n\n return result;\n}\n\n/**\n * Check if value is a plain object (not array, null, Date, etc.)\n *\n * @param value - Value to check\n * @returns True if value is a plain object\n * @private\n */\nfunction isPlainObject(value: any): value is Record<string, any> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n // Check if it's a plain object (not Array, Date, RegExp, etc.)\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n","/**\n * Configuration management with dot-notation paths and underwrite pattern.\n *\n * The Config class manages SDK configuration with support for:\n * - Dot-notation paths for nested access (`'my.plugin.setting'`)\n * - Underwrite pattern for defaults (existing values take precedence)\n * - Required plugin tracking\n * - Immutable getAll() for safe access\n *\n * @example\n * ```typescript\n * const config = new Config({ api: { timeout: 5000 } });\n *\n * // Set defaults (won't overwrite existing timeout)\n * config.defaults({ api: { timeout: 3000, retries: 3 } });\n *\n * // Get with dot-notation\n * config.get('api.timeout'); // 5000\n * config.get('api.retries'); // 3\n *\n * // Set values\n * config.set('api.baseUrl', 'https://api.example.com');\n * ```\n */\n\nimport { deepMerge } from '../util/deep-merge';\n\nexport class Config {\n private data: Record<string, any> = {};\n private required = new Set<string>();\n\n /**\n * Create a new Config instance.\n *\n * @param initialConfig - Initial configuration object\n */\n constructor(initialConfig: Record<string, any> = {}) {\n // Deep copy to prevent external mutation\n this.data = JSON.parse(JSON.stringify(initialConfig));\n }\n\n /**\n * Set default configuration values using underwrite pattern.\n *\n * Existing configuration values always take precedence over defaults.\n * This allows plugins to provide defaults without overwriting user config.\n *\n * @param config - Default configuration object\n *\n * @example\n * ```typescript\n * // User provided config\n * const config = new Config({ api: { timeout: 10000 } });\n *\n * // Plugin sets defaults\n * config.defaults({\n * api: { timeout: 3000, retries: 3 },\n * debug: false\n * });\n *\n * // Result: { api: { timeout: 10000, retries: 3 }, debug: false }\n * // User's timeout (10000) wins over default (3000)\n * ```\n */\n defaults(config: Record<string, any>): void {\n // Use underwrite pattern: existing config (target) wins over defaults (source)\n this.data = deepMerge(this.data, config);\n }\n\n /**\n * Merge configuration values (new values override existing).\n *\n * New configuration values take precedence over existing values.\n * This is the opposite of defaults() and is used when user provides new config.\n *\n * @param config - Configuration object to merge\n *\n * @example\n * ```typescript\n * const config = new Config({ api: { timeout: 3000 } });\n *\n * // User provides new config\n * config.merge({ api: { timeout: 10000, retries: 3 } });\n *\n * // Result: { api: { timeout: 10000, retries: 3 } }\n * // New timeout (10000) wins over existing (3000)\n * ```\n */\n merge(config: Record<string, any>): void {\n // Regular merge: new config (source) wins over existing (target)\n this.data = deepMerge(config, this.data);\n }\n\n /**\n * Get a configuration value by dot-notation path.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @returns Configuration value or undefined if not found\n *\n * @example\n * ```typescript\n * config.get('api.timeout'); // 5000\n * config.get('api.retries'); // 3\n * config.get('nonexistent.path'); // undefined\n * config.get<number>('api.timeout'); // Type-safe access\n * ```\n */\n get<T = any>(path: string): T {\n const keys = path.split('.');\n let current: any = this.data;\n\n for (const key of keys) {\n if (current == null) {\n return undefined as T;\n }\n current = current[key];\n }\n\n return current as T;\n }\n\n /**\n * Set a configuration value by dot-notation path.\n *\n * Creates intermediate objects as needed.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @param value - Value to set\n *\n * @example\n * ```typescript\n * config.set('api.timeout', 5000);\n * config.set('api.headers.authorization', 'Bearer token');\n * config.set('deeply.nested.value', 42);\n * ```\n */\n set(path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop();\n if (!lastKey) return; // Guard against empty path\n\n let current: any = this.data;\n\n // Create intermediate objects\n for (const key of keys) {\n if (current[key] == null || typeof current[key] !== 'object') {\n current[key] = {};\n }\n current = current[key];\n }\n\n current[lastKey] = value;\n }\n\n /**\n * Mark a plugin namespace as required.\n *\n * Required plugins must be properly enabled for the SDK to function.\n *\n * @param namespace - Plugin namespace to mark as required\n *\n * @example\n * ```typescript\n * config.markRequired('analytics');\n * config.isRequired('analytics'); // true\n * ```\n */\n markRequired(namespace?: string): void {\n if (namespace !== undefined && namespace !== null) {\n this.required.add(namespace);\n }\n }\n\n /**\n * Check if a plugin namespace is marked as required.\n *\n * @param namespace - Plugin namespace to check\n * @returns True if the namespace is required\n */\n isRequired(namespace: string): boolean {\n return this.required.has(namespace);\n }\n\n /**\n * Get all configuration as an immutable copy.\n *\n * Returns a deep copy to prevent external mutation of config.\n *\n * @returns Copy of the entire configuration object\n *\n * @example\n * ```typescript\n * const allConfig = config.getAll();\n * allConfig.api = {}; // Does not affect internal config\n * ```\n */\n getAll(): Record<string, any> {\n // Deep copy to prevent nested mutation\n return JSON.parse(JSON.stringify(this.data));\n }\n}\n","/**\n * Event Emitter with wildcard pattern matching support.\n *\n * Supports wildcard patterns for event subscriptions:\n * - Exact match: `'widget.show'` matches `'widget.show'`\n * - Wildcard suffix: `'widget.*'` matches `'widget.show'`, `'widget.hide'`, etc.\n * - Wildcard prefix: `'*.show'` matches `'widget.show'`, `'modal.show'`, etc.\n * - Match all: `'*'` matches all events\n *\n * Uses regex compilation for efficient pattern matching.\n */\n\n/**\n * Subscription entry storing the pattern and handler.\n */\ninterface Subscription {\n pattern: string;\n compiledPattern: RegExp;\n handler: (...args: any[]) => void;\n}\n\nexport class Emitter {\n private subscriptions: Subscription[] = [];\n\n /**\n * Subscribe to an event or pattern.\n *\n * @param event - Event name or wildcard pattern\n * @param handler - Event handler function\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const emitter = new Emitter();\n *\n * // Exact match\n * emitter.on('user.login', (data) => console.log('Login:', data));\n *\n * // Wildcard patterns\n * emitter.on('user.*', (data) => console.log('User event:', data));\n * emitter.on('*.error', (data) => console.log('Error:', data));\n * emitter.on('*', (data) => console.log('Any event:', data));\n *\n * // Unsubscribe\n * const unsub = emitter.on('test', handler);\n * unsub();\n * ```\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n if (typeof handler !== 'function') {\n throw new TypeError('handler must be a function');\n }\n\n const subscription: Subscription = {\n pattern: event,\n compiledPattern: this.compilePattern(event),\n handler,\n };\n\n this.subscriptions.push(subscription);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Unsubscribe from an event or pattern.\n *\n * @param event - Event name or pattern to unsubscribe from\n * @param handler - Handler function to remove\n */\n off(event: string, handler: (...args: any[]) => void): void {\n this.subscriptions = this.subscriptions.filter(\n (sub) => !(sub.pattern === event && sub.handler === handler)\n );\n }\n\n /**\n * Emit an event to all matching subscribers.\n *\n * Notifies all handlers whose patterns match the event name.\n * Handlers are called with the provided arguments.\n * Errors in handlers are caught and logged to prevent breaking the event flow.\n *\n * @param event - Event name to emit\n * @param args - Arguments to pass to handlers\n *\n * @example\n * ```typescript\n * emitter.emit('user.login', { userId: '123' });\n * emitter.emit('widget.show', { id: 'modal-1' }, { animate: true });\n * ```\n */\n emit(event: string, ...args: any[]): void {\n for (const subscription of this.subscriptions) {\n if (subscription.compiledPattern.test(event)) {\n try {\n subscription.handler(...args);\n } catch (err) {\n console.error(`Error in event handler for \"${event}\":`, err);\n }\n }\n }\n }\n\n /**\n * Remove all event listeners.\n *\n * Useful for cleanup when destroying the SDK instance.\n */\n removeAllListeners(): void {\n this.subscriptions = [];\n }\n\n /**\n * Compile a pattern string into a RegExp for matching.\n *\n * Converts wildcard patterns into regular expressions:\n * - `widget.*` → `/^widget\\.(.*?)$/`\n * - `*.show` → `/^(.*?)\\.show$/`\n * - `*` → `/^(.*?)$/`\n *\n * @param pattern - Pattern string with optional wildcards\n * @returns Compiled RegExp for matching event names\n * @private\n */\n private compilePattern(pattern: string): RegExp {\n // Escape all regex special characters\n const escaped = this.escapeRegExp(pattern);\n // Replace escaped asterisks with wildcard capture groups\n const withWildcards = escaped.replace(/\\\\\\*/g, '(.*?)');\n // Anchor to start and end\n return new RegExp(`^${withWildcards}$`);\n }\n\n /**\n * Escape special regex characters in a string.\n *\n * @param str - String to escape\n * @returns Escaped string safe for use in RegExp\n * @private\n */\n private escapeRegExp(str: string): string {\n return str.replace(/[\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n}\n","/**\n * Expose capability for adding plugin methods to SDK instance.\n *\n * Plugins use this to add public API methods that users can call.\n * Methods are merged directly onto the SDK instance.\n *\n * @example\n * ```typescript\n * const expose = new Expose(sdkInstance);\n * expose.expose({\n * track(event: string) {\n * console.log('Tracking:', event);\n * }\n * });\n * // Now: sdk.track('page_view');\n * ```\n */\n\nexport class Expose {\n private sdk: any;\n\n /**\n * Create an Expose instance.\n *\n * @param sdk - SDK instance to expose methods on\n */\n constructor(sdk: any) {\n this.sdk = sdk;\n }\n\n /**\n * Expose methods on the SDK instance.\n *\n * Merges the provided methods object onto the SDK instance,\n * making them available as `sdk.methodName()`.\n *\n * @param api - Object containing methods to expose\n *\n * @example\n * ```typescript\n * expose.expose({\n * track(event: string, properties?: any) {\n * // Track event\n * },\n * identify(userId: string) {\n * // Identify user\n * }\n * });\n *\n * // Available as:\n * // sdk.track('page_view', { path: '/home' });\n * // sdk.identify('user-123');\n * ```\n */\n expose(api: Record<string, any>): void {\n Object.assign(this.sdk, api);\n }\n}\n","/**\n * Namespace capability for plugin identification.\n *\n * Each plugin must claim a unique namespace to identify itself.\n * Namespaces are used for config scoping and event namespacing.\n *\n * @example\n * ```typescript\n * const namespace = new Namespace();\n * namespace.ns('analytics.tracking');\n * console.log(namespace.name); // 'analytics.tracking'\n * ```\n */\n\nexport class Namespace {\n /**\n * The plugin's namespace.\n * Set via the `ns()` method, can only be set once.\n */\n name: string = '';\n\n /**\n * Set the plugin's namespace.\n *\n * Can only be called once per instance. Attempting to set it again throws an error.\n *\n * @param namespace - Dot-notation namespace (e.g., 'analytics.tracking')\n * @throws Error if namespace is already set\n *\n * @example\n * ```typescript\n * const ns = new Namespace();\n * ns.ns('my.plugin'); // Success\n * ns.ns('other.plugin'); // Throws Error\n * ```\n */\n ns(namespace: string): void {\n if (this.name) {\n throw new Error(\n `Namespace already set to \"${this.name}\". Cannot reassign to \"${namespace}\".`\n );\n }\n this.name = namespace;\n }\n}\n","/**\n * Main SDK class\n *\n * Composes all capabilities and provides the plugin registration system.\n * Follows functional plugin architecture with capability injection.\n */\n\nimport { Config } from './capabilities/config';\nimport { Emitter } from './capabilities/emitter';\nimport { Expose } from './capabilities/expose';\nimport { Namespace } from './capabilities/namespace';\nimport type { Plugin, PluginFunction, SDKConfig } from './types';\n\n/**\n * SDK - Main SDK class for building JavaScript SDKs\n *\n * @example\n * ```typescript\n * const sdk = new SDK({ name: 'my-sdk' });\n *\n * sdk.use((plugin, instance, config) => {\n * plugin.ns('my.plugin');\n * plugin.defaults({ my: { setting: 'value' } });\n * plugin.expose({\n * track(event: string) {\n * console.log('Tracking:', event);\n * }\n * });\n * });\n *\n * await sdk.init();\n * sdk.track('page_view');\n * ```\n */\nexport class SDK {\n /**\n * Configuration instance\n * @private\n */\n private configInstance: Config;\n\n /**\n * Event emitter instance\n * @private\n */\n private emitter: Emitter;\n\n /**\n * Registered plugins by namespace\n * @private\n */\n private plugins: Map<string, { namespace: Namespace; plugin: Plugin }> = new Map();\n\n /**\n * Initialization state\n * @private\n */\n private isInitialized = false;\n\n /**\n * Create a new SDK instance.\n *\n * @param config - Initial SDK configuration\n *\n * @example\n * ```typescript\n * const sdk = new SDK({\n * name: 'my-sdk',\n * api: {\n * endpoint: 'https://api.example.com',\n * timeout: 5000\n * }\n * });\n * ```\n */\n constructor(config: SDKConfig = {}) {\n this.emitter = new Emitter();\n this.configInstance = new Config(config);\n }\n\n /**\n * Register a plugin.\n *\n * Plugins receive capability-injected objects and can extend the SDK.\n * Supports method chaining.\n *\n * @param pluginFn - Plugin function\n * @returns this - For method chaining\n *\n * @example\n * ```typescript\n * sdk\n * .use(analyticsPlugin)\n * .use(trackingPlugin)\n * .init();\n * ```\n */\n use(pluginFn: PluginFunction): this {\n // Create capability instances for this plugin\n const namespace = new Namespace();\n const expose = new Expose(this);\n\n // Compose Plugin object with all capabilities\n const plugin: Plugin = {\n // Namespace capability\n ns: namespace.ns.bind(namespace),\n\n // Config capabilities\n defaults: this.configInstance.defaults.bind(this.configInstance),\n\n // Emitter capabilities\n on: this.emitter.on.bind(this.emitter),\n off: this.emitter.off.bind(this.emitter),\n emit: this.emitter.emit.bind(this.emitter),\n\n // Expose capability\n expose: expose.expose.bind(expose),\n\n // Requirer capability\n mustEnable: () => {\n if (namespace.name) {\n this.configInstance.markRequired(namespace.name);\n }\n },\n };\n\n // Execute plugin function with capability injection\n pluginFn(plugin, this, this.configInstance);\n\n // Store plugin by namespace\n if (namespace.name) {\n this.plugins.set(namespace.name, { namespace, plugin });\n }\n\n return this;\n }\n\n /**\n * Initialize the SDK.\n *\n * Emits `sdk:init` event before initialization and `sdk:ready` after.\n * Idempotent - can be called multiple times safely.\n *\n * @param config - Optional configuration to merge with existing config\n * @returns Promise that resolves when initialization is complete\n *\n * @example\n * ```typescript\n * sdk.on('sdk:ready', () => {\n * console.log('SDK is ready!');\n * });\n *\n * await sdk.init({ api: { timeout: 5000 } });\n * ```\n */\n async init(config?: SDKConfig): Promise<void> {\n if (this.isInitialized) {\n console.warn('SDK already initialized');\n return;\n }\n\n // Merge config if provided (new values override defaults)\n if (config) {\n this.configInstance.merge(config);\n }\n\n // Emit init event (plugins can listen for this)\n this.emitter.emit('sdk:init');\n\n // Check for required plugins\n const requiredNamespaces = Array.from(this.plugins.keys()).filter((ns) =>\n this.configInstance.isRequired(ns)\n );\n\n for (const ns of requiredNamespaces) {\n if (!this.plugins.has(ns)) {\n throw new Error(`Required plugin \"${ns}\" is not registered`);\n }\n }\n\n this.isInitialized = true;\n\n // Emit ready event\n this.emitter.emit('sdk:ready');\n }\n\n /**\n * Destroy the SDK.\n *\n * Emits `sdk:destroy` event, clears all plugins, and removes all event listeners.\n *\n * @returns Promise that resolves when destruction is complete\n *\n * @example\n * ```typescript\n * await sdk.destroy();\n * ```\n */\n async destroy(): Promise<void> {\n // Emit destroy event (plugins can listen for cleanup)\n this.emitter.emit('sdk:destroy');\n\n // Clear plugins\n this.plugins.clear();\n\n // Remove all event listeners\n this.emitter.removeAllListeners();\n\n this.isInitialized = false;\n }\n\n /**\n * Get a configuration value by path.\n *\n * Delegates to the Config capability.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @returns Configuration value\n *\n * @example\n * ```typescript\n * const timeout = sdk.get('api.timeout');\n * const nested = sdk.get('my.plugin.setting');\n * ```\n */\n get<T = any>(path: string): T {\n return this.configInstance.get(path);\n }\n\n /**\n * Set a configuration value by path.\n *\n * Delegates to the Config capability.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @param value - Value to set\n *\n * @example\n * ```typescript\n * sdk.set('api.timeout', 10000);\n * sdk.set('my.plugin.enabled', true);\n * ```\n */\n set(path: string, value: any): void {\n this.configInstance.set(path, value);\n }\n\n /**\n * Subscribe to an event.\n *\n * Delegates to the Emitter capability. Supports wildcard patterns.\n *\n * @param event - Event name or pattern (e.g., 'track:*')\n * @param handler - Event handler function\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = sdk.on('track:page', (data) => {\n * console.log('Page tracked:', data);\n * });\n *\n * // Later...\n * unsubscribe();\n * ```\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n return this.emitter.on(event, handler);\n }\n\n /**\n * Unsubscribe from an event.\n *\n * Delegates to the Emitter capability.\n *\n * @param event - Event name\n * @param handler - Event handler function to remove\n *\n * @example\n * ```typescript\n * const handler = () => console.log('ready');\n * sdk.on('sdk:ready', handler);\n * sdk.off('sdk:ready', handler);\n * ```\n */\n off(event: string, handler: (...args: any[]) => void): void {\n this.emitter.off(event, handler);\n }\n\n /**\n * Emit an event.\n *\n * Delegates to the Emitter capability.\n *\n * @param event - Event name\n * @param args - Event arguments\n *\n * @example\n * ```typescript\n * sdk.emit('custom:event', { data: 'value' });\n * ```\n */\n emit(event: string, ...args: any[]): void {\n this.emitter.emit(event, ...args);\n }\n\n /**\n * Get all configuration as an immutable copy.\n *\n * Delegates to the Config capability.\n *\n * @returns Copy of the entire configuration object\n *\n * @example\n * ```typescript\n * const allConfig = sdk.getAll();\n * console.log(allConfig);\n * ```\n */\n getAll(): Record<string, any> {\n return this.configInstance.getAll();\n }\n\n /**\n * Check if SDK is initialized.\n *\n * @returns true if initialized, false otherwise\n *\n * @example\n * ```typescript\n * if (sdk.isReady()) {\n * sdk.track('event');\n * }\n * ```\n */\n isReady(): boolean {\n return this.isInitialized;\n }\n}\n","import { SDK } from '@lytics/sdk-kit';\nimport { storagePlugin } from '@lytics/sdk-kit-plugins';\nimport { bannerPlugin, debugPlugin, frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';\nimport type {\n Context,\n Decision,\n Experience,\n ExperienceConfig,\n RuntimeState,\n TraceStep,\n UrlRule,\n} from './types';\n\n/**\n * Experience Runtime\n *\n * Core class that manages experience registration and evaluation.\n * Built on @lytics/sdk-kit for plugin system and lifecycle management.\n *\n * Design principles:\n * - Pure functions for evaluation logic (easy to test)\n * - Event-driven architecture (extensible via plugins)\n * - Explainability-first (every decision has reasons)\n */\nexport class ExperienceRuntime {\n private sdk: SDK;\n private experiences: Map<string, Experience> = new Map();\n private decisions: Decision[] = [];\n private initialized = false;\n private destroyed = false;\n\n constructor(config: ExperienceConfig = {}) {\n // Create SDK instance\n this.sdk = new SDK({\n name: 'experience-sdk',\n ...config,\n });\n\n // Auto-register plugins\n this.sdk.use(storagePlugin);\n this.sdk.use(debugPlugin);\n this.sdk.use(frequencyPlugin);\n this.sdk.use(bannerPlugin);\n }\n\n /**\n * Initialize the runtime\n */\n async init(config?: ExperienceConfig): Promise<void> {\n if (this.initialized) {\n console.warn('[experiences] Already initialized');\n return;\n }\n\n // Recreate SDK if it was destroyed\n if (this.destroyed) {\n this.sdk = new SDK({\n name: 'experience-sdk',\n ...config,\n });\n\n // Re-register core plugins\n this.sdk.use(storagePlugin);\n this.sdk.use(debugPlugin);\n this.sdk.use(frequencyPlugin);\n this.sdk.use(bannerPlugin);\n\n this.destroyed = false;\n }\n\n if (config) {\n // Merge config if provided\n Object.entries(config).forEach(([key, value]) => {\n this.sdk.set(key, value);\n });\n }\n\n // Initialize SDK (will init all plugins)\n await this.sdk.init();\n\n this.initialized = true;\n\n // Emit ready event\n this.sdk.emit('experiences:ready');\n }\n\n /**\n * Register an experience\n */\n register(id: string, experience: Omit<Experience, 'id'>): void {\n const exp: Experience = { id, ...experience };\n this.experiences.set(id, exp);\n\n // Register frequency config with frequency plugin if it exists\n if (exp.frequency && (this.sdk as any).frequency?._registerExperience) {\n (this.sdk as any).frequency._registerExperience(id, exp.frequency.per);\n }\n\n this.sdk.emit('experiences:registered', { id, experience: exp });\n }\n\n /**\n * Evaluate experiences against context\n * Returns decision with explainability\n * First match wins (use evaluateAll() for multiple experiences)\n */\n evaluate(context?: Partial<Context>): Decision {\n const startTime = Date.now();\n const evalContext = buildContext(context);\n\n // Find matching experience\n let matchedExperience: Experience | undefined;\n const allReasons: string[] = [];\n const allTrace: TraceStep[] = [];\n\n for (const [, experience] of this.experiences) {\n const result = evaluateExperience(experience, evalContext);\n\n allReasons.push(...result.reasons);\n allTrace.push(...result.trace);\n\n if (result.matched) {\n // Check frequency cap if experience has frequency rules\n if (experience.frequency && (this.sdk as any).frequency) {\n const freqStart = Date.now();\n const hasReached = (this.sdk as any).frequency.hasReachedCap(\n experience.id,\n experience.frequency.max,\n experience.frequency.per\n );\n\n allTrace.push({\n step: 'check-frequency-cap',\n timestamp: freqStart,\n duration: Date.now() - freqStart,\n input: experience.frequency,\n output: hasReached,\n passed: !hasReached,\n });\n\n if (hasReached) {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n allReasons.push(\n `Frequency cap reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n continue; // Skip this experience, check next\n }\n\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n allReasons.push(\n `Frequency cap not reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n }\n\n matchedExperience = experience;\n break; // First match wins\n }\n }\n\n const decision: Decision = {\n show: !!matchedExperience,\n experienceId: matchedExperience?.id,\n reasons: allReasons,\n trace: allTrace,\n context: evalContext,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: Date.now() - startTime,\n experiencesEvaluated: this.experiences.size,\n },\n };\n\n // Store decision for inspection\n this.decisions.push(decision);\n\n // Emit for plugins to react (include matched experience for rendering)\n this.sdk.emit('experiences:evaluated', {\n decision,\n experience: matchedExperience,\n });\n\n return decision;\n }\n\n /**\n * Evaluate all experiences against context\n * Returns multiple decisions (sorted by priority)\n * All matching experiences will be shown\n */\n evaluateAll(context?: Partial<Context>): Decision[] {\n const evalContext = buildContext(context);\n\n // Sort experiences by priority (higher = more important)\n // Ties maintain registration order (Map preserves insertion order)\n const sortedExperiences = Array.from(this.experiences.values()).sort((a, b) => {\n const priorityA = a.priority ?? 0;\n const priorityB = b.priority ?? 0;\n return priorityB - priorityA; // Descending order\n });\n\n const decisions: Decision[] = [];\n\n // Evaluate each experience\n for (const experience of sortedExperiences) {\n const expStartTime = Date.now();\n const result = evaluateExperience(experience, evalContext);\n\n let show = result.matched;\n const reasons = [...result.reasons];\n const trace = [...result.trace];\n\n // Check frequency cap if experience has frequency rules\n if (show && experience.frequency && (this.sdk as any).frequency) {\n const freqStart = Date.now();\n const hasReached = (this.sdk as any).frequency.hasReachedCap(\n experience.id,\n experience.frequency.max,\n experience.frequency.per\n );\n\n trace.push({\n step: 'check-frequency-cap',\n timestamp: freqStart,\n duration: Date.now() - freqStart,\n input: experience.frequency,\n output: hasReached,\n passed: !hasReached,\n });\n\n if (hasReached) {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n reasons.push(\n `Frequency cap reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n show = false;\n } else {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n reasons.push(\n `Frequency cap not reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n }\n }\n\n const decision: Decision = {\n show,\n experienceId: experience.id,\n reasons,\n trace,\n context: evalContext,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: Date.now() - expStartTime,\n experiencesEvaluated: 1,\n },\n };\n\n decisions.push(decision);\n this.decisions.push(decision);\n }\n\n // Emit single event with all decisions (array)\n // Plugins can filter to their relevant experiences\n const matchedDecisions = decisions.filter((d) => d.show);\n const matchedExperiences = matchedDecisions\n .map((d) => d.experienceId && this.experiences.get(d.experienceId))\n .filter((exp): exp is Experience => exp !== undefined);\n\n this.sdk.emit(\n 'experiences:evaluated',\n matchedDecisions.map((decision, index) => ({\n decision,\n experience: matchedExperiences[index],\n }))\n );\n\n return decisions;\n }\n\n /**\n * Explain a specific experience\n */\n explain(experienceId: string): Decision | null {\n const experience = this.experiences.get(experienceId);\n if (!experience) {\n return null;\n }\n\n const context = buildContext();\n const result = evaluateExperience(experience, context);\n\n return {\n show: result.matched,\n experienceId,\n reasons: result.reasons,\n trace: result.trace,\n context,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: 0,\n experiencesEvaluated: 1,\n },\n };\n }\n\n /**\n * Get runtime state (for inspection)\n */\n getState(): RuntimeState {\n return {\n initialized: this.initialized,\n experiences: new Map(this.experiences),\n decisions: [...this.decisions],\n config: this.sdk ? this.sdk.getAll() : {},\n };\n }\n\n /**\n * Event subscription (proxy to SDK)\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n return this.sdk.on(event, handler);\n }\n\n /**\n * Destroy runtime\n */\n async destroy(): Promise<void> {\n if (this.sdk) {\n await this.sdk.destroy();\n }\n this.destroyed = true;\n this.experiences.clear();\n this.decisions = [];\n this.initialized = false;\n }\n}\n\n// Pure functions for evaluation logic (easy to test, no dependencies)\n\n/**\n * Build evaluation context from partial input\n * Pure function - no side effects\n */\nexport function buildContext(partial?: Partial<Context>): Context {\n return {\n url: partial?.url ?? (typeof window !== 'undefined' ? window.location.href : ''),\n timestamp: Date.now(),\n user: partial?.user,\n custom: partial?.custom,\n };\n}\n\n/**\n * Evaluate an experience against context\n * Pure function - returns reasons and trace\n */\nexport function evaluateExperience(\n experience: Experience,\n context: Context\n): { matched: boolean; reasons: string[]; trace: TraceStep[] } {\n const reasons: string[] = [];\n const trace: TraceStep[] = [];\n let matched = true;\n\n // Evaluate URL rule\n if (experience.targeting.url) {\n const urlStart = Date.now();\n const urlMatch = evaluateUrlRule(experience.targeting.url, context.url);\n\n trace.push({\n step: 'evaluate-url-rule',\n timestamp: urlStart,\n duration: Date.now() - urlStart,\n input: { rule: experience.targeting.url, url: context.url },\n output: urlMatch,\n passed: urlMatch,\n });\n\n if (urlMatch) {\n reasons.push('URL matches targeting rule');\n } else {\n reasons.push('URL does not match targeting rule');\n matched = false;\n }\n }\n\n return { matched, reasons, trace };\n}\n\n/**\n * Evaluate URL targeting rule\n * Pure function - deterministic output\n */\nexport function evaluateUrlRule(rule: UrlRule, url: string = ''): boolean {\n // Check equals (exact match)\n if (rule.equals !== undefined) {\n return url === rule.equals;\n }\n\n // Check contains (substring match)\n if (rule.contains !== undefined) {\n return url.includes(rule.contains);\n }\n\n // Check matches (regex match)\n if (rule.matches !== undefined) {\n return rule.matches.test(url);\n }\n\n // No rules specified = match all\n return true;\n}\n","/**\n * Singleton Pattern Implementation\n *\n * Provides a default singleton instance with convenient wrapper functions\n * for simple use cases, plus createInstance() for advanced scenarios.\n */\n\nimport { ExperienceRuntime } from './runtime';\nimport type { Context, Decision, Experience, ExperienceConfig, RuntimeState } from './types';\n\n/**\n * Create a new Experience SDK instance\n *\n * Use this for advanced scenarios where you need multiple isolated runtimes.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n *\n * const exp = createInstance({ debug: true });\n * await exp.init();\n * exp.register('welcome', { ... });\n * ```\n */\nexport function createInstance(config?: ExperienceConfig): ExperienceRuntime {\n return new ExperienceRuntime(config);\n}\n\n/**\n * Default singleton instance\n *\n * Provides a convenient global instance for simple use cases.\n * For script tag users, this is exposed as the global `experiences` object.\n */\nconst defaultInstance = createInstance();\n\n/**\n * Initialize the Experience SDK\n *\n * @example\n * ```typescript\n * import { init } from '@prosdevlab/experience-sdk';\n * await init({ debug: true });\n * ```\n */\nexport async function init(config?: ExperienceConfig): Promise<void> {\n return defaultInstance.init(config);\n}\n\n/**\n * Register an experience\n *\n * @example\n * ```typescript\n * import { register } from '@prosdevlab/experience-sdk';\n *\n * register('welcome-banner', {\n * type: 'banner',\n * targeting: { url: { contains: '/' } },\n * content: { title: 'Welcome!', message: 'Thanks for visiting' }\n * });\n * ```\n */\nexport function register(id: string, experience: Omit<Experience, 'id'>): void {\n defaultInstance.register(id, experience);\n}\n\n/**\n * Evaluate experiences against current context\n * First match wins (use evaluateAll() for multiple experiences)\n *\n * @example\n * ```typescript\n * import { evaluate } from '@prosdevlab/experience-sdk';\n *\n * const decision = evaluate({ url: window.location.href });\n * if (decision.show) {\n * console.log('Show experience:', decision.experienceId);\n * console.log('Reasons:', decision.reasons);\n * }\n * ```\n */\nexport function evaluate(context?: Partial<Context>): Decision {\n return defaultInstance.evaluate(context);\n}\n\n/**\n * Evaluate all experiences against current context\n * Returns array of decisions sorted by priority (higher = more important)\n * All matching experiences will be shown\n *\n * @example\n * ```typescript\n * import { evaluateAll } from '@prosdevlab/experience-sdk';\n *\n * const decisions = evaluateAll({ url: window.location.href });\n * decisions.forEach(decision => {\n * if (decision.show) {\n * console.log('Show:', decision.experienceId);\n * console.log('Reasons:', decision.reasons);\n * }\n * });\n * ```\n */\nexport function evaluateAll(context?: Partial<Context>): Decision[] {\n return defaultInstance.evaluateAll(context);\n}\n\n/**\n * Explain why a specific experience would/wouldn't show\n *\n * @example\n * ```typescript\n * import { explain } from '@prosdevlab/experience-sdk';\n *\n * const explanation = explain('welcome-banner');\n * console.log('Would show?', explanation?.show);\n * console.log('Reasons:', explanation?.reasons);\n * ```\n */\nexport function explain(experienceId: string): Decision | null {\n return defaultInstance.explain(experienceId);\n}\n\n/**\n * Get current runtime state\n *\n * @example\n * ```typescript\n * import { getState } from '@prosdevlab/experience-sdk';\n *\n * const state = getState();\n * console.log('Initialized?', state.initialized);\n * console.log('Experiences:', Array.from(state.experiences.keys()));\n * ```\n */\nexport function getState(): RuntimeState {\n return defaultInstance.getState();\n}\n\n/**\n * Subscribe to SDK events\n *\n * @example\n * ```typescript\n * import { on } from '@prosdevlab/experience-sdk';\n *\n * const unsubscribe = on('experiences:evaluated', (decision) => {\n * console.log('Evaluation:', decision);\n * });\n *\n * // Later: unsubscribe()\n * ```\n */\nexport function on(event: string, handler: (...args: unknown[]) => void): () => void {\n return defaultInstance.on(event, handler);\n}\n\n/**\n * Destroy the SDK instance\n *\n * @example\n * ```typescript\n * import { destroy } from '@prosdevlab/experience-sdk';\n * await destroy();\n * ```\n */\nexport async function destroy(): Promise<void> {\n return defaultInstance.destroy();\n}\n\n/**\n * Default export for convenient importing\n *\n * @example\n * ```typescript\n * import experiences from '@prosdevlab/experience-sdk';\n * await experiences.init();\n * ```\n */\nexport const experiences = {\n createInstance,\n init,\n register,\n evaluate,\n evaluateAll,\n explain,\n getState,\n on,\n destroy,\n};\n\n/**\n * Global singleton instance for IIFE builds\n *\n * When loaded via script tag, this object is available as `window.experiences`\n */\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).experiences = experiences;\n}\n"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/memory.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/cookie.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/localStorage.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/backends/sessionStorage.ts","../../../node_modules/.pnpm/@lytics+sdk-kit-plugins@0.1.2_@lytics+sdk-kit@0.1.1_typescript@5.9.3_/node_modules/@lytics/sdk-kit-plugins/src/storage/storage.ts","../../plugins/src/utils/sanitize.ts","../../plugins/src/banner/banner.ts","../../plugins/src/debug/debug.ts","../../plugins/src/frequency/frequency.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/util/deep-merge.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/config.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/emitter.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/expose.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/capabilities/namespace.ts","../../../node_modules/.pnpm/@lytics+sdk-kit@0.1.1_typescript@5.9.3/node_modules/@lytics/sdk-kit/src/sdk.ts","../src/runtime.ts","../src/singleton.ts"],"names":["MemoryBackend","key","value","_options","CookieBackend","defaultOptions","name","cookies","cookie","error","options","opts","parts","expires","eqPos","testKey","supported","LocalStorageBackend","SessionStorageBackend","storagePlugin","plugin","instance","config","getBackendType","getNamespace","getDefaultTTL","getCookieDefaults","backends","getBackend","type","buildKey","namespace","ns","isExpired","stored","set","backendType","backend","namespacedKey","ttl","serialized","get","remove","clear","storage","prefix","keysToRemove","i","trimmed","eqIndex","encodedKey","isSupported","ALLOWED_TAGS","ALLOWED_ATTRIBUTES","sanitizeHTML","html","temp","sanitizeNode","node","escapeHTML","element","tagName","allowedAttrs","attrs","attr","sanitizedHref","sanitizeURL","escapeAttribute","attrString","innerHTML","child","sanitized","text","div","url","decoded","bannerPlugin","activeBanners","injectDefaultStyles","styleId","style","createBannerElement","experience","content","position","dismissable","zIndex","banner","baseClasses","container","contentDiv","title","message","buttonContainer","buttonsDiv","createButton","buttonConfig","button","variant","buttonClasses","closeButton","show","experienceId","id","isShowing","payload","items","item","typedItem","decision","debugPlugin","isEnabled","shouldLogConsole","shouldEmitWindow","log","data","logData","event","frequencyPlugin","experienceFrequencyMap","getStorageBackend","per","getStorageKey","getImpressionData","raw","saveImpressionData","getTimeWindow","getImpressionCount","hasReachedCap","max","timeWindow","now","timestamp","recordImpression","sevenDaysAgo","ts","freqStep","t","deepMerge","target","source","result","sourceValue","targetValue","isPlainObject","Config","initialConfig","path","keys","current","lastKey","Emitter","handler","subscription","sub","args","err","pattern","withWildcards","str","Expose","sdk","api","Namespace","SDK","pluginFn","expose","requiredNamespaces","ExperienceRuntime","exp","context","startTime","evalContext","buildContext","matchedExperience","allReasons","allTrace","evaluateExperience","freqStart","hasReached","count","sortedExperiences","a","b","priorityA","decisions","expStartTime","reasons","trace","matchedDecisions","d","matchedExperiences","index","partial","matched","urlStart","urlMatch","evaluateUrlRule","rule","createInstance","defaultInstance","init","register","evaluate","evaluateAll","explain","getState","on","destroy","experiences"],"mappings":"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","file":"experience-sdk.global.js","sourcesContent":["/**\n * Memory Storage Backend\n *\n * In-memory storage fallback when other storage mechanisms are unavailable.\n * Data is lost when the page is refreshed.\n */\n\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class MemoryBackend implements StorageBackend {\n private storage = new Map<string, string>();\n\n get(key: string): string | null {\n return this.storage.get(key) ?? null;\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n this.storage.set(key, value);\n }\n\n remove(key: string): void {\n this.storage.delete(key);\n }\n\n clear(): void {\n this.storage.clear();\n }\n\n isSupported(): boolean {\n // Memory storage is always supported\n return true;\n }\n}\n","/**\n * Cookie Storage Backend\n *\n * Stores data in browser cookies with support for domain, path, secure, and sameSite options.\n * Falls back to memory storage if cookies are unavailable.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class CookieBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n private defaultOptions: StorageBackendOptions;\n\n constructor(defaultOptions: StorageBackendOptions = {}) {\n this.defaultOptions = {\n path: '/',\n sameSite: 'lax',\n ...defaultOptions,\n };\n }\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n const name = `${encodeURIComponent(key)}=`;\n const cookies = document.cookie.split(';');\n\n for (let cookie of cookies) {\n cookie = cookie.trim();\n if (cookie.startsWith(name)) {\n return decodeURIComponent(cookie.substring(name.length));\n }\n }\n\n return null;\n } catch (error) {\n console.warn('Cookie get failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n const opts = { ...this.defaultOptions, ...options };\n const parts: string[] = [`${encodeURIComponent(key)}=${encodeURIComponent(value)}`];\n\n // Add expiration if TTL is provided\n if (opts.ttl) {\n const expires = new Date();\n expires.setTime(expires.getTime() + opts.ttl * 1000);\n parts.push(`expires=${expires.toUTCString()}`);\n }\n\n if (opts.path) {\n parts.push(`path=${opts.path}`);\n }\n\n if (opts.domain) {\n parts.push(`domain=${opts.domain}`);\n }\n\n if (opts.secure) {\n parts.push('secure');\n }\n\n if (opts.sameSite) {\n parts.push(`samesite=${opts.sameSite}`);\n }\n\n document.cookie = parts.join('; ');\n } catch (error) {\n console.warn('Cookie set failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n // Set cookie with past expiration date to delete it\n const opts = this.defaultOptions;\n const parts: string[] = [\n `${encodeURIComponent(key)}=`,\n 'expires=Thu, 01 Jan 1970 00:00:00 UTC',\n ];\n\n if (opts.path) {\n parts.push(`path=${opts.path}`);\n }\n\n if (opts.domain) {\n parts.push(`domain=${opts.domain}`);\n }\n\n document.cookie = parts.join('; ');\n } catch (error) {\n console.warn('Cookie remove failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n // Get all cookie names and delete them\n const cookies = document.cookie.split(';');\n\n for (let cookie of cookies) {\n cookie = cookie.trim();\n const eqPos = cookie.indexOf('=');\n const name = eqPos > -1 ? cookie.substring(0, eqPos) : cookie;\n this.remove(decodeURIComponent(name));\n }\n } catch (error) {\n console.warn('Cookie clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n // Check if cookies are enabled\n if (typeof document === 'undefined' || !document.cookie) {\n return false;\n }\n\n // Try to set and remove a test cookie\n const testKey = '__cookie_test__';\n document.cookie = `${testKey}=test; path=/`;\n const supported = document.cookie.indexOf(testKey) !== -1;\n\n // Clean up test cookie\n document.cookie = `${testKey}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n\n return supported;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * LocalStorage Backend\n *\n * Persistent storage that survives page refreshes and browser restarts.\n * Falls back to memory storage if localStorage is unavailable or quota is exceeded.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class LocalStorageBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n return localStorage.getItem(key);\n } catch (error) {\n console.warn('localStorage.getItem failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n localStorage.setItem(key, value);\n } catch (error) {\n // Quota exceeded or other error\n console.warn('localStorage.setItem failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n localStorage.removeItem(key);\n } catch (error) {\n console.warn('localStorage.removeItem failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n localStorage.clear();\n } catch (error) {\n console.warn('localStorage.clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n const testKey = '__storage_test__';\n localStorage.setItem(testKey, 'test');\n localStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * SessionStorage Backend\n *\n * Session-scoped storage that persists only for the duration of the page session.\n * Data is cleared when the tab/window is closed.\n * Falls back to memory storage if sessionStorage is unavailable.\n */\n\nimport { MemoryBackend } from './memory';\nimport type { StorageBackend, StorageBackendOptions } from './types';\n\nexport class SessionStorageBackend implements StorageBackend {\n private fallback: MemoryBackend | null = null;\n\n get(key: string): string | null {\n if (!this.isSupported()) {\n return this.getFallback().get(key);\n }\n\n try {\n return sessionStorage.getItem(key);\n } catch (error) {\n console.warn('sessionStorage.getItem failed:', error);\n return this.getFallback().get(key);\n }\n }\n\n set(key: string, value: string, _options?: StorageBackendOptions): void {\n if (!this.isSupported()) {\n this.getFallback().set(key, value);\n return;\n }\n\n try {\n sessionStorage.setItem(key, value);\n } catch (error) {\n console.warn('sessionStorage.setItem failed, falling back to memory:', error);\n this.getFallback().set(key, value);\n }\n }\n\n remove(key: string): void {\n if (!this.isSupported()) {\n this.getFallback().remove(key);\n return;\n }\n\n try {\n sessionStorage.removeItem(key);\n } catch (error) {\n console.warn('sessionStorage.removeItem failed:', error);\n this.getFallback().remove(key);\n }\n }\n\n clear(): void {\n if (!this.isSupported()) {\n this.getFallback().clear();\n return;\n }\n\n try {\n sessionStorage.clear();\n } catch (error) {\n console.warn('sessionStorage.clear failed:', error);\n this.getFallback().clear();\n }\n }\n\n isSupported(): boolean {\n try {\n const testKey = '__storage_test__';\n sessionStorage.setItem(testKey, 'test');\n sessionStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n private getFallback(): MemoryBackend {\n if (!this.fallback) {\n this.fallback = new MemoryBackend();\n }\n return this.fallback;\n }\n}\n","/**\n * Storage Plugin\n *\n * Universal storage abstraction with support for:\n * - Multiple backends (localStorage, sessionStorage, cookie, memory)\n * - TTL/expiration\n * - Namespace isolation\n * - JSON serialization\n * - Automatic fallback\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\nimport { CookieBackend } from './backends/cookie';\nimport { LocalStorageBackend } from './backends/localStorage';\nimport { MemoryBackend } from './backends/memory';\nimport { SessionStorageBackend } from './backends/sessionStorage';\nimport type { StorageBackend, StorageBackendOptions } from './backends/types';\n\nexport type StorageBackendType = 'localStorage' | 'sessionStorage' | 'cookie' | 'memory';\n\nexport interface StoragePluginConfig {\n storage?: {\n backend?: StorageBackendType;\n namespace?: string;\n ttl?: number;\n // Cookie-specific defaults\n domain?: string;\n path?: string;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n };\n}\n\nexport interface StorageOptions extends StorageBackendOptions {\n backend?: StorageBackendType;\n namespace?: string;\n}\n\nexport interface StoragePlugin {\n set(key: string, value: unknown, options?: StorageOptions): void;\n get<T = unknown>(key: string, options?: Pick<StorageOptions, 'backend'>): T | null;\n remove(key: string, options?: Pick<StorageOptions, 'backend'>): void;\n clear(options?: Pick<StorageOptions, 'backend'>): void;\n}\n\ninterface StoredValue<T> {\n value: T;\n expires?: number; // Timestamp in milliseconds\n}\n\n/**\n * Storage Plugin\n *\n * Provides a universal storage API with automatic backend selection and fallback.\n *\n * @example\n * ```typescript\n * const sdk = new SDK({ storage: { backend: 'localStorage', namespace: 'myapp' } });\n * sdk.use(storagePlugin);\n *\n * sdk.storage.set('user', { id: 123, name: 'Alice' });\n * const user = sdk.storage.get('user');\n * ```\n */\nexport const storagePlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('storage');\n\n // Set default config\n plugin.defaults({\n storage: {\n backend: 'localStorage',\n namespace: '',\n path: '/',\n sameSite: 'lax',\n },\n });\n\n // Get config values\n const getBackendType = (): StorageBackendType => config.get('storage.backend') ?? 'localStorage';\n const getNamespace = (): string => config.get('storage.namespace') ?? '';\n const getDefaultTTL = (): number | undefined => config.get('storage.ttl');\n const getCookieDefaults = (): StorageBackendOptions => ({\n domain: config.get('storage.domain'),\n path: config.get('storage.path') ?? '/',\n secure: config.get('storage.secure'),\n sameSite: config.get('storage.sameSite') ?? 'lax',\n });\n\n // Backend instances (lazy-initialized)\n const backends: Partial<Record<StorageBackendType, StorageBackend>> = {};\n\n /**\n * Get or create a backend instance\n */\n function getBackend(type: StorageBackendType): StorageBackend {\n if (!backends[type]) {\n switch (type) {\n case 'localStorage':\n backends[type] = new LocalStorageBackend();\n break;\n case 'sessionStorage':\n backends[type] = new SessionStorageBackend();\n break;\n case 'cookie':\n backends[type] = new CookieBackend(getCookieDefaults());\n break;\n case 'memory':\n backends[type] = new MemoryBackend();\n break;\n }\n }\n return backends[type] as StorageBackend;\n }\n\n /**\n * Build a namespaced key\n */\n function buildKey(key: string, namespace?: string): string {\n const ns = namespace ?? getNamespace();\n return ns ? `${ns}:${key}` : key;\n }\n\n /**\n * Check if a stored value has expired\n */\n function isExpired(stored: StoredValue<any>): boolean {\n if (!stored.expires) {\n return false;\n }\n return Date.now() > stored.expires;\n }\n\n /**\n * Set a value in storage\n */\n function set<T>(key: string, value: T, options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n // Wrap value with expiration metadata\n const stored: StoredValue<T> = { value };\n const ttl = options?.ttl ?? getDefaultTTL();\n\n if (ttl) {\n stored.expires = Date.now() + ttl * 1000;\n }\n\n // Serialize to JSON\n const serialized = JSON.stringify(stored);\n\n // Store using backend\n backend.set(namespacedKey, serialized, options);\n\n // Emit event\n plugin.emit('storage:set', { key, value, backend: backendType });\n }\n\n /**\n * Get a value from storage\n */\n function get<T>(key: string, options?: StorageOptions): T | null {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n // Get from backend\n const serialized = backend.get(namespacedKey);\n\n if (!serialized) {\n return null;\n }\n\n try {\n // Deserialize from JSON\n const stored: StoredValue<T> = JSON.parse(serialized);\n\n // Check expiration\n if (isExpired(stored)) {\n // Remove expired value\n backend.remove(namespacedKey);\n plugin.emit('storage:expired', { key, backend: backendType });\n return null;\n }\n\n plugin.emit('storage:get', { key, backend: backendType });\n return stored.value;\n } catch (error) {\n console.warn('Failed to parse stored value:', error);\n // Remove corrupted value\n backend.remove(namespacedKey);\n return null;\n }\n }\n\n /**\n * Remove a value from storage\n */\n function remove(key: string, options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespacedKey = buildKey(key, options?.namespace);\n\n backend.remove(namespacedKey);\n plugin.emit('storage:remove', { key, backend: backendType });\n }\n\n /**\n * Clear all values from storage\n *\n * If a namespace is provided, only clears values with that namespace prefix.\n * Otherwise, clears all values in the backend.\n */\n function clear(options?: StorageOptions): void {\n const backendType = options?.backend ?? getBackendType();\n const backend = getBackend(backendType);\n const namespace = options?.namespace;\n\n // If no namespace specified, clear everything\n if (!namespace) {\n backend.clear();\n plugin.emit('storage:clear', { backend: backendType });\n return;\n }\n\n // Namespace-specific clearing: iterate through all keys and remove matching ones\n if (backendType === 'localStorage' || backendType === 'sessionStorage') {\n const storage = backendType === 'localStorage' ? localStorage : sessionStorage;\n const prefix = `${namespace}:`;\n const keysToRemove: string[] = [];\n\n // Collect keys to remove\n for (let i = 0; i < storage.length; i++) {\n const key = storage.key(i);\n if (key?.startsWith(prefix)) {\n keysToRemove.push(key);\n }\n }\n\n // Remove them\n for (const key of keysToRemove) {\n backend.remove(key);\n }\n } else if (backendType === 'cookie') {\n // For cookies, parse document.cookie and remove matching keys\n const prefix = `${namespace}:`;\n const cookies = document.cookie.split(';');\n\n for (const cookie of cookies) {\n const trimmed = cookie.trim();\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n\n const encodedKey = trimmed.substring(0, eqIndex);\n const key = decodeURIComponent(encodedKey);\n\n if (key.startsWith(prefix)) {\n backend.remove(key);\n }\n }\n } else {\n // For memory backend, just clear everything (it's in-memory anyway)\n backend.clear();\n }\n\n plugin.emit('storage:clear', { backend: backendType, namespace });\n }\n\n /**\n * Check if a backend is supported\n */\n function isSupported(backendType?: StorageBackendType): boolean {\n const type = backendType ?? getBackendType();\n const backend = getBackend(type);\n return backend.isSupported();\n }\n\n // Expose public API\n plugin.expose({\n storage: {\n set,\n get,\n remove,\n clear,\n isSupported,\n },\n });\n\n // Log initialization\n instance.on('sdk:ready', () => {\n const backendType = getBackendType();\n const backend = getBackend(backendType);\n const supported = backend.isSupported();\n\n if (!supported) {\n console.warn(\n `Storage backend '${backendType}' is not supported, falling back to memory storage`\n );\n }\n });\n};\n\nexport { CookieBackend } from './backends/cookie';\nexport { LocalStorageBackend } from './backends/localStorage';\nexport { MemoryBackend } from './backends/memory';\nexport { SessionStorageBackend } from './backends/sessionStorage';\n// Export types and backends for testing\nexport type { StorageBackend, StorageBackendOptions } from './backends/types';\n","/**\n * HTML Sanitizer\n *\n * Lightweight HTML sanitizer for experience content (messages, titles).\n * Whitelist-based approach that only allows safe formatting tags.\n *\n * Security: Prevents XSS attacks by stripping dangerous tags and attributes.\n */\n\n/**\n * Allowed HTML tags for sanitization\n * Only safe formatting tags are permitted\n */\nconst ALLOWED_TAGS = ['strong', 'em', 'a', 'br', 'span', 'b', 'i', 'p'] as const;\n\n/**\n * Allowed attributes per tag\n */\nconst ALLOWED_ATTRIBUTES: Record<string, string[]> = {\n a: ['href', 'class', 'style', 'title'],\n span: ['class', 'style'],\n p: ['class', 'style'],\n // Other tags have no attributes allowed\n};\n\n/**\n * Sanitize HTML string by removing dangerous tags and attributes\n *\n * @param html - HTML string to sanitize\n * @returns Sanitized HTML string safe for innerHTML\n *\n * @example\n * ```typescript\n * sanitizeHTML('<strong>Hello</strong><script>alert(\"xss\")</script>');\n * // Returns: '<strong>Hello</strong>'\n * ```\n */\nexport function sanitizeHTML(html: string): string {\n if (!html || typeof html !== 'string') {\n return '';\n }\n\n // Create a temporary DOM element to parse HTML\n const temp = document.createElement('div');\n temp.innerHTML = html;\n\n /**\n * Recursively sanitize a DOM node\n */\n function sanitizeNode(node: Node): string {\n // Text nodes - escape HTML entities\n if (node.nodeType === Node.TEXT_NODE) {\n return escapeHTML(node.textContent || '');\n }\n\n // Element nodes\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n\n // Handle tags with whitespace (malformed HTML like \"< script >\")\n // Browser normalizes these, but if we see a tag that's not in our list,\n // it might be a dangerous tag that was normalized\n if (!tagName || tagName.includes(' ')) {\n return '';\n }\n\n // If tag is not allowed, return empty string\n if (!ALLOWED_TAGS.includes(tagName as any)) {\n return '';\n }\n\n // Get allowed attributes for this tag\n const allowedAttrs = ALLOWED_ATTRIBUTES[tagName] || [];\n\n // Build attribute string\n const attrs: string[] = [];\n for (const attr of allowedAttrs) {\n const value = element.getAttribute(attr);\n if (value !== null) {\n // Sanitize attribute values\n if (attr === 'href') {\n // Only allow safe URLs (http, https, mailto, tel, relative)\n const sanitizedHref = sanitizeURL(value);\n if (sanitizedHref) {\n attrs.push(`href=\"${escapeAttribute(sanitizedHref)}\"`);\n }\n } else {\n // For all other attributes (title, class, style), escape HTML entities\n attrs.push(`${attr}=\"${escapeAttribute(value)}\"`);\n }\n }\n }\n\n const attrString = attrs.length > 0 ? ' ' + attrs.join(' ') : '';\n\n // Process child nodes\n let innerHTML = '';\n for (const child of Array.from(element.childNodes)) {\n innerHTML += sanitizeNode(child);\n }\n\n // Self-closing tags\n if (tagName === 'br') {\n return `<br${attrString} />`;\n }\n\n return `<${tagName}${attrString}>${innerHTML}</${tagName}>`;\n }\n\n return '';\n }\n\n // Sanitize all nodes\n let sanitized = '';\n for (const child of Array.from(temp.childNodes)) {\n sanitized += sanitizeNode(child);\n }\n\n return sanitized;\n}\n\n/**\n * Escape HTML entities to prevent XSS in text content\n */\nfunction escapeHTML(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n\n/**\n * Escape HTML entities for use in attribute values\n */\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/**\n * Sanitize URL to prevent javascript: and data: XSS attacks\n *\n * @param url - URL to sanitize\n * @returns Sanitized URL or empty string if unsafe\n */\nfunction sanitizeURL(url: string): string {\n if (!url || typeof url !== 'string') {\n return '';\n }\n\n // Decode URL-encoded characters to check for encoded attacks\n let decoded: string;\n try {\n decoded = decodeURIComponent(url);\n } catch {\n // If decoding fails, use original\n decoded = url;\n }\n\n const trimmed = decoded.trim().toLowerCase();\n\n // Block javascript: and data: protocols (check both original and decoded)\n if (\n trimmed.startsWith('javascript:') ||\n trimmed.startsWith('data:') ||\n url.toLowerCase().trim().startsWith('javascript:') ||\n url.toLowerCase().trim().startsWith('data:')\n ) {\n return '';\n }\n\n // Allow http, https, mailto, tel, and relative URLs\n if (\n trimmed.startsWith('http://') ||\n trimmed.startsWith('https://') ||\n trimmed.startsWith('mailto:') ||\n trimmed.startsWith('tel:') ||\n trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?')\n ) {\n return url; // Return original (case preserved)\n }\n\n // Allow relative paths without protocol\n if (!trimmed.includes(':')) {\n return url;\n }\n\n // Block everything else\n return '';\n}\n","/**\n * Banner Plugin\n *\n * Renders banner experiences at the top or bottom of the page.\n * Auto-shows banners when experiences are evaluated.\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\nimport type { BannerContent, Decision, Experience } from '../types';\nimport { sanitizeHTML } from '../utils/sanitize';\n\nexport interface BannerPluginConfig {\n banner?: {\n position?: 'top' | 'bottom';\n dismissable?: boolean;\n zIndex?: number;\n };\n}\n\nexport interface BannerPlugin {\n show(experience: Experience): void;\n remove(): void;\n isShowing(): boolean;\n}\n\n/**\n * Banner Plugin\n *\n * Automatically renders banner experiences when they are evaluated.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { bannerPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ banner: { position: 'top', dismissable: true } });\n * sdk.use(bannerPlugin);\n * ```\n */\nexport const bannerPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('banner');\n\n // Set defaults\n plugin.defaults({\n banner: {\n position: 'top',\n dismissable: true,\n zIndex: 10000,\n },\n });\n\n // Track multiple active banners by experience ID\n const activeBanners = new Map<string, HTMLElement>();\n\n /**\n * Inject default banner styles if not already present\n */\n function injectDefaultStyles(): void {\n const styleId = 'xp-banner-styles';\n if (document.getElementById(styleId)) {\n return; // Already injected\n }\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n .xp-banner {\n position: fixed;\n left: 0;\n right: 0;\n width: 100%;\n padding: 16px 20px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n display: flex;\n align-items: center;\n justify-content: space-between;\n box-sizing: border-box;\n z-index: 10000;\n background: #f9fafb;\n color: #111827;\n border-bottom: 1px solid #e5e7eb;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05);\n }\n \n .xp-banner--top {\n top: 0;\n }\n \n .xp-banner--bottom {\n bottom: 0;\n border-bottom: none;\n border-top: 1px solid #e5e7eb;\n box-shadow: 0 -1px 3px 0 rgba(0, 0, 0, 0.05);\n }\n \n .xp-banner__container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n width: 100%;\n }\n \n .xp-banner__content {\n flex: 1;\n min-width: 0;\n }\n \n .xp-banner__title {\n font-weight: 600;\n margin-bottom: 4px;\n margin-top: 0;\n font-size: 14px;\n }\n \n .xp-banner__message {\n margin: 0;\n font-size: 14px;\n }\n \n .xp-banner__buttons {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n flex-shrink: 0;\n }\n \n .xp-banner__button {\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n text-decoration: none;\n }\n \n .xp-banner__button--primary {\n background: #2563eb;\n color: #ffffff;\n }\n \n .xp-banner__button--primary:hover {\n background: #1d4ed8;\n }\n \n .xp-banner__button--secondary {\n background: #ffffff;\n color: #374151;\n border: 1px solid #d1d5db;\n }\n \n .xp-banner__button--secondary:hover {\n background: #f9fafb;\n }\n \n .xp-banner__button--link {\n background: transparent;\n color: #2563eb;\n padding: 4px 8px;\n font-weight: 400;\n text-decoration: underline;\n }\n \n .xp-banner__button--link:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n \n .xp-banner__close {\n background: transparent;\n border: none;\n color: #6b7280;\n font-size: 24px;\n line-height: 1;\n cursor: pointer;\n padding: 0;\n margin: 0;\n opacity: 0.7;\n transition: opacity 0.2s;\n flex-shrink: 0;\n }\n \n .xp-banner__close:hover {\n opacity: 1;\n }\n \n @media (max-width: 640px) {\n .xp-banner__container {\n flex-direction: column;\n align-items: stretch;\n }\n \n .xp-banner__buttons {\n width: 100%;\n flex-direction: column;\n }\n \n .xp-banner__button {\n width: 100%;\n }\n }\n \n /* Dark mode support */\n @media (prefers-color-scheme: dark) {\n .xp-banner {\n background: #1f2937;\n color: #f3f4f6;\n border-bottom-color: #374151;\n }\n \n .xp-banner--bottom {\n border-top-color: #374151;\n }\n \n .xp-banner__button--primary {\n background: #3b82f6;\n }\n \n .xp-banner__button--primary:hover {\n background: #2563eb;\n }\n \n .xp-banner__button--secondary {\n background: #374151;\n color: #f3f4f6;\n border-color: #4b5563;\n }\n \n .xp-banner__button--secondary:hover {\n background: #4b5563;\n }\n \n .xp-banner__button--link {\n color: #93c5fd;\n }\n \n .xp-banner__close {\n color: #9ca3af;\n }\n }\n `;\n document.head.appendChild(style);\n }\n\n /**\n * Create banner DOM element\n */\n function createBannerElement(experience: Experience): HTMLElement {\n const content = experience.content as BannerContent;\n // Allow per-experience position override, fall back to global config\n const position = content.position ?? config.get('banner.position') ?? 'top';\n const dismissable = content.dismissable ?? config.get('banner.dismissable') ?? true;\n const zIndex = config.get('banner.zIndex') ?? 10000;\n\n // Inject default styles if needed\n injectDefaultStyles();\n\n // Create banner container\n const banner = document.createElement('div');\n banner.setAttribute('data-experience-id', experience.id);\n\n // Build className: base classes + position + user's custom class\n const baseClasses = ['xp-banner', `xp-banner--${position}`];\n if (content.className) {\n baseClasses.push(content.className);\n }\n banner.className = baseClasses.join(' ');\n\n // Apply user's custom styles\n if (content.style) {\n Object.assign(banner.style, content.style);\n }\n\n // Override z-index if configured\n if (zIndex !== 10000) {\n banner.style.zIndex = String(zIndex);\n }\n\n // Create container\n const container = document.createElement('div');\n container.className = 'xp-banner__container';\n banner.appendChild(container);\n\n // Create content container\n const contentDiv = document.createElement('div');\n contentDiv.className = 'xp-banner__content';\n\n // Add title if present\n if (content.title) {\n const title = document.createElement('h3');\n title.className = 'xp-banner__title';\n // Sanitize HTML to prevent XSS attacks\n title.innerHTML = sanitizeHTML(content.title);\n contentDiv.appendChild(title);\n }\n\n // Add message\n const message = document.createElement('p');\n message.className = 'xp-banner__message';\n // Sanitize HTML to prevent XSS attacks\n message.innerHTML = sanitizeHTML(content.message);\n contentDiv.appendChild(message);\n\n container.appendChild(contentDiv);\n\n banner.appendChild(contentDiv);\n\n // Create button container for actions and/or dismiss\n const buttonContainer = document.createElement('div');\n buttonContainer.style.cssText = `\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n `;\n\n // Create buttons container\n const buttonsDiv = document.createElement('div');\n buttonsDiv.className = 'xp-banner__buttons';\n\n // Helper function to create button with variant styling\n function createButton(buttonConfig: {\n text: string;\n action?: string;\n url?: string;\n variant?: 'primary' | 'secondary' | 'link';\n metadata?: Record<string, unknown>;\n className?: string;\n style?: Record<string, string>;\n }): HTMLButtonElement {\n const button = document.createElement('button');\n button.textContent = buttonConfig.text;\n\n const variant = buttonConfig.variant || 'primary';\n\n // Build className: base class + variant + user's custom class\n const buttonClasses = ['xp-banner__button', `xp-banner__button--${variant}`];\n if (buttonConfig.className) {\n buttonClasses.push(buttonConfig.className);\n }\n button.className = buttonClasses.join(' ');\n\n // Apply user's custom styles\n if (buttonConfig.style) {\n Object.assign(button.style, buttonConfig.style);\n }\n\n button.addEventListener('click', () => {\n // Emit action event\n instance.emit('experiences:action', {\n experienceId: experience.id,\n type: 'banner',\n action: buttonConfig.action,\n url: buttonConfig.url,\n metadata: buttonConfig.metadata,\n variant: variant,\n timestamp: Date.now(),\n });\n\n // Navigate if URL provided\n if (buttonConfig.url) {\n window.location.href = buttonConfig.url;\n }\n });\n\n return button;\n }\n\n // Add buttons from buttons array\n if (content.buttons && content.buttons.length > 0) {\n content.buttons.forEach((buttonConfig) => {\n const button = createButton(buttonConfig);\n buttonsDiv.appendChild(button);\n });\n }\n\n // Add dismiss button if dismissable\n if (dismissable) {\n const closeButton = document.createElement('button');\n closeButton.className = 'xp-banner__close';\n closeButton.innerHTML = '&times;';\n closeButton.setAttribute('aria-label', 'Close banner');\n\n closeButton.addEventListener('click', () => {\n remove(experience.id);\n instance.emit('experiences:dismissed', {\n experienceId: experience.id,\n type: 'banner',\n });\n });\n\n buttonsDiv.appendChild(closeButton);\n }\n\n container.appendChild(buttonsDiv);\n\n return banner;\n }\n\n /**\n * Show a banner experience\n */\n function show(experience: Experience): void {\n // If banner already showing for this experience, skip\n if (activeBanners.has(experience.id)) {\n return;\n }\n\n // Only show if we're in a browser environment\n if (typeof document === 'undefined') {\n return;\n }\n\n const banner = createBannerElement(experience);\n document.body.appendChild(banner);\n activeBanners.set(experience.id, banner);\n\n instance.emit('experiences:shown', {\n experienceId: experience.id,\n type: 'banner',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Remove a banner by experience ID (or all if no ID provided)\n */\n function remove(experienceId?: string): void {\n if (experienceId) {\n // Remove specific banner\n const banner = activeBanners.get(experienceId);\n if (banner?.parentNode) {\n banner.parentNode.removeChild(banner);\n }\n activeBanners.delete(experienceId);\n } else {\n // Remove all banners\n for (const [id, banner] of activeBanners.entries()) {\n if (banner?.parentNode) {\n banner.parentNode.removeChild(banner);\n }\n activeBanners.delete(id);\n }\n }\n }\n\n /**\n * Check if any banner is currently showing\n */\n function isShowing(): boolean {\n return activeBanners.size > 0;\n }\n\n // Expose banner API\n plugin.expose({\n banner: {\n show,\n remove,\n isShowing,\n },\n });\n\n // Auto-show banner on experiences:evaluated event\n instance.on('experiences:evaluated', (payload: unknown) => {\n // Handle both single decision and array of decisions\n // evaluate() emits: { decision, experience }\n // evaluateAll() emits: [{ decision, experience }, ...]\n const items = Array.isArray(payload) ? payload : [payload];\n\n for (const item of items) {\n // Item is { decision, experience }\n const typedItem = item as { decision?: Decision; experience?: Experience };\n const decision = typedItem.decision;\n const experience = typedItem.experience;\n\n // Only handle banner-type experiences\n if (experience?.type === 'banner') {\n if (decision?.show) {\n show(experience);\n } else if (experience.id && activeBanners.has(experience.id)) {\n // Hide specific banner if decision says don't show\n remove(experience.id);\n }\n }\n }\n });\n\n // Cleanup on destroy\n instance.on('sdk:destroy', () => {\n remove();\n });\n};\n","/**\n * Debug Plugin\n *\n * Emits structured debug events to window and optionally logs to console.\n * Useful for debugging and Chrome extension integration.\n */\n\nimport type { PluginFunction } from '@lytics/sdk-kit';\n\nexport interface DebugPluginConfig {\n debug?: {\n enabled?: boolean;\n console?: boolean;\n window?: boolean;\n };\n}\n\nexport interface DebugPlugin {\n log(message: string, data?: unknown): void;\n isEnabled(): boolean;\n}\n\n/**\n * Debug Plugin\n *\n * Listens to all SDK events and emits them as window events for debugging.\n * Also optionally logs to console.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { debugPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ debug: { enabled: true, console: true } });\n * sdk.use(debugPlugin);\n * ```\n */\nexport const debugPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('debug');\n\n // Set defaults\n plugin.defaults({\n debug: {\n enabled: false,\n console: false,\n window: true,\n },\n });\n\n // Helper to check if debug is enabled\n const isEnabled = (): boolean => config.get('debug.enabled') ?? false;\n const shouldLogConsole = (): boolean => config.get('debug.console') ?? false;\n const shouldEmitWindow = (): boolean => config.get('debug.window') ?? true;\n\n // Log function\n const log = (message: string, data?: unknown): void => {\n if (!isEnabled()) return;\n\n const timestamp = new Date().toISOString();\n const logData = {\n timestamp,\n message,\n data,\n };\n\n // Console logging\n if (shouldLogConsole()) {\n console.log(`[experiences] ${message}`, data || '');\n }\n\n // Window event emission\n if (shouldEmitWindow() && typeof window !== 'undefined') {\n const event = new CustomEvent('experience-sdk:debug', {\n detail: logData,\n });\n window.dispatchEvent(event);\n }\n };\n\n // Expose debug API\n plugin.expose({\n debug: {\n log,\n isEnabled,\n },\n });\n\n // If debug is enabled, listen to all events\n if (isEnabled()) {\n // Listen to experiences:* events\n instance.on('experiences:ready', () => {\n if (!isEnabled()) return;\n log('SDK initialized and ready');\n });\n\n instance.on('experiences:registered', (payload) => {\n if (!isEnabled()) return;\n log('Experience registered', payload);\n });\n\n instance.on('experiences:evaluated', (payload) => {\n if (!isEnabled()) return;\n log('Experience evaluated', payload);\n });\n }\n};\n","/**\n * Frequency Capping Plugin\n *\n * Tracks experience impressions and enforces frequency caps.\n * Uses sdk-kit's storage plugin for persistence.\n */\n\nimport type { PluginFunction, SDK } from '@lytics/sdk-kit';\nimport { type StoragePlugin, storagePlugin } from '@lytics/sdk-kit-plugins';\nimport type { Decision, TraceStep } from '../types';\n\nexport interface FrequencyPluginConfig {\n frequency?: {\n enabled?: boolean;\n namespace?: string;\n };\n}\n\nexport interface FrequencyPlugin {\n getImpressionCount(experienceId: string): number;\n hasReachedCap(experienceId: string, max: number, per: 'session' | 'day' | 'week'): boolean;\n recordImpression(experienceId: string): void;\n}\n\ninterface ImpressionData {\n count: number;\n lastImpression: number;\n impressions: number[];\n per?: 'session' | 'day' | 'week'; // Track which storage type this uses\n}\n\n/**\n * Frequency Capping Plugin\n *\n * Automatically tracks impressions and enforces frequency caps.\n * Requires storage plugin for persistence.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n * import { frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';\n *\n * const sdk = createInstance({ frequency: { enabled: true } });\n * sdk.use(frequencyPlugin);\n * ```\n */\nexport const frequencyPlugin: PluginFunction = (plugin, instance, config) => {\n plugin.ns('frequency');\n\n // Set defaults\n plugin.defaults({\n frequency: {\n enabled: true,\n namespace: 'experiences:frequency',\n },\n });\n\n // Track experience frequency configs\n const experienceFrequencyMap = new Map<string, 'session' | 'day' | 'week'>();\n\n // Auto-load storage plugin if not already loaded\n if (!(instance as SDK & { storage?: StoragePlugin }).storage) {\n instance.use(storagePlugin);\n }\n\n const isEnabled = (): boolean => config.get('frequency.enabled') ?? true;\n const getNamespace = (): string => config.get('frequency.namespace') ?? 'experiences:frequency';\n\n // Helper to get the right storage backend based on frequency type\n const getStorageBackend = (per: 'session' | 'day' | 'week'): Storage => {\n return per === 'session' ? sessionStorage : localStorage;\n };\n\n // Helper to get storage key\n const getStorageKey = (experienceId: string): string => {\n return `${getNamespace()}:${experienceId}`;\n };\n\n // Helper to get impression data\n const getImpressionData = (\n experienceId: string,\n per: 'session' | 'day' | 'week'\n ): ImpressionData => {\n const storage = getStorageBackend(per);\n const key = getStorageKey(experienceId);\n const raw = storage.getItem(key);\n\n if (!raw) {\n return {\n count: 0,\n lastImpression: 0,\n impressions: [],\n per,\n };\n }\n\n try {\n return JSON.parse(raw) as ImpressionData;\n } catch {\n return {\n count: 0,\n lastImpression: 0,\n impressions: [],\n per,\n };\n }\n };\n\n // Helper to save impression data\n const saveImpressionData = (experienceId: string, data: ImpressionData): void => {\n const per = data.per || 'session'; // Default to session if not specified\n const storage = getStorageBackend(per);\n const key = getStorageKey(experienceId);\n storage.setItem(key, JSON.stringify(data));\n };\n\n // Get time window in milliseconds\n const getTimeWindow = (per: 'session' | 'day' | 'week'): number => {\n switch (per) {\n case 'session':\n return Number.POSITIVE_INFINITY; // Session storage handles this\n case 'day':\n return 24 * 60 * 60 * 1000; // 24 hours\n case 'week':\n return 7 * 24 * 60 * 60 * 1000; // 7 days\n }\n };\n\n /**\n * Get impression count for an experience\n */\n const getImpressionCount = (\n experienceId: string,\n per: 'session' | 'day' | 'week' = 'session'\n ): number => {\n if (!isEnabled()) return 0;\n const data = getImpressionData(experienceId, per);\n return data.count;\n };\n\n /**\n * Check if an experience has reached its frequency cap\n */\n const hasReachedCap = (\n experienceId: string,\n max: number,\n per: 'session' | 'day' | 'week'\n ): boolean => {\n if (!isEnabled()) return false;\n\n const data = getImpressionData(experienceId, per);\n const timeWindow = getTimeWindow(per);\n const now = Date.now();\n\n // For session caps, just check total count\n if (per === 'session') {\n return data.count >= max;\n }\n\n // For time-based caps, count impressions within the window\n const recentImpressions = data.impressions.filter((timestamp) => now - timestamp < timeWindow);\n\n return recentImpressions.length >= max;\n };\n\n /**\n * Record an impression for an experience\n */\n const recordImpression = (\n experienceId: string,\n per: 'session' | 'day' | 'week' = 'session'\n ): void => {\n if (!isEnabled()) return;\n\n const data = getImpressionData(experienceId, per);\n const now = Date.now();\n\n // Update count and add timestamp\n data.count += 1;\n data.lastImpression = now;\n data.impressions.push(now);\n data.per = per; // Store the frequency type\n\n // Keep only recent impressions (last 7 days)\n const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;\n data.impressions = data.impressions.filter((ts) => ts > sevenDaysAgo);\n\n // Save updated data\n saveImpressionData(experienceId, data);\n\n // Emit event\n instance.emit('experiences:impression-recorded', {\n experienceId,\n count: data.count,\n timestamp: now,\n });\n };\n\n // Expose frequency API\n plugin.expose({\n frequency: {\n getImpressionCount,\n hasReachedCap,\n recordImpression,\n // Internal method to register experience frequency config\n _registerExperience: (experienceId: string, per: 'session' | 'day' | 'week') => {\n experienceFrequencyMap.set(experienceId, per);\n },\n },\n });\n\n // Listen to evaluation events and record impressions\n if (isEnabled()) {\n instance.on('experiences:evaluated', (payload: unknown) => {\n // Handle both single decision and array of decisions\n // evaluate() emits: { decision, experience }\n // evaluateAll() emits: [{ decision, experience }, ...]\n const items = Array.isArray(payload) ? payload : [payload];\n\n for (const item of items) {\n // Item is { decision, experience }\n const decision = (item as { decision?: Decision }).decision;\n\n // Only record if experience was shown\n if (decision?.show && decision.experienceId) {\n // Try to get the 'per' value from our map, fall back to checking the input in trace\n let per: 'session' | 'day' | 'week' =\n experienceFrequencyMap.get(decision.experienceId) || 'session';\n\n // If not in map, try to infer from the decision trace\n if (!experienceFrequencyMap.has(decision.experienceId)) {\n const freqStep = decision.trace.find(\n (t: TraceStep) => t.step === 'check-frequency-cap'\n );\n if (freqStep?.input && typeof freqStep.input === 'object' && 'per' in freqStep.input) {\n per = (freqStep.input as { per: 'session' | 'day' | 'week' }).per;\n // Cache it for next time\n experienceFrequencyMap.set(decision.experienceId, per);\n }\n }\n\n recordImpression(decision.experienceId, per);\n }\n }\n });\n }\n};\n","/**\n * Deep merge utility with \"underwrite\" pattern.\n *\n * Recursively merges source into target, where **target values take precedence**.\n * This is the opposite of typical deep merge where source wins.\n *\n * This \"underwrite\" pattern is used for config defaults:\n * - User config (target) always wins\n * - Defaults (source) only fill in missing values\n *\n * @param target - Target object (takes precedence)\n * @param source - Source object (provides defaults)\n * @returns New merged object (does not mutate inputs)\n *\n * @example\n * ```typescript\n * const userConfig = { api: { timeout: 5000 } };\n * const defaults = { api: { timeout: 3000, retries: 3 }, debug: false };\n *\n * const result = deepMerge(target, source);\n * // Result: {\n * // api: { timeout: 5000, retries: 3 }, // timeout from user, retries from defaults\n * // debug: false // debug from defaults\n * // }\n * ```\n */\nexport function deepMerge(\n target: Record<string, any>,\n source: Record<string, any>\n): Record<string, any> {\n // Create a new object to avoid mutation\n const result: Record<string, any> = { ...target };\n\n for (const key in source) {\n if (!Object.hasOwn(source, key)) {\n continue;\n }\n\n const sourceValue = source[key];\n const targetValue = result[key];\n\n // If target has no value for this key, use source value\n if (targetValue === undefined) {\n result[key] = sourceValue;\n continue;\n }\n\n // If both are plain objects, recursively merge\n if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n }\n\n // Otherwise, target value wins (underwrite pattern)\n // result[key] is already set from { ...target }\n }\n\n return result;\n}\n\n/**\n * Check if value is a plain object (not array, null, Date, etc.)\n *\n * @param value - Value to check\n * @returns True if value is a plain object\n * @private\n */\nfunction isPlainObject(value: any): value is Record<string, any> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n // Check if it's a plain object (not Array, Date, RegExp, etc.)\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n","/**\n * Configuration management with dot-notation paths and underwrite pattern.\n *\n * The Config class manages SDK configuration with support for:\n * - Dot-notation paths for nested access (`'my.plugin.setting'`)\n * - Underwrite pattern for defaults (existing values take precedence)\n * - Required plugin tracking\n * - Immutable getAll() for safe access\n *\n * @example\n * ```typescript\n * const config = new Config({ api: { timeout: 5000 } });\n *\n * // Set defaults (won't overwrite existing timeout)\n * config.defaults({ api: { timeout: 3000, retries: 3 } });\n *\n * // Get with dot-notation\n * config.get('api.timeout'); // 5000\n * config.get('api.retries'); // 3\n *\n * // Set values\n * config.set('api.baseUrl', 'https://api.example.com');\n * ```\n */\n\nimport { deepMerge } from '../util/deep-merge';\n\nexport class Config {\n private data: Record<string, any> = {};\n private required = new Set<string>();\n\n /**\n * Create a new Config instance.\n *\n * @param initialConfig - Initial configuration object\n */\n constructor(initialConfig: Record<string, any> = {}) {\n // Deep copy to prevent external mutation\n this.data = JSON.parse(JSON.stringify(initialConfig));\n }\n\n /**\n * Set default configuration values using underwrite pattern.\n *\n * Existing configuration values always take precedence over defaults.\n * This allows plugins to provide defaults without overwriting user config.\n *\n * @param config - Default configuration object\n *\n * @example\n * ```typescript\n * // User provided config\n * const config = new Config({ api: { timeout: 10000 } });\n *\n * // Plugin sets defaults\n * config.defaults({\n * api: { timeout: 3000, retries: 3 },\n * debug: false\n * });\n *\n * // Result: { api: { timeout: 10000, retries: 3 }, debug: false }\n * // User's timeout (10000) wins over default (3000)\n * ```\n */\n defaults(config: Record<string, any>): void {\n // Use underwrite pattern: existing config (target) wins over defaults (source)\n this.data = deepMerge(this.data, config);\n }\n\n /**\n * Merge configuration values (new values override existing).\n *\n * New configuration values take precedence over existing values.\n * This is the opposite of defaults() and is used when user provides new config.\n *\n * @param config - Configuration object to merge\n *\n * @example\n * ```typescript\n * const config = new Config({ api: { timeout: 3000 } });\n *\n * // User provides new config\n * config.merge({ api: { timeout: 10000, retries: 3 } });\n *\n * // Result: { api: { timeout: 10000, retries: 3 } }\n * // New timeout (10000) wins over existing (3000)\n * ```\n */\n merge(config: Record<string, any>): void {\n // Regular merge: new config (source) wins over existing (target)\n this.data = deepMerge(config, this.data);\n }\n\n /**\n * Get a configuration value by dot-notation path.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @returns Configuration value or undefined if not found\n *\n * @example\n * ```typescript\n * config.get('api.timeout'); // 5000\n * config.get('api.retries'); // 3\n * config.get('nonexistent.path'); // undefined\n * config.get<number>('api.timeout'); // Type-safe access\n * ```\n */\n get<T = any>(path: string): T {\n const keys = path.split('.');\n let current: any = this.data;\n\n for (const key of keys) {\n if (current == null) {\n return undefined as T;\n }\n current = current[key];\n }\n\n return current as T;\n }\n\n /**\n * Set a configuration value by dot-notation path.\n *\n * Creates intermediate objects as needed.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @param value - Value to set\n *\n * @example\n * ```typescript\n * config.set('api.timeout', 5000);\n * config.set('api.headers.authorization', 'Bearer token');\n * config.set('deeply.nested.value', 42);\n * ```\n */\n set(path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop();\n if (!lastKey) return; // Guard against empty path\n\n let current: any = this.data;\n\n // Create intermediate objects\n for (const key of keys) {\n if (current[key] == null || typeof current[key] !== 'object') {\n current[key] = {};\n }\n current = current[key];\n }\n\n current[lastKey] = value;\n }\n\n /**\n * Mark a plugin namespace as required.\n *\n * Required plugins must be properly enabled for the SDK to function.\n *\n * @param namespace - Plugin namespace to mark as required\n *\n * @example\n * ```typescript\n * config.markRequired('analytics');\n * config.isRequired('analytics'); // true\n * ```\n */\n markRequired(namespace?: string): void {\n if (namespace !== undefined && namespace !== null) {\n this.required.add(namespace);\n }\n }\n\n /**\n * Check if a plugin namespace is marked as required.\n *\n * @param namespace - Plugin namespace to check\n * @returns True if the namespace is required\n */\n isRequired(namespace: string): boolean {\n return this.required.has(namespace);\n }\n\n /**\n * Get all configuration as an immutable copy.\n *\n * Returns a deep copy to prevent external mutation of config.\n *\n * @returns Copy of the entire configuration object\n *\n * @example\n * ```typescript\n * const allConfig = config.getAll();\n * allConfig.api = {}; // Does not affect internal config\n * ```\n */\n getAll(): Record<string, any> {\n // Deep copy to prevent nested mutation\n return JSON.parse(JSON.stringify(this.data));\n }\n}\n","/**\n * Event Emitter with wildcard pattern matching support.\n *\n * Supports wildcard patterns for event subscriptions:\n * - Exact match: `'widget.show'` matches `'widget.show'`\n * - Wildcard suffix: `'widget.*'` matches `'widget.show'`, `'widget.hide'`, etc.\n * - Wildcard prefix: `'*.show'` matches `'widget.show'`, `'modal.show'`, etc.\n * - Match all: `'*'` matches all events\n *\n * Uses regex compilation for efficient pattern matching.\n */\n\n/**\n * Subscription entry storing the pattern and handler.\n */\ninterface Subscription {\n pattern: string;\n compiledPattern: RegExp;\n handler: (...args: any[]) => void;\n}\n\nexport class Emitter {\n private subscriptions: Subscription[] = [];\n\n /**\n * Subscribe to an event or pattern.\n *\n * @param event - Event name or wildcard pattern\n * @param handler - Event handler function\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const emitter = new Emitter();\n *\n * // Exact match\n * emitter.on('user.login', (data) => console.log('Login:', data));\n *\n * // Wildcard patterns\n * emitter.on('user.*', (data) => console.log('User event:', data));\n * emitter.on('*.error', (data) => console.log('Error:', data));\n * emitter.on('*', (data) => console.log('Any event:', data));\n *\n * // Unsubscribe\n * const unsub = emitter.on('test', handler);\n * unsub();\n * ```\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n if (typeof handler !== 'function') {\n throw new TypeError('handler must be a function');\n }\n\n const subscription: Subscription = {\n pattern: event,\n compiledPattern: this.compilePattern(event),\n handler,\n };\n\n this.subscriptions.push(subscription);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Unsubscribe from an event or pattern.\n *\n * @param event - Event name or pattern to unsubscribe from\n * @param handler - Handler function to remove\n */\n off(event: string, handler: (...args: any[]) => void): void {\n this.subscriptions = this.subscriptions.filter(\n (sub) => !(sub.pattern === event && sub.handler === handler)\n );\n }\n\n /**\n * Emit an event to all matching subscribers.\n *\n * Notifies all handlers whose patterns match the event name.\n * Handlers are called with the provided arguments.\n * Errors in handlers are caught and logged to prevent breaking the event flow.\n *\n * @param event - Event name to emit\n * @param args - Arguments to pass to handlers\n *\n * @example\n * ```typescript\n * emitter.emit('user.login', { userId: '123' });\n * emitter.emit('widget.show', { id: 'modal-1' }, { animate: true });\n * ```\n */\n emit(event: string, ...args: any[]): void {\n for (const subscription of this.subscriptions) {\n if (subscription.compiledPattern.test(event)) {\n try {\n subscription.handler(...args);\n } catch (err) {\n console.error(`Error in event handler for \"${event}\":`, err);\n }\n }\n }\n }\n\n /**\n * Remove all event listeners.\n *\n * Useful for cleanup when destroying the SDK instance.\n */\n removeAllListeners(): void {\n this.subscriptions = [];\n }\n\n /**\n * Compile a pattern string into a RegExp for matching.\n *\n * Converts wildcard patterns into regular expressions:\n * - `widget.*` → `/^widget\\.(.*?)$/`\n * - `*.show` → `/^(.*?)\\.show$/`\n * - `*` → `/^(.*?)$/`\n *\n * @param pattern - Pattern string with optional wildcards\n * @returns Compiled RegExp for matching event names\n * @private\n */\n private compilePattern(pattern: string): RegExp {\n // Escape all regex special characters\n const escaped = this.escapeRegExp(pattern);\n // Replace escaped asterisks with wildcard capture groups\n const withWildcards = escaped.replace(/\\\\\\*/g, '(.*?)');\n // Anchor to start and end\n return new RegExp(`^${withWildcards}$`);\n }\n\n /**\n * Escape special regex characters in a string.\n *\n * @param str - String to escape\n * @returns Escaped string safe for use in RegExp\n * @private\n */\n private escapeRegExp(str: string): string {\n return str.replace(/[\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n}\n","/**\n * Expose capability for adding plugin methods to SDK instance.\n *\n * Plugins use this to add public API methods that users can call.\n * Methods are merged directly onto the SDK instance.\n *\n * @example\n * ```typescript\n * const expose = new Expose(sdkInstance);\n * expose.expose({\n * track(event: string) {\n * console.log('Tracking:', event);\n * }\n * });\n * // Now: sdk.track('page_view');\n * ```\n */\n\nexport class Expose {\n private sdk: any;\n\n /**\n * Create an Expose instance.\n *\n * @param sdk - SDK instance to expose methods on\n */\n constructor(sdk: any) {\n this.sdk = sdk;\n }\n\n /**\n * Expose methods on the SDK instance.\n *\n * Merges the provided methods object onto the SDK instance,\n * making them available as `sdk.methodName()`.\n *\n * @param api - Object containing methods to expose\n *\n * @example\n * ```typescript\n * expose.expose({\n * track(event: string, properties?: any) {\n * // Track event\n * },\n * identify(userId: string) {\n * // Identify user\n * }\n * });\n *\n * // Available as:\n * // sdk.track('page_view', { path: '/home' });\n * // sdk.identify('user-123');\n * ```\n */\n expose(api: Record<string, any>): void {\n Object.assign(this.sdk, api);\n }\n}\n","/**\n * Namespace capability for plugin identification.\n *\n * Each plugin must claim a unique namespace to identify itself.\n * Namespaces are used for config scoping and event namespacing.\n *\n * @example\n * ```typescript\n * const namespace = new Namespace();\n * namespace.ns('analytics.tracking');\n * console.log(namespace.name); // 'analytics.tracking'\n * ```\n */\n\nexport class Namespace {\n /**\n * The plugin's namespace.\n * Set via the `ns()` method, can only be set once.\n */\n name: string = '';\n\n /**\n * Set the plugin's namespace.\n *\n * Can only be called once per instance. Attempting to set it again throws an error.\n *\n * @param namespace - Dot-notation namespace (e.g., 'analytics.tracking')\n * @throws Error if namespace is already set\n *\n * @example\n * ```typescript\n * const ns = new Namespace();\n * ns.ns('my.plugin'); // Success\n * ns.ns('other.plugin'); // Throws Error\n * ```\n */\n ns(namespace: string): void {\n if (this.name) {\n throw new Error(\n `Namespace already set to \"${this.name}\". Cannot reassign to \"${namespace}\".`\n );\n }\n this.name = namespace;\n }\n}\n","/**\n * Main SDK class\n *\n * Composes all capabilities and provides the plugin registration system.\n * Follows functional plugin architecture with capability injection.\n */\n\nimport { Config } from './capabilities/config';\nimport { Emitter } from './capabilities/emitter';\nimport { Expose } from './capabilities/expose';\nimport { Namespace } from './capabilities/namespace';\nimport type { Plugin, PluginFunction, SDKConfig } from './types';\n\n/**\n * SDK - Main SDK class for building JavaScript SDKs\n *\n * @example\n * ```typescript\n * const sdk = new SDK({ name: 'my-sdk' });\n *\n * sdk.use((plugin, instance, config) => {\n * plugin.ns('my.plugin');\n * plugin.defaults({ my: { setting: 'value' } });\n * plugin.expose({\n * track(event: string) {\n * console.log('Tracking:', event);\n * }\n * });\n * });\n *\n * await sdk.init();\n * sdk.track('page_view');\n * ```\n */\nexport class SDK {\n /**\n * Configuration instance\n * @private\n */\n private configInstance: Config;\n\n /**\n * Event emitter instance\n * @private\n */\n private emitter: Emitter;\n\n /**\n * Registered plugins by namespace\n * @private\n */\n private plugins: Map<string, { namespace: Namespace; plugin: Plugin }> = new Map();\n\n /**\n * Initialization state\n * @private\n */\n private isInitialized = false;\n\n /**\n * Create a new SDK instance.\n *\n * @param config - Initial SDK configuration\n *\n * @example\n * ```typescript\n * const sdk = new SDK({\n * name: 'my-sdk',\n * api: {\n * endpoint: 'https://api.example.com',\n * timeout: 5000\n * }\n * });\n * ```\n */\n constructor(config: SDKConfig = {}) {\n this.emitter = new Emitter();\n this.configInstance = new Config(config);\n }\n\n /**\n * Register a plugin.\n *\n * Plugins receive capability-injected objects and can extend the SDK.\n * Supports method chaining.\n *\n * @param pluginFn - Plugin function\n * @returns this - For method chaining\n *\n * @example\n * ```typescript\n * sdk\n * .use(analyticsPlugin)\n * .use(trackingPlugin)\n * .init();\n * ```\n */\n use(pluginFn: PluginFunction): this {\n // Create capability instances for this plugin\n const namespace = new Namespace();\n const expose = new Expose(this);\n\n // Compose Plugin object with all capabilities\n const plugin: Plugin = {\n // Namespace capability\n ns: namespace.ns.bind(namespace),\n\n // Config capabilities\n defaults: this.configInstance.defaults.bind(this.configInstance),\n\n // Emitter capabilities\n on: this.emitter.on.bind(this.emitter),\n off: this.emitter.off.bind(this.emitter),\n emit: this.emitter.emit.bind(this.emitter),\n\n // Expose capability\n expose: expose.expose.bind(expose),\n\n // Requirer capability\n mustEnable: () => {\n if (namespace.name) {\n this.configInstance.markRequired(namespace.name);\n }\n },\n };\n\n // Execute plugin function with capability injection\n pluginFn(plugin, this, this.configInstance);\n\n // Store plugin by namespace\n if (namespace.name) {\n this.plugins.set(namespace.name, { namespace, plugin });\n }\n\n return this;\n }\n\n /**\n * Initialize the SDK.\n *\n * Emits `sdk:init` event before initialization and `sdk:ready` after.\n * Idempotent - can be called multiple times safely.\n *\n * @param config - Optional configuration to merge with existing config\n * @returns Promise that resolves when initialization is complete\n *\n * @example\n * ```typescript\n * sdk.on('sdk:ready', () => {\n * console.log('SDK is ready!');\n * });\n *\n * await sdk.init({ api: { timeout: 5000 } });\n * ```\n */\n async init(config?: SDKConfig): Promise<void> {\n if (this.isInitialized) {\n console.warn('SDK already initialized');\n return;\n }\n\n // Merge config if provided (new values override defaults)\n if (config) {\n this.configInstance.merge(config);\n }\n\n // Emit init event (plugins can listen for this)\n this.emitter.emit('sdk:init');\n\n // Check for required plugins\n const requiredNamespaces = Array.from(this.plugins.keys()).filter((ns) =>\n this.configInstance.isRequired(ns)\n );\n\n for (const ns of requiredNamespaces) {\n if (!this.plugins.has(ns)) {\n throw new Error(`Required plugin \"${ns}\" is not registered`);\n }\n }\n\n this.isInitialized = true;\n\n // Emit ready event\n this.emitter.emit('sdk:ready');\n }\n\n /**\n * Destroy the SDK.\n *\n * Emits `sdk:destroy` event, clears all plugins, and removes all event listeners.\n *\n * @returns Promise that resolves when destruction is complete\n *\n * @example\n * ```typescript\n * await sdk.destroy();\n * ```\n */\n async destroy(): Promise<void> {\n // Emit destroy event (plugins can listen for cleanup)\n this.emitter.emit('sdk:destroy');\n\n // Clear plugins\n this.plugins.clear();\n\n // Remove all event listeners\n this.emitter.removeAllListeners();\n\n this.isInitialized = false;\n }\n\n /**\n * Get a configuration value by path.\n *\n * Delegates to the Config capability.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @returns Configuration value\n *\n * @example\n * ```typescript\n * const timeout = sdk.get('api.timeout');\n * const nested = sdk.get('my.plugin.setting');\n * ```\n */\n get<T = any>(path: string): T {\n return this.configInstance.get(path);\n }\n\n /**\n * Set a configuration value by path.\n *\n * Delegates to the Config capability.\n *\n * @param path - Dot-notation path (e.g., 'api.timeout')\n * @param value - Value to set\n *\n * @example\n * ```typescript\n * sdk.set('api.timeout', 10000);\n * sdk.set('my.plugin.enabled', true);\n * ```\n */\n set(path: string, value: any): void {\n this.configInstance.set(path, value);\n }\n\n /**\n * Subscribe to an event.\n *\n * Delegates to the Emitter capability. Supports wildcard patterns.\n *\n * @param event - Event name or pattern (e.g., 'track:*')\n * @param handler - Event handler function\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = sdk.on('track:page', (data) => {\n * console.log('Page tracked:', data);\n * });\n *\n * // Later...\n * unsubscribe();\n * ```\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n return this.emitter.on(event, handler);\n }\n\n /**\n * Unsubscribe from an event.\n *\n * Delegates to the Emitter capability.\n *\n * @param event - Event name\n * @param handler - Event handler function to remove\n *\n * @example\n * ```typescript\n * const handler = () => console.log('ready');\n * sdk.on('sdk:ready', handler);\n * sdk.off('sdk:ready', handler);\n * ```\n */\n off(event: string, handler: (...args: any[]) => void): void {\n this.emitter.off(event, handler);\n }\n\n /**\n * Emit an event.\n *\n * Delegates to the Emitter capability.\n *\n * @param event - Event name\n * @param args - Event arguments\n *\n * @example\n * ```typescript\n * sdk.emit('custom:event', { data: 'value' });\n * ```\n */\n emit(event: string, ...args: any[]): void {\n this.emitter.emit(event, ...args);\n }\n\n /**\n * Get all configuration as an immutable copy.\n *\n * Delegates to the Config capability.\n *\n * @returns Copy of the entire configuration object\n *\n * @example\n * ```typescript\n * const allConfig = sdk.getAll();\n * console.log(allConfig);\n * ```\n */\n getAll(): Record<string, any> {\n return this.configInstance.getAll();\n }\n\n /**\n * Check if SDK is initialized.\n *\n * @returns true if initialized, false otherwise\n *\n * @example\n * ```typescript\n * if (sdk.isReady()) {\n * sdk.track('event');\n * }\n * ```\n */\n isReady(): boolean {\n return this.isInitialized;\n }\n}\n","import { SDK } from '@lytics/sdk-kit';\nimport { storagePlugin } from '@lytics/sdk-kit-plugins';\nimport { bannerPlugin, debugPlugin, frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';\nimport type {\n Context,\n Decision,\n Experience,\n ExperienceConfig,\n RuntimeState,\n TraceStep,\n UrlRule,\n} from './types';\n\n/**\n * Experience Runtime\n *\n * Core class that manages experience registration and evaluation.\n * Built on @lytics/sdk-kit for plugin system and lifecycle management.\n *\n * Design principles:\n * - Pure functions for evaluation logic (easy to test)\n * - Event-driven architecture (extensible via plugins)\n * - Explainability-first (every decision has reasons)\n */\nexport class ExperienceRuntime {\n private sdk: SDK;\n private experiences: Map<string, Experience> = new Map();\n private decisions: Decision[] = [];\n private initialized = false;\n private destroyed = false;\n\n constructor(config: ExperienceConfig = {}) {\n // Create SDK instance\n this.sdk = new SDK({\n name: 'experience-sdk',\n ...config,\n });\n\n // Auto-register plugins\n this.sdk.use(storagePlugin);\n this.sdk.use(debugPlugin);\n this.sdk.use(frequencyPlugin);\n this.sdk.use(bannerPlugin);\n }\n\n /**\n * Initialize the runtime\n */\n async init(config?: ExperienceConfig): Promise<void> {\n if (this.initialized) {\n console.warn('[experiences] Already initialized');\n return;\n }\n\n // Recreate SDK if it was destroyed\n if (this.destroyed) {\n this.sdk = new SDK({\n name: 'experience-sdk',\n ...config,\n });\n\n // Re-register core plugins\n this.sdk.use(storagePlugin);\n this.sdk.use(debugPlugin);\n this.sdk.use(frequencyPlugin);\n this.sdk.use(bannerPlugin);\n\n this.destroyed = false;\n }\n\n if (config) {\n // Merge config if provided\n Object.entries(config).forEach(([key, value]) => {\n this.sdk.set(key, value);\n });\n }\n\n // Initialize SDK (will init all plugins)\n await this.sdk.init();\n\n this.initialized = true;\n\n // Emit ready event\n this.sdk.emit('experiences:ready');\n }\n\n /**\n * Register an experience\n */\n register(id: string, experience: Omit<Experience, 'id'>): void {\n const exp: Experience = { id, ...experience };\n this.experiences.set(id, exp);\n\n // Register frequency config with frequency plugin if it exists\n if (exp.frequency && (this.sdk as any).frequency?._registerExperience) {\n (this.sdk as any).frequency._registerExperience(id, exp.frequency.per);\n }\n\n this.sdk.emit('experiences:registered', { id, experience: exp });\n }\n\n /**\n * Evaluate experiences against context\n * Returns decision with explainability\n * First match wins (use evaluateAll() for multiple experiences)\n */\n evaluate(context?: Partial<Context>): Decision {\n const startTime = Date.now();\n const evalContext = buildContext(context);\n\n // Find matching experience\n let matchedExperience: Experience | undefined;\n const allReasons: string[] = [];\n const allTrace: TraceStep[] = [];\n\n for (const [, experience] of this.experiences) {\n const result = evaluateExperience(experience, evalContext);\n\n allReasons.push(...result.reasons);\n allTrace.push(...result.trace);\n\n if (result.matched) {\n // Check frequency cap if experience has frequency rules\n if (experience.frequency && (this.sdk as any).frequency) {\n const freqStart = Date.now();\n const hasReached = (this.sdk as any).frequency.hasReachedCap(\n experience.id,\n experience.frequency.max,\n experience.frequency.per\n );\n\n allTrace.push({\n step: 'check-frequency-cap',\n timestamp: freqStart,\n duration: Date.now() - freqStart,\n input: experience.frequency,\n output: hasReached,\n passed: !hasReached,\n });\n\n if (hasReached) {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n allReasons.push(\n `Frequency cap reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n continue; // Skip this experience, check next\n }\n\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n allReasons.push(\n `Frequency cap not reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n }\n\n matchedExperience = experience;\n break; // First match wins\n }\n }\n\n const decision: Decision = {\n show: !!matchedExperience,\n experienceId: matchedExperience?.id,\n reasons: allReasons,\n trace: allTrace,\n context: evalContext,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: Date.now() - startTime,\n experiencesEvaluated: this.experiences.size,\n },\n };\n\n // Store decision for inspection\n this.decisions.push(decision);\n\n // Emit for plugins to react (include matched experience for rendering)\n this.sdk.emit('experiences:evaluated', {\n decision,\n experience: matchedExperience,\n });\n\n return decision;\n }\n\n /**\n * Evaluate all experiences against context\n * Returns multiple decisions (sorted by priority)\n * All matching experiences will be shown\n */\n evaluateAll(context?: Partial<Context>): Decision[] {\n const evalContext = buildContext(context);\n\n // Sort experiences by priority (higher = more important)\n // Ties maintain registration order (Map preserves insertion order)\n const sortedExperiences = Array.from(this.experiences.values()).sort((a, b) => {\n const priorityA = a.priority ?? 0;\n const priorityB = b.priority ?? 0;\n return priorityB - priorityA; // Descending order\n });\n\n const decisions: Decision[] = [];\n\n // Evaluate each experience\n for (const experience of sortedExperiences) {\n const expStartTime = Date.now();\n const result = evaluateExperience(experience, evalContext);\n\n let show = result.matched;\n const reasons = [...result.reasons];\n const trace = [...result.trace];\n\n // Check frequency cap if experience has frequency rules\n if (show && experience.frequency && (this.sdk as any).frequency) {\n const freqStart = Date.now();\n const hasReached = (this.sdk as any).frequency.hasReachedCap(\n experience.id,\n experience.frequency.max,\n experience.frequency.per\n );\n\n trace.push({\n step: 'check-frequency-cap',\n timestamp: freqStart,\n duration: Date.now() - freqStart,\n input: experience.frequency,\n output: hasReached,\n passed: !hasReached,\n });\n\n if (hasReached) {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n reasons.push(\n `Frequency cap reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n show = false;\n } else {\n const count = (this.sdk as any).frequency.getImpressionCount(\n experience.id,\n experience.frequency.per\n );\n reasons.push(\n `Frequency cap not reached (${count}/${experience.frequency.max} this ${experience.frequency.per})`\n );\n }\n }\n\n const decision: Decision = {\n show,\n experienceId: experience.id,\n reasons,\n trace,\n context: evalContext,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: Date.now() - expStartTime,\n experiencesEvaluated: 1,\n },\n };\n\n decisions.push(decision);\n this.decisions.push(decision);\n }\n\n // Emit single event with all decisions (array)\n // Plugins can filter to their relevant experiences\n const matchedDecisions = decisions.filter((d) => d.show);\n const matchedExperiences = matchedDecisions\n .map((d) => d.experienceId && this.experiences.get(d.experienceId))\n .filter((exp): exp is Experience => exp !== undefined);\n\n this.sdk.emit(\n 'experiences:evaluated',\n matchedDecisions.map((decision, index) => ({\n decision,\n experience: matchedExperiences[index],\n }))\n );\n\n return decisions;\n }\n\n /**\n * Explain a specific experience\n */\n explain(experienceId: string): Decision | null {\n const experience = this.experiences.get(experienceId);\n if (!experience) {\n return null;\n }\n\n const context = buildContext();\n const result = evaluateExperience(experience, context);\n\n return {\n show: result.matched,\n experienceId,\n reasons: result.reasons,\n trace: result.trace,\n context,\n metadata: {\n evaluatedAt: Date.now(),\n totalDuration: 0,\n experiencesEvaluated: 1,\n },\n };\n }\n\n /**\n * Get runtime state (for inspection)\n */\n getState(): RuntimeState {\n return {\n initialized: this.initialized,\n experiences: new Map(this.experiences),\n decisions: [...this.decisions],\n config: this.sdk ? this.sdk.getAll() : {},\n };\n }\n\n /**\n * Event subscription (proxy to SDK)\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n return this.sdk.on(event, handler);\n }\n\n /**\n * Destroy runtime\n */\n async destroy(): Promise<void> {\n if (this.sdk) {\n await this.sdk.destroy();\n }\n this.destroyed = true;\n this.experiences.clear();\n this.decisions = [];\n this.initialized = false;\n }\n}\n\n// Pure functions for evaluation logic (easy to test, no dependencies)\n\n/**\n * Build evaluation context from partial input\n * Pure function - no side effects\n */\nexport function buildContext(partial?: Partial<Context>): Context {\n return {\n url: partial?.url ?? (typeof window !== 'undefined' ? window.location.href : ''),\n timestamp: Date.now(),\n user: partial?.user,\n custom: partial?.custom,\n };\n}\n\n/**\n * Evaluate an experience against context\n * Pure function - returns reasons and trace\n */\nexport function evaluateExperience(\n experience: Experience,\n context: Context\n): { matched: boolean; reasons: string[]; trace: TraceStep[] } {\n const reasons: string[] = [];\n const trace: TraceStep[] = [];\n let matched = true;\n\n // Evaluate URL rule\n if (experience.targeting.url) {\n const urlStart = Date.now();\n const urlMatch = evaluateUrlRule(experience.targeting.url, context.url);\n\n trace.push({\n step: 'evaluate-url-rule',\n timestamp: urlStart,\n duration: Date.now() - urlStart,\n input: { rule: experience.targeting.url, url: context.url },\n output: urlMatch,\n passed: urlMatch,\n });\n\n if (urlMatch) {\n reasons.push('URL matches targeting rule');\n } else {\n reasons.push('URL does not match targeting rule');\n matched = false;\n }\n }\n\n return { matched, reasons, trace };\n}\n\n/**\n * Evaluate URL targeting rule\n * Pure function - deterministic output\n */\nexport function evaluateUrlRule(rule: UrlRule, url: string = ''): boolean {\n // Check equals (exact match)\n if (rule.equals !== undefined) {\n return url === rule.equals;\n }\n\n // Check contains (substring match)\n if (rule.contains !== undefined) {\n return url.includes(rule.contains);\n }\n\n // Check matches (regex match)\n if (rule.matches !== undefined) {\n return rule.matches.test(url);\n }\n\n // No rules specified = match all\n return true;\n}\n","/**\n * Singleton Pattern Implementation\n *\n * Provides a default singleton instance with convenient wrapper functions\n * for simple use cases, plus createInstance() for advanced scenarios.\n */\n\nimport { ExperienceRuntime } from './runtime';\nimport type { Context, Decision, Experience, ExperienceConfig, RuntimeState } from './types';\n\n/**\n * Create a new Experience SDK instance\n *\n * Use this for advanced scenarios where you need multiple isolated runtimes.\n *\n * @example\n * ```typescript\n * import { createInstance } from '@prosdevlab/experience-sdk';\n *\n * const exp = createInstance({ debug: true });\n * await exp.init();\n * exp.register('welcome', { ... });\n * ```\n */\nexport function createInstance(config?: ExperienceConfig): ExperienceRuntime {\n return new ExperienceRuntime(config);\n}\n\n/**\n * Default singleton instance\n *\n * Provides a convenient global instance for simple use cases.\n * For script tag users, this is exposed as the global `experiences` object.\n */\nconst defaultInstance = createInstance();\n\n/**\n * Initialize the Experience SDK\n *\n * @example\n * ```typescript\n * import { init } from '@prosdevlab/experience-sdk';\n * await init({ debug: true });\n * ```\n */\nexport async function init(config?: ExperienceConfig): Promise<void> {\n return defaultInstance.init(config);\n}\n\n/**\n * Register an experience\n *\n * @example\n * ```typescript\n * import { register } from '@prosdevlab/experience-sdk';\n *\n * register('welcome-banner', {\n * type: 'banner',\n * targeting: { url: { contains: '/' } },\n * content: { title: 'Welcome!', message: 'Thanks for visiting' }\n * });\n * ```\n */\nexport function register(id: string, experience: Omit<Experience, 'id'>): void {\n defaultInstance.register(id, experience);\n}\n\n/**\n * Evaluate experiences against current context\n * First match wins (use evaluateAll() for multiple experiences)\n *\n * @example\n * ```typescript\n * import { evaluate } from '@prosdevlab/experience-sdk';\n *\n * const decision = evaluate({ url: window.location.href });\n * if (decision.show) {\n * console.log('Show experience:', decision.experienceId);\n * console.log('Reasons:', decision.reasons);\n * }\n * ```\n */\nexport function evaluate(context?: Partial<Context>): Decision {\n return defaultInstance.evaluate(context);\n}\n\n/**\n * Evaluate all experiences against current context\n * Returns array of decisions sorted by priority (higher = more important)\n * All matching experiences will be shown\n *\n * @example\n * ```typescript\n * import { evaluateAll } from '@prosdevlab/experience-sdk';\n *\n * const decisions = evaluateAll({ url: window.location.href });\n * decisions.forEach(decision => {\n * if (decision.show) {\n * console.log('Show:', decision.experienceId);\n * console.log('Reasons:', decision.reasons);\n * }\n * });\n * ```\n */\nexport function evaluateAll(context?: Partial<Context>): Decision[] {\n return defaultInstance.evaluateAll(context);\n}\n\n/**\n * Explain why a specific experience would/wouldn't show\n *\n * @example\n * ```typescript\n * import { explain } from '@prosdevlab/experience-sdk';\n *\n * const explanation = explain('welcome-banner');\n * console.log('Would show?', explanation?.show);\n * console.log('Reasons:', explanation?.reasons);\n * ```\n */\nexport function explain(experienceId: string): Decision | null {\n return defaultInstance.explain(experienceId);\n}\n\n/**\n * Get current runtime state\n *\n * @example\n * ```typescript\n * import { getState } from '@prosdevlab/experience-sdk';\n *\n * const state = getState();\n * console.log('Initialized?', state.initialized);\n * console.log('Experiences:', Array.from(state.experiences.keys()));\n * ```\n */\nexport function getState(): RuntimeState {\n return defaultInstance.getState();\n}\n\n/**\n * Subscribe to SDK events\n *\n * @example\n * ```typescript\n * import { on } from '@prosdevlab/experience-sdk';\n *\n * const unsubscribe = on('experiences:evaluated', (decision) => {\n * console.log('Evaluation:', decision);\n * });\n *\n * // Later: unsubscribe()\n * ```\n */\nexport function on(event: string, handler: (...args: unknown[]) => void): () => void {\n return defaultInstance.on(event, handler);\n}\n\n/**\n * Destroy the SDK instance\n *\n * @example\n * ```typescript\n * import { destroy } from '@prosdevlab/experience-sdk';\n * await destroy();\n * ```\n */\nexport async function destroy(): Promise<void> {\n return defaultInstance.destroy();\n}\n\n/**\n * Default export for convenient importing\n *\n * @example\n * ```typescript\n * import experiences from '@prosdevlab/experience-sdk';\n * await experiences.init();\n * ```\n */\nexport const experiences = {\n createInstance,\n init,\n register,\n evaluate,\n evaluateAll,\n explain,\n getState,\n on,\n destroy,\n};\n\n/**\n * Global singleton instance for IIFE builds\n *\n * When loaded via script tag, this object is available as `window.experiences`\n */\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).experiences = experiences;\n}\n"]}