@vircle/sdk-web 0.4.0 → 0.6.1
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.
- package/README.md +68 -18
- package/dist/index.d.ts +118 -3
- package/dist/index.esm.js +321 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +321 -4
- package/dist/index.js.map +1 -1
- package/dist/vircle-web-sdk.min.js +1 -1
- package/dist/vircle-web-sdk.min.js.map +1 -1
- package/dist/vircle-web-sdk.standalone.esm.js +1 -1
- package/dist/vircle-web-sdk.standalone.esm.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),t=class{static create(e,t,i){const s=(new Date).toISOString();return{id:e||void 0,anonymousId:i||this.generateAnonymousId(),traits:t||{},preferences:this.getDefaultPreferences(),createdAt:s,updatedAt:s}}static generateAnonymousId(){return`anon_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}static getDefaultPreferences(){let e="en";try{"undefined"!=typeof navigator&&navigator&&"language"in navigator&&"string"==typeof navigator.language&&navigator.language.length>0&&(e=navigator.language.split("-")[0])}catch(e){}let t="UTC";try{if("undefined"!=typeof Intl&&Intl&&Intl.DateTimeFormat){t=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}}catch(e){}return{language:e,timezone:t,theme:"auto",notifications:{email:!1,push:!1,sms:!1},privacy:{analytics:!0,marketing:!1,functional:!0}}}},i={UNKNOWN_ERROR:{code:"UNKNOWN_ERROR",severity:"high",category:"system",retryable:!1,userMessage:"An unknown error occurred"},INITIALIZATION_ERROR:{code:"INITIALIZATION_ERROR",severity:"critical",category:"configuration",retryable:!1,userMessage:"Failed to initialize SDK"},MISSING_API_KEY:{code:"MISSING_API_KEY",severity:"critical",category:"configuration",retryable:!1,userMessage:"API key is required",troubleshooting:["Check that apiKey is provided in configuration","Verify API key is not empty or null"]},NETWORK_ERROR:{code:"NETWORK_ERROR",severity:"medium",category:"network",retryable:!0,userMessage:"Network connection failed"},REQUEST_TIMEOUT:{code:"REQUEST_TIMEOUT",severity:"medium",category:"network",retryable:!0,userMessage:"Request timed out"},VALIDATION_ERROR:{code:"VALIDATION_ERROR",severity:"medium",category:"validation",retryable:!1,userMessage:"Data validation failed"},EVENT_TOO_LARGE:{code:"EVENT_TOO_LARGE",severity:"medium",category:"validation",retryable:!1,userMessage:"Event size exceeds maximum limit",troubleshooting:["Reduce event payload size","Remove unnecessary properties","Consider splitting large events"]},STORAGE_UNAVAILABLE:{code:"STORAGE_UNAVAILABLE",severity:"high",category:"storage",retryable:!1,userMessage:"Storage is not available"},PLUGIN_NOT_FOUND:{code:"PLUGIN_NOT_FOUND",severity:"medium",category:"plugin",retryable:!1,userMessage:"Plugin not found"},FEATURE_NOT_SUPPORTED:{code:"FEATURE_NOT_SUPPORTED",severity:"low",category:"feature",retryable:!1,userMessage:"Feature is not supported in this environment"},CONSENT_REQUIRED:{code:"CONSENT_REQUIRED",severity:"medium",category:"privacy",retryable:!1,userMessage:"User consent is required for data collection"},ENCRYPTION_ERROR:{code:"ENCRYPTION_ERROR",severity:"high",category:"system",retryable:!1,userMessage:"Data encryption failed",troubleshooting:["Ensure the provided public key is valid and in the correct format (DER-encoded SPKI, then Base64)","Verify that the crypto environment (Web Crypto API or Node.js crypto) is available and not corrupted"]}},s=class e extends Error{constructor(t,s,r={}){const n=i[t]||i.UNKNOWN_ERROR;super(s||n.userMessage||`Error: ${t}`),this.name="VircleError",this.code=t,this.timestamp=r.timestamp||(new Date).toISOString(),this.context=r.context||{},this.requestId=r.requestId,this.userId=r.userId,this.sessionId=r.sessionId,this.cause=r.cause,this.metadata={...n,...r.metadata},this.severity=this.metadata.severity,this.category=this.metadata.category,this.retryable=this.metadata.retryable,Error.captureStackTrace&&Error.captureStackTrace(this,e)}toJSON(){return{name:this.name,code:this.code,message:this.message,severity:this.severity,category:this.category,retryable:this.retryable,timestamp:this.timestamp,context:this.context,requestId:this.requestId,userId:this.userId,sessionId:this.sessionId,stack:this.stack,cause:this.cause?{name:this.cause.name,message:this.cause.message,stack:this.cause.stack}:void 0,metadata:this.metadata}}getUserMessage(){return this.metadata.userMessage||this.message}getTroubleshooting(){return this.metadata.troubleshooting||[]}shouldRetry(){return this.retryable}static fromHttpError(t,i,s={}){let r;switch(t){case 400:r="VALIDATION_ERROR";break;case 401:r="UNAUTHORIZED";break;case 403:r="FORBIDDEN";break;case 404:r="NOT_FOUND";break;case 408:case 504:r="REQUEST_TIMEOUT";break;case 413:r="EVENT_TOO_LARGE";break;case 429:r="TOO_MANY_REQUESTS";break;case 500:case 502:r="SERVER_ERROR";break;case 503:r="SERVICE_UNAVAILABLE";break;default:r="NETWORK_ERROR"}return new e(r,i,{...s,context:{...s.context,httpStatus:t}})}static fromError(t,i="UNKNOWN_ERROR",s={}){return new e(i,t.message,{...s,cause:t})}},r=class extends s{constructor(e,t={}){super("INVALID_CONFIGURATION",e,t),this.name="ConfigurationError"}},n=class extends s{constructor(e,t=[],i={}){super("VALIDATION_ERROR",e,i),this.name="ValidationError",this.validationErrors=t}toJSON(){return{...super.toJSON(),validationErrors:this.validationErrors}}},o=class extends s{constructor(e,t,i={}){super(t&&t>=500?"SERVER_ERROR":"NETWORK_ERROR",e,i),this.name="NetworkError",this.httpStatus=t,this.responseBody=i.context?.responseBody}toJSON(){return{...super.toJSON(),httpStatus:this.httpStatus,responseBody:this.responseBody}}},a=class extends s{constructor(e,t,i="PLUGIN_ERROR",s={}){super(i,t,{...s,context:{...s.context,pluginName:e}}),this.name="PluginError",this.pluginName=e}toJSON(){return{...super.toJSON(),pluginName:this.pluginName}}},c=class extends s{constructor(e,t="STORAGE_ERROR",i={}){super(t,e,i),this.name="StorageError"}},l=class{constructor(e,t={}){this.disposed=!1,this.config=e,this.options={autoEnrich:!0,enableValidation:!0,maxEventSize:102400,...t},this.contextService=t.contextService,this.pluginService=t.pluginService,this.storageService=t.storageService,this.transportService=t.transportService}async track(e){if(this.disposed)throw new s("SERVICE_DISPOSED","EventService has been disposed");try{let t=await this.processEvent(e);this.pluginService&&(t=await this.pluginService.executeHook("beforeEventSend",t)),this.transportService?(this.config.debug&&console.log("[EventService] Sending event to transport:",t.name),await this.transportService.send(t),this.config.debug&&console.log("[EventService] Event sent to transport successfully:",t.name)):this.config.debug&&console.warn("[EventService] No transport service available"),this.pluginService&&await this.pluginService.executeHook("afterEventSend",t)}catch(t){throw this.pluginService&&await this.pluginService.executeHook("onError",{error:t,context:{event:e}}),t}}createEvent(e){return new u(this,e)}async processEvent(e){let t={...e};if(this.options.autoEnrich&&(t=await this.enrichEvent(t)),this.options.maxEventSize){const e=this.calculateEventSize(t);if(e>this.options.maxEventSize)throw new s("EVENT_TOO_LARGE",`Event size (${e} bytes) exceeds maximum allowed size (${this.options.maxEventSize} bytes)`)}return t}async enrichEvent(e){const t={...e};if(t.timestamp||(t.timestamp=(new Date).toISOString()),this.contextService)try{const e=await this.contextService.collectAutoContext();e.context&&(t.context=this.mergeContext(e.context,t.context||{}))}catch(e){const t=new Error(`Failed to collect auto context: ${e.message}`);this.options.onNonCriticalError&&this.options.onNonCriticalError(t)}return t}mergeContext(e,t){return{...e,...t}}calculateEventSize(e){try{return new Blob([JSON.stringify(e)]).size}catch{return 2*JSON.stringify(e).length}}dispose(){this.disposed||(this.disposed=!0,this.contextService=void 0,this.pluginService=void 0,this.storageService=void 0,this.transportService=void 0,this.config={},this.options={})}isDisposed(){return this.disposed}},u=class{constructor(e,t){this.event={},this.eventService=e,t&&(this.event.name=t)}name(e){return this.event.name=e,this}userId(e){return this.event.userId=e,this}sessionId(e){return this.event.sessionId=e,this}properties(e){return this.event.properties={...this.event.properties,...e},this}property(e,t){return this.event.properties||(this.event.properties={}),this.event.properties[e]=t,this}context(e){return this.event.context={...this.event.context,...e},this}device(e){return this.event.context||(this.event.context={}),this.event.context.device={...this.event.context.device,...e},this}app(e){return this.event.context||(this.event.context={}),this.event.context.app={...this.event.context.app,...e},this}page(e){return this.event.context||(this.event.context={}),this.event.context.page={...this.event.context.page,...e},this}campaign(e){return this.event.context||(this.event.context={}),this.event.context.campaign={...this.event.context.campaign,...e},this}custom(e,t){return this.event.context||(this.event.context={}),this.event.context.custom||(this.event.context.custom={}),this.event.context.custom[e]=t,this}track(){const e=this.build();return this.eventService.track(e)}build(){if(!this.event.name)throw new s("VALIDATION_ERROR","Event name is required");return{name:this.event.name,timestamp:this.event.timestamp,userId:this.event.userId,sessionId:this.event.sessionId,properties:this.event.properties||{},context:this.event.context||{}}}},h=class{constructor(e){this.config={...e}}getConfig(){return{...this.config}}updateConfig(e){this.config={...this.config,...e}}get(e){return this.config[e]}set(e,t){this.config[e]=t}},d=class{constructor(e){this.config=e}async collectAutoContext(){const e={},t=[],i=[],s=this.config.autoCollect||{};try{if(s.device){const s=await this.collectDeviceInfo();s.device&&(e.device=s.device),t.push(...s.warnings||[]),i.push(...s.errors||[])}if(s.app){const s=await this.collectAppInfo();s.app&&(e.app=s.app),t.push(...s.warnings||[]),i.push(...s.errors||[])}if(s.page&&this.isWebEnvironment()){const i=this.collectPageInfo();i.page&&(e.page=i.page),t.push(...i.warnings||[])}if(s.userAgent){const t=this.collectUserAgent();t.userAgent&&(e.userAgent=t.userAgent)}if(s.referrer&&this.isWebEnvironment()){const t=this.collectReferrer();t.referrer&&(e.referrer=t.referrer)}if(s.campaign){const t=this.collectCampaignInfo();t.campaign&&(e.campaign=t.campaign)}if(s.performance&&this.isWebEnvironment()){const i=this.collectPerformanceInfo();i.performance&&(e.performance=i.performance),t.push(...i.warnings||[])}}catch(e){i.push(`Failed to collect auto context: ${e.message}`)}return{context:e,warnings:t,errors:i}}async collectDeviceInfo(){if(this.cachedDeviceInfo)return{device:this.cachedDeviceInfo};const e=[],t=[],i={};try{if(this.isReactNativeEnvironment()){e.push("Limited device info available in React Native - use platform-specific adapter for full info"),i.type="mobile";try{"undefined"!=typeof Intl&&Intl&&Intl.DateTimeFormat&&(i.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone)}catch(e){i.timezone="UTC"}return this.cachedDeviceInfo=i,{device:this.cachedDeviceInfo,warnings:e}}if(this.isWebEnvironment()&&"undefined"!=typeof navigator){const t=navigator.userAgent;if(t.includes("Chrome")){i.browser="Chrome";const e=t.match(/Chrome\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}else if(t.includes("Firefox")){i.browser="Firefox";const e=t.match(/Firefox\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}else if(t.includes("Safari")){i.browser="Safari";const e=t.match(/Version\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}if(t.includes("Windows")){i.os="Windows";const e=t.match(/Windows NT (\d+\.?\d*)/);e&&(i.osVersion=e[1])}else if(t.includes("Mac OS")){i.os="macOS";const e=t.match(/Mac OS X (\d+_?\d*)/);e&&(i.osVersion=e[1].replace("_","."))}else t.includes("Linux")&&(i.os="Linux");this.isMobileEnvironment()?i.type="mobile":t.includes("Tablet")||t.includes("iPad")?i.type="tablet":i.type="desktop";try{"language"in navigator&&"string"==typeof navigator.language&&navigator.language.length>0&&(i.language=navigator.language)}catch(e){}"undefined"!=typeof screen?i.screenResolution=`${screen.width}x${screen.height}`:"undefined"!=typeof window&&window.screen&&(i.screenResolution=`${window.screen.width}x${window.screen.height}`),"undefined"!=typeof window&&window.innerWidth&&window.innerHeight&&(i.viewport={width:window.innerWidth,height:window.innerHeight});try{i.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(t){e.push("Failed to detect timezone")}}else e.push("Navigator API not available - limited device info");return this.cachedDeviceInfo=i,{device:this.cachedDeviceInfo,warnings:e,errors:t}}catch(i){return t.push(`Failed to collect device info: ${i.message}`),{warnings:e,errors:t}}}async collectAppInfo(){if(this.cachedAppInfo)return{app:this.cachedAppInfo};const e=[],t=[],i={};try{if(this.isWebEnvironment()&&"undefined"!=typeof document&&(i.name=document.title||"Unknown Web App"),"undefined"!=typeof process&&process.env){i.version=process.env.npm_package_version||process.env.APP_VERSION,i.build=process.env.BUILD_NUMBER;const e=process.env.NODE_ENV;"development"!==e&&"production"!==e||(i.environment=e)}return this.cachedAppInfo=i,{app:this.cachedAppInfo,warnings:e,errors:t}}catch(i){return t.push(`Failed to collect app info: ${i.message}`),{warnings:e,errors:t}}}collectPageInfo(){if(!this.isWebEnvironment()||"undefined"==typeof document)return{warnings:["Page info collection only available in web environment"]};const e={},t=[];try{e.title=document.title,e.url=window.location.href,e.path=window.location.pathname,e.search=window.location.search,e.hash=window.location.hash,e.referrer=document.referrer;const i={};return document.querySelectorAll("meta[name], meta[property]").forEach(e=>{const t=e.getAttribute("name")||e.getAttribute("property"),s=e.getAttribute("content");t&&s&&(i[t]=s)}),Object.keys(i).length>0&&(e.meta=i),{page:e,warnings:t}}catch(e){return t.push(`Failed to collect page info: ${e.message}`),{warnings:t}}}collectUserAgent(){return"undefined"!=typeof navigator&&navigator.userAgent?{userAgent:navigator.userAgent}:{}}collectReferrer(){return this.isWebEnvironment()&&"undefined"!=typeof document&&document.referrer?{referrer:document.referrer}:{}}collectCampaignInfo(){if(!this.isWebEnvironment()||"undefined"==typeof window)return{};const e={},t=new URLSearchParams(window.location.search);let i=!1;["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(s=>{const r=t.get(s);r&&(e[s]=r,i=!0)});return["gclid","fbclid","msclkid","ttclid"].forEach(s=>{const r=t.get(s);r&&(e[s]=r,i=!0)}),i?{campaign:e}:{}}collectPerformanceInfo(){if(!this.isWebEnvironment()||"undefined"==typeof window||!window.performance)return{warnings:["Performance API not available"]};const e={},t=[];try{const i=window.performance.timing,s=window.performance.navigation;if(i&&(e.loadTime=i.loadEventEnd-i.navigationStart,e.domReadyTime=i.domContentLoadedEventEnd-i.navigationStart,e.responseTime=i.responseEnd-i.requestStart,e.renderTime=i.loadEventEnd-i.responseEnd),s&&(e.navigationType=s.type,e.redirectCount=s.redirectCount),"connection"in navigator){const t=navigator.connection;e.connectionType=t.effectiveType,e.downlink=t.downlink,e.rtt=t.rtt}return{performance:e,warnings:t}}catch(e){return t.push(`Failed to collect performance info: ${e.message}`),{warnings:t}}}mergeContext(e,t={}){return{...e,...t,device:{...e.device,...t.device},app:{...e.app,...t.app},page:{...e.page,...t.page},campaign:{...e.campaign,...t.campaign},performance:{...e.performance,...t.performance}}}clearCache(){this.cachedAppInfo=void 0}isReactNativeEnvironment(){return"undefined"!=typeof navigator&&"ReactNative"===navigator.product}isWebEnvironment(){return"undefined"!=typeof window&&"undefined"!=typeof document&&!this.isReactNativeEnvironment()}isMobileEnvironment(){return!!this.isReactNativeEnvironment()||!(!this.isWebEnvironment()||"undefined"==typeof navigator)&&(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||"undefined"!=typeof window&&window.innerWidth<=768)}},g=class{constructor(e,t={}){this.plugins=new Map,this.eventHandlers=new Map,this.pluginEventHandlers=new Map,this.pluginStorage=new Map,this.config=e,this.options={maxExecutionTime:5e3,enableTimeout:!0,errorHandling:"lenient",...t}}setTrackFn(e){this.trackFn=e}setIdentifyFn(e){this.identifyFn=e}async register(e){if(this.validatePlugin(e),this.plugins.has(e.name))throw new a(e.name,`Plugin '${e.name}' is already registered`,"PLUGIN_ALREADY_REGISTERED");try{const t=this.createPluginContext(e.name);e.initialize&&await this.executeWithTimeout(()=>e.initialize(this.config,t),`Plugin '${e.name}' initialization`),this.plugins.set(e.name,e)}catch(t){throw new a(e.name,`Failed to register plugin: ${t.message}`,"PLUGIN_INITIALIZATION_FAILED",{cause:t})}}async unregister(e){const t=this.plugins.get(e);if(!t)return!1;let i;try{t.cleanup&&await this.executeWithTimeout(()=>t.cleanup(),`Plugin '${e}' cleanup`)}catch(e){i=e}finally{this.plugins.delete(e),this.pluginStorage.delete(e),this.removePluginEventHandlers(e)}if(i)throw new s("PLUGIN_ERROR",`Plugin cleanup failed for '${e}': ${i.message}`,{cause:i});return!0}async executeHook(e,t){const i=[],s=[],r=Array.from(this.plugins.values()).filter(t=>t.hooks&&t.hooks[e]);if(0===r.length)return t;for(const n of r)try{const s=this.createPluginContext(n.name),r=n.hooks[e],o=await this.executeWithTimeout(()=>r(t,s),`Plugin '${n.name}' ${e} hook`);i.push(o),"beforeEventSend"!==e&&"afterEventSend"!==e||(t=o||t)}catch(t){const i=new a(n.name,`Hook '${e}' failed: ${t.message}`,"PLUGIN_HOOK_FAILED",{cause:t});if(s.push(i),"strict"===this.options.errorHandling)throw i}return s.length>0&&"lenient"===this.options.errorHandling?{results:i,errors:s,data:"beforeEventSend"===e||"afterEventSend"===e?t:void 0}:"beforeEventSend"===e||"afterEventSend"===e?t:i}getPlugin(e){return this.plugins.get(e)}getPlugins(){return Array.from(this.plugins.values())}getPluginNames(){return Array.from(this.plugins.keys())}hasPlugin(e){return this.plugins.has(e)}getPluginCount(){return this.plugins.size}async executeLifecycle(e,t){const i=this.getLifecycleHook(e);i&&await this.executeHook(i,t)}async cleanup(){const e=Array.from(this.plugins.keys()).map(e=>this.unregister(e));await Promise.all(e)}getPluginHealth(){const e={};for(const[t,i]of this.plugins)try{i.name&&i.version?e[t]={status:"healthy"}:e[t]={status:"error",error:"Missing required plugin properties"}}catch(i){e[t]={status:"error",error:i.message}}return e}validatePlugin(e){if(!e.name)throw new a("","Plugin must have a name","PLUGIN_VALIDATION_FAILED");if(!e.version)throw new a(e.name,"Plugin must have a version","PLUGIN_VALIDATION_FAILED");if(!/^[a-zA-Z0-9_-]+$/.test(e.name))throw new a(e.name,"Plugin name must contain only letters, numbers, underscores, and hyphens","PLUGIN_VALIDATION_FAILED");if(!/^\d+\.\d+\.\d+/.test(e.version))throw new a(e.name,"Plugin version must be in semver format (x.y.z)","PLUGIN_VALIDATION_FAILED");if(e.hooks){const t=["beforeEvent","afterEvent","beforeBatch","afterBatch","onError","beforeStart","afterStart","beforeStop","afterStop","beforeEventSend","afterEventSend","onConfigChange","onUserIdentify","onSessionStart","onSessionEnd"];for(const i of Object.keys(e.hooks)){if(!t.includes(i))throw new a(e.name,`Invalid plugin hook: ${i}`,"PLUGIN_VALIDATION_FAILED");if("function"!=typeof e.hooks[i])throw new a(e.name,`Plugin hook '${i}' must be a function`,"PLUGIN_VALIDATION_FAILED")}}}createPluginContext(e){const t=this;return{getConfig:()=>({...this.config}),on:(t,i)=>{this.eventHandlers.has(t)||this.eventHandlers.set(t,new Set),this.eventHandlers.get(t).add(i),this.pluginEventHandlers.has(e)||this.pluginEventHandlers.set(e,[]),this.pluginEventHandlers.get(e).push({event:t,handler:i})},off:(t,i)=>{const s=this.eventHandlers.get(t);s&&s.delete(i);const r=this.pluginEventHandlers.get(e);if(r){const e=r.findIndex(e=>e.event===t&&e.handler===i);-1!==e&&r.splice(e,1)}},emit:(e,t)=>{const i=this.eventHandlers.get(e);i&&i.forEach(i=>{try{i(t)}catch(t){this.config.debug&&console.error(`Error in event handler for '${e}':`,t)}})},use:e=>{this.config.debug&&console.warn("Middleware registration is not yet implemented")},getPlugin:e=>t.plugins.get(e),track:(i,s)=>{t.trackFn?t.trackFn(i,s).catch(t=>{console.error(`[Plugin:${e}] track() failed:`,t)}):this.config.debug&&console.warn(`[Plugin:${e}] track() called but SDK track function not injected`)},identify:(i,s)=>{t.identifyFn?t.identifyFn(i,s).catch(t=>{console.error(`[Plugin:${e}] identify() failed:`,t)}):this.config.debug&&console.warn(`[Plugin:${e}] identify() called but SDK identify function not injected`)},logger:{debug:(t,...i)=>{this.config.debug&&console.debug(`[Plugin:${e}] ${t}`,...i)},info:(t,...i)=>{this.config.debug&&console.info(`[Plugin:${e}] ${t}`,...i)},warn:(t,...i)=>{this.config.debug&&console.warn(`[Plugin:${e}] ${t}`,...i)},error:(t,...i)=>{this.config.debug&&console.error(`[Plugin:${e}] ${t}`,...i)}},storage:{get:async i=>{if(t.pluginStorage.has(e))return t.pluginStorage.get(e).get(i)},set:async(i,s)=>{t.pluginStorage.has(e)||t.pluginStorage.set(e,new Map),t.pluginStorage.get(e).set(i,s)},remove:async i=>{const s=t.pluginStorage.get(e);s&&s.delete(i)}}}}async executeWithTimeout(e,t){return this.options.enableTimeout?new Promise((i,s)=>{const r=setTimeout(()=>{s(new Error(`${t} timed out after ${this.options.maxExecutionTime}ms`))},this.options.maxExecutionTime);Promise.resolve(e()).then(e=>{clearTimeout(r),i(e)}).catch(e=>{clearTimeout(r),s(e)})}):await e()}removePluginEventHandlers(e){const t=this.pluginEventHandlers.get(e);if(t){for(const{event:e,handler:i}of t){const t=this.eventHandlers.get(e);t&&t.delete(i)}this.pluginEventHandlers.delete(e)}}getLifecycleHook(e){return{"config-changed":"onConfigChange","user-identified":"onUserIdentify","session-started":"onSessionStart","session-ended":"onSessionEnd"}[e]}},p=class{constructor(e=1e3){this.store=new Map,this.maxSize=e}async get(e){const t=this.store.get(e);return t?t.ttl&&Date.now()>t.timestamp+1e3*t.ttl?(this.store.delete(e),null):t.value:null}async set(e,t,i){if(this.store.size>=this.maxSize&&!this.store.has(e)){const e=this.store.keys().next().value;e&&this.store.delete(e)}this.store.set(e,{value:t,timestamp:Date.now(),ttl:i})}async remove(e){return this.store.delete(e)}async clear(){this.store.clear()}async keys(){return Array.from(this.store.keys())}async size(){return this.store.size}},f=class{constructor(e="vircle_"){if(this.prefix=e,"undefined"==typeof localStorage)throw new c("localStorage is not available","STORAGE_NOT_AVAILABLE")}async get(e){try{const t=localStorage.getItem(this.prefix+e);if(!t)return null;const i=JSON.parse(t);return i.ttl&&Date.now()>i.timestamp+1e3*i.ttl?(await this.remove(e),null):i.value}catch(t){throw new c(`Failed to get item '${e}': ${t.message}`)}}async set(e,t,i){try{const s={value:t,timestamp:Date.now(),ttl:i};localStorage.setItem(this.prefix+e,JSON.stringify(s))}catch(t){if("QuotaExceededError"===t.name)throw new c("Storage quota exceeded","STORAGE_QUOTA_EXCEEDED");throw new c(`Failed to set item '${e}': ${t.message}`)}}async remove(e){try{const t=this.prefix+e,i=null!==localStorage.getItem(t);return localStorage.removeItem(t),i}catch(t){throw new c(`Failed to remove item '${e}': ${t.message}`)}}async clear(){try{Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).forEach(e=>localStorage.removeItem(e))}catch(e){throw new c(`Failed to clear storage: ${e.message}`)}}async keys(){try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).map(e=>e.substring(this.prefix.length))}catch(e){throw new c(`Failed to get keys: ${e.message}`)}}async size(){try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).length}catch(e){throw new c(`Failed to get size: ${e.message}`)}}},m=class{constructor(e="vircle_db"){if(this.dbVersion=1,this.storeName="vircle_store",this.db=null,this.dbName=e,"undefined"==typeof indexedDB)throw new c("IndexedDB is not available","STORAGE_NOT_AVAILABLE")}async initDB(){return this.db?this.db:new Promise((e,t)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{t(new c("Failed to open IndexedDB","STORAGE_ERROR"))},i.onsuccess=()=>{this.db=i.result,e(this.db)},i.onupgradeneeded=()=>{const e=i.result;e.objectStoreNames.contains(this.storeName)||e.createObjectStore(this.storeName,{keyPath:"key"})}})}async get(e){try{const t=await this.initDB(),i=t.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((t,s)=>{const r=i.get(e);r.onerror=()=>{s(new c(`Failed to get item '${e}'`,"STORAGE_ERROR"))},r.onsuccess=()=>{const i=r.result;if(!i)return void t(null);const s=i.data;if(s.ttl&&Date.now()>s.timestamp+1e3*s.ttl)return this.remove(e),void t(null);t(s.value)}})}catch(t){throw new c(`Failed to get item '${e}': ${t.message}`)}}async set(e,t,i){try{const s=await this.initDB(),r=s.transaction([this.storeName],"readwrite").objectStore(this.storeName),n={value:t,timestamp:Date.now(),ttl:i};return new Promise((t,i)=>{const s=r.put({key:e,data:n});s.onerror=()=>{i(new c(`Failed to set item '${e}'`,"STORAGE_ERROR"))},s.onsuccess=()=>{t()}})}catch(t){throw new c(`Failed to set item '${e}': ${t.message}`)}}async remove(e){try{const t=await this.initDB(),i=t.transaction([this.storeName],"readwrite").objectStore(this.storeName);return new Promise((t,s)=>{const r=i.get(e);r.onsuccess=()=>{const n=void 0!==r.result,o=i.delete(e);o.onerror=()=>{s(new c(`Failed to remove item '${e}'`,"STORAGE_ERROR"))},o.onsuccess=()=>{t(n)}},r.onerror=()=>{s(new c(`Failed to check item '${e}'`,"STORAGE_ERROR"))}})}catch(t){throw new c(`Failed to remove item '${e}': ${t.message}`)}}async clear(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readwrite").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.clear();s.onerror=()=>{i(new c("Failed to clear storage","STORAGE_ERROR"))},s.onsuccess=()=>{e()}})}catch(e){throw new c(`Failed to clear storage: ${e.message}`)}}async keys(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.getAllKeys();s.onerror=()=>{i(new c("Failed to get keys","STORAGE_ERROR"))},s.onsuccess=()=>{e(s.result)}})}catch(e){throw new c(`Failed to get keys: ${e.message}`)}}async size(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.count();s.onerror=()=>{i(new c("Failed to get size","STORAGE_ERROR"))},s.onsuccess=()=>{e(s.result)}})}catch(e){throw new c(`Failed to get size: ${e.message}`)}}},y=class{constructor(e={}){this.options={type:"memory",maxSize:10485760,keyPrefix:"vircle_",...e},this.adapter=e.adapter||this.createAdapter()}async get(e){try{return await this.adapter.get(e)}catch(t){throw new c(`Failed to get '${e}': ${t.message}`)}}async set(e,t,i){try{const s=i??this.options.ttl;await this.adapter.set(e,t,s)}catch(t){throw new c(`Failed to set '${e}': ${t.message}`)}}async remove(e){try{return await this.adapter.remove(e)}catch(t){throw new c(`Failed to remove '${e}': ${t.message}`)}}async clear(){try{await this.adapter.clear()}catch(e){throw new c(`Failed to clear storage: ${e.message}`)}}async keys(){try{return await this.adapter.keys()}catch(e){throw new c(`Failed to get keys: ${e.message}`)}}async size(){try{return await this.adapter.size()}catch(e){throw new c(`Failed to get size: ${e.message}`)}}async has(e){try{return null!==await this.adapter.get(e)}catch(t){throw new c(`Failed to check key '${e}': ${t.message}`)}}async getMultiple(e){const t={};return await Promise.all(e.map(async e=>{try{t[e]=await this.adapter.get(e)}catch(i){t[e]=null}})),t}async setMultiple(e,t){await Promise.all(Object.entries(e).map(([e,i])=>this.adapter.set(e,i,t??this.options.ttl)))}createAdapter(){switch(this.options.type){case"localStorage":return new f(this.options.keyPrefix);case"indexedDB":return new m(`${this.options.keyPrefix}db`);default:return new p(this.options.maxSize||1e3)}}static async testStorageAvailability(e){try{switch(e){case"localStorage":return"undefined"!=typeof localStorage&&(localStorage.setItem("vircle_test","test"),localStorage.removeItem("vircle_test"),!0);case"indexedDB":return"undefined"!=typeof indexedDB;case"memory":return!0;default:return!1}}catch{return!1}}static getRecommendedStorageType(){return"undefined"!=typeof window?"undefined"!=typeof indexedDB?"indexedDB":"undefined"!=typeof localStorage?"localStorage":"memory":"memory"}};function v(e){if(!e)return"***";const t=e.length;return t<8?"***":t<=16?`${e.substring(0,2)}...${e.substring(t-2)}`:`${e.substring(0,4)}...${e.substring(t-4)}`}function w(e){if(!e||"object"!=typeof e)return e;const t={...e};if("apiKey"in t&&(t.apiKey=v(t.apiKey)),t.headers){const e={...t.headers};Object.keys(e).forEach(t=>{if("authorization"===t.toLowerCase()){const i=e[t];"string"==typeof i&&(i.startsWith("Bearer ")?e[t]=`Bearer ${v(i.substring(7))}`:e[t]=v(i))}}),t.headers=e}return Object.keys(t).forEach(e=>{"object"==typeof t[e]&&null!==t[e]&&(t[e]=w(t[e]))}),t}var b=class{constructor(e){this.items=[],this.maxSize=e}enqueue(e,t=0){const i={data:e,priority:t,timestamp:Date.now()},s=this.findInsertIndex(t);this.items.splice(s,0,i),this.maxSize&&this.items.length>this.maxSize&&this.items.pop()}dequeue(){const e=this.items.shift();return e?.data}extractByPriority(e){const t=[],i=[];for(const s of this.items)s.priority>=e?t.push(s.data):i.push(s);return this.items=i,t}extractBatch(e){const t=[];for(let i=0;i<e&&this.items.length>0;i++){const e=this.items.shift();e&&t.push(e.data)}return t}extractOldItems(e){const t=Date.now(),i=[],s=[];for(const r of this.items)t-r.timestamp>e?i.push(r.data):s.push(r);return this.items=s,i}peek(){return this.items[0]?.data}size(){return this.items.length}isEmpty(){return 0===this.items.length}clear(){this.items=[]}getStatsByPriority(){const e=new Map;for(const t of this.items){const i=e.get(t.priority)||0;e.set(t.priority,i+1)}return e}findInsertIndex(e){let t=0,i=this.items.length;for(;t<i;){const s=Math.floor((t+i)/2);this.items[s].priority>=e?t=s+1:i=s}return t}},S={purchase:100,payment:100,error:100,crash:100,identify:75,signup:75,login:75,logout:75,click:75,submit:75,page_view:50,screen_view:50,scroll:50,heartbeat:25,session_extend:25,background_sync:0,cache_update:0};function E(e,t){const i=S[e.toLowerCase()];return void 0!==i?i:e.includes("error")||e.includes("fail")?100:e.includes("click")||e.includes("tap")?75:(e.includes("view")||e.includes("load"),50)}var I,A=class{constructor(e={}){this.state="CLOSED",this.failures=0,this.successes=0,this.lastFailureTime=0,this.halfOpenRetries=0,this.requestVolume=[],this.options={failureThreshold:5,resetTimeout:6e4,halfOpenRetries:3,volumeThreshold:10,errorThresholdPercentage:50,onStateChange:()=>{},...e}}async execute(e){if(this.isOpen())throw new Error(`Circuit breaker is OPEN. Next retry at ${new Date(this.getNextRetryTime()).toISOString()}`);try{const t=await e();return this.onSuccess(),t}catch(e){throw this.onFailure(),e}}isOpen(){return"OPEN"===this.state&&(!(Date.now()>=this.getNextRetryTime())||(this.transitionTo("HALF_OPEN"),!1))}onSuccess(){switch(this.recordRequest(!0),this.successes++,this.state){case"CLOSED":this.failures=0;break;case"HALF_OPEN":this.successes>=this.options.halfOpenRetries&&this.transitionTo("CLOSED")}}onFailure(){switch(this.recordRequest(!1),this.lastFailureTime=Date.now(),this.state){case"CLOSED":this.failures++,this.shouldOpen()&&this.transitionTo("OPEN");break;case"HALF_OPEN":this.transitionTo("OPEN")}}transitionTo(e){const t=this.state;switch(this.state=e,e){case"CLOSED":this.failures=0,this.successes=0;break;case"OPEN":this.halfOpenRetries=0;break;case"HALF_OPEN":this.successes=0,this.failures=0}t!==e&&this.options.onStateChange(e)}shouldOpen(){if(this.failures>=this.options.failureThreshold)return!0;const e=this.getRecentRequests();if(e.length>=this.options.volumeThreshold){return this.calculateErrorRate(e)>=this.options.errorThresholdPercentage}return!1}recordRequest(e){const t=Date.now();this.requestVolume.push({timestamp:t,success:e});const i=t-3e5;this.requestVolume=this.requestVolume.filter(e=>e.timestamp>i)}getRecentRequests(){const e=Date.now()-6e4;return this.requestVolume.filter(t=>t.timestamp>e)}calculateErrorRate(e){if(0===e.length)return 0;return e.filter(e=>!e.success).length/e.length*100}getNextRetryTime(){return this.lastFailureTime+this.options.resetTimeout}getStats(){const e=this.getRecentRequests(),t=this.calculateErrorRate(e);return{state:this.state,failures:this.failures,successes:this.successes,lastFailureTime:this.lastFailureTime||void 0,nextRetryTime:"OPEN"===this.state?this.getNextRetryTime():void 0,errorRate:t}}reset(){this.transitionTo("CLOSED"),this.failures=0,this.successes=0,this.lastFailureTime=0,this.halfOpenRetries=0,this.requestVolume=[]}trip(){this.transitionTo("OPEN"),this.lastFailureTime=Date.now()}};function x(e,t=1e3,i=3e4){const s=Math.min(t*Math.pow(2,e-1),i),r=.2*s*(2*Math.random()-1);return Math.round(s+r)}if("undefined"==typeof window&&"undefined"!=typeof global)try{I=e("crypto")}catch(e){}var R=class{static safeBase64Encode(e){if("undefined"!=typeof Buffer){return(e instanceof ArrayBuffer?Buffer.from(e):Buffer.from(e.buffer,e.byteOffset,e.byteLength)).toString("base64")}{const t=e instanceof ArrayBuffer?new Uint8Array(e):e,i=[],s=32768;for(let e=0;e<t.length;e+=s){const r=t.subarray(e,e+s);i.push(String.fromCharCode.apply(null,Array.from(r)))}return btoa(i.join(""))}}static safeBase64Decode(e){if("undefined"!=typeof Buffer)return new Uint8Array(Buffer.from(e,"base64"));{const t=atob(e),i=new Uint8Array(t.length);for(let e=0;e<t.length;e++)i[e]=t.charCodeAt(e);return i}}static async encrypt(e,t){try{if("undefined"!=typeof window&&window.crypto?.subtle)return this.encryptWebCrypto(e,t);if("undefined"!=typeof global&&global.crypto)return this.encryptNodeCrypto(e,t);throw new Error("No crypto implementation available")}catch(e){throw new s("ENCRYPTION_ERROR","Failed to encrypt data",{cause:e})}}static async encryptWebCrypto(e,t){const i=(new TextEncoder).encode(e),s=this.safeBase64Decode(t),r=await crypto.subtle.importKey("raw",s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength),{name:this.ALGORITHM,length:this.KEY_LENGTH},!1,["encrypt"]),n=crypto.getRandomValues(new Uint8Array(this.IV_LENGTH)),o=await crypto.subtle.encrypt({name:this.ALGORITHM,iv:n},r,i),a=new Uint8Array(n.length+o.byteLength);return a.set(n,0),a.set(new Uint8Array(o),n.length),this.safeBase64Encode(a)}static async encryptNodeCrypto(e,t){const i=I,s=Buffer.from(t,"base64"),r=i.randomBytes(this.IV_LENGTH),n=i.createCipheriv("aes-256-gcm",s,r);let o=n.update(e,"utf8");o=Buffer.concat([o,n.final()]);const a=n.getAuthTag();return Buffer.concat([r,o,a]).toString("base64")}static async generateAESKey(){if("undefined"!=typeof window&&window.crypto?.subtle)return crypto.subtle.generateKey({name:this.ALGORITHM,length:this.KEY_LENGTH},!0,["encrypt","decrypt"]);if(I)return I.randomBytes(32);throw new Error("No crypto implementation available")}static async encryptAESKey(e,t){if("undefined"!=typeof window&&window.crypto?.subtle){const i=this.safeBase64Decode(t),s=await crypto.subtle.importKey("spki",i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength),{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"]),r=await crypto.subtle.exportKey("raw",e),n=await crypto.subtle.encrypt({name:"RSA-OAEP"},s,r);return this.safeBase64Encode(new Uint8Array(n))}if(I){const i=I.createPublicKey({key:Buffer.from(t,"base64"),format:"der",type:"spki"});return I.publicEncrypt({key:i,oaepHash:"sha256",padding:I.constants.RSA_PKCS1_OAEP_PADDING},e).toString("base64")}throw new Error("No crypto implementation available")}static async encryptPayload(e,t){try{const i=JSON.stringify(e),s=await this.generateAESKey();let r,n,o;if("undefined"!=typeof window&&window.crypto?.subtle){const e=(new TextEncoder).encode(i),t=crypto.getRandomValues(new Uint8Array(this.IV_LENGTH)),a=await crypto.subtle.encrypt({name:this.ALGORITHM,iv:t},s,e),c=16,l=a.byteLength-c,u=a.slice(0,l),h=a.slice(l);r=this.safeBase64Encode(new Uint8Array(u)),o=this.safeBase64Encode(new Uint8Array(h)),n=this.safeBase64Encode(t)}else{if(!I)throw new Error("No crypto implementation available");{const e=I.randomBytes(this.IV_LENGTH),t=I.createCipheriv("aes-256-gcm",s,e);let a=t.update(i,"utf8");a=Buffer.concat([a,t.final()]),o=t.getAuthTag(),r=Buffer.concat([a,o]).toString("base64"),n=e.toString("base64")}}return{data:r,key:await this.encryptAESKey(s,t),iv:n,authTag:o,metadata:{algorithm:this.ALGORITHM,keyAlgorithm:"RSA-OAEP",timestamp:(new Date).toISOString()}}}catch(e){throw new s("ENCRYPTION_ERROR","Failed to encrypt payload",{cause:e})}}};R.ALGORITHM="AES-GCM",R.KEY_LENGTH=256,R.IV_LENGTH=12,R.TAG_LENGTH=16;var C,P,T="vircle_user",k="vircle_session",N={PUBLIC_KEY:(C="VIRCLE_RSA_PUBLIC_KEY",P="","undefined"!=typeof process&&process.env&&"object"==typeof process.env&&process.env[C]||P)},O={development:"https://dev-integration.vircle.co.kr/v1/track/events",production:"https://integration.vircle.co.kr/v1/track/events"},_={development:"https://dstatic.vircle.co.kr/sdk/v1/config",production:"https://static.vircle.co.kr/sdk/v1/config"},V=class{constructor(e,t={}){this.eventQueue=new b,this.requestQueue=[],this.isProcessingQueue=!1,this.isFlushingQueue=!1,this.disposed=!1,this.config=e,this.options={timeout:3e4,retryAttempts:3,retryDelay:1e3,batchSize:50,enableBatching:!0,enableCompression:!1,...t},this.cryptoAdapter=t.cryptoAdapter,this.circuitBreaker=new A({failureThreshold:5,resetTimeout:6e4,errorThresholdPercentage:50,onStateChange:e=>{this.config.debug&&console.warn(`[TransportService] Circuit breaker state changed to: ${e}`)}}),this.setupAutoFlush()}setupAutoFlush(){this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(async()=>{try{await this.flushPriorityQueue()}catch(e){this.config.debug&&console.error("[TransportService] Auto-flush error:",e)}},this.config.batch?.flushInterval||1e4)}async send(e){if(this.disposed)throw new s("SERVICE_DISPOSED","TransportService has been disposed");this.config.debug&&console.log("[TransportService] Received event:",e.name);const t=E(e.name);if(this.eventQueue.enqueue(e,t),this.config.debug&&console.log("[TransportService] Event enqueued with priority:",t,"Queue size:",this.eventQueue.size()),t>=100){return(await this.flushPriorityQueue()).results[0]||{success:!0}}if(this.eventQueue.size()>=(this.options.batchSize||50)){return(await this.flushPriorityQueue()).results[0]||{success:!0}}if(this.config.debug||"development"===this.config.environment){this.config.debug&&console.log("[TransportService] Debug mode: flushing immediately");return(await this.flushPriorityQueue()).results[0]||{success:!0}}return this.scheduleNextTickFlush(),{success:!0}}scheduleNextTickFlush(){this.pendingFlushTimer||(this.pendingFlushTimer=setTimeout(()=>{this.pendingFlushTimer=void 0,this.flushPriorityQueue().catch(()=>{})},0))}async sendBatch(e){if(this.disposed)throw new s("SERVICE_DISPOSED","TransportService has been disposed");if(0===e.length)return{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};for(const t of e){const e=E(t.name);this.eventQueue.enqueue(t,e)}return this.flushPriorityQueue()}async flushPriorityQueue(){if(this.isFlushingQueue)return this.config.debug&&console.log("[TransportService] Already flushing queue, skipping..."),{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};if(this.eventQueue.isEmpty())return{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};this.isFlushingQueue=!0;try{const e=this.eventQueue.extractByPriority(100),t=this.eventQueue.extractByPriority(75),i=this.eventQueue.extractBatch(this.options.batchSize||50),s=[];let r=0,n=0;if(e.length>0){const t=await this.executeBatchRequest(e);s.push(...t.results),r+=t.successfulEvents,n+=t.failedEvents}if(t.length>0){const e=await this.executeBatchRequest(t);s.push(...e.results),r+=e.successfulEvents,n+=e.failedEvents}if(i.length>0){const e=await this.executeBatchRequest(i);s.push(...e.results),r+=e.successfulEvents,n+=e.failedEvents}return{totalEvents:s.length,successfulEvents:r,failedEvents:n,results:s}}finally{this.isFlushingQueue=!1}}async processQueue(){if(!this.isProcessingQueue&&0!==this.requestQueue.length){this.isProcessingQueue=!0;try{for(;this.requestQueue.length>0;){const e=[],t=[];let i=0;for(;this.requestQueue.length>0&&i<this.options.batchSize;){const s=this.requestQueue.shift(),r=this.options.batchSize-i;if(!(s.events.length<=r)){const n=s.events.slice(0,r),o=s.events.slice(r);e.push({events:n,resolve:s.resolve,reject:s.reject}),t.push(...n),i+=n.length,this.requestQueue.unshift({events:o,resolve:s.resolve,reject:s.reject});break}e.push(s),t.push(...s.events),i+=s.events.length}try{const i=await this.executeBatchRequest(t);let s=0;for(const t of e){const e=i.results.slice(s,s+t.events.length),r={totalEvents:t.events.length,successfulEvents:e.filter(e=>e.success).length,failedEvents:e.filter(e=>!e.success).length,results:e};t.resolve(r),s+=t.events.length}}catch(t){for(const i of e)i.reject(t)}}}finally{this.isProcessingQueue=!1}}}async executeBatchRequest(e){let t=null;this.config.debug&&console.log("[Vircle SDK] executeBatchRequest start - events :",e);try{return await this.circuitBreaker.execute(async()=>{for(let i=0;i<=this.options.retryAttempts;i++){try{const i=await this.makeHttpRequest(e);if(i.success)return{totalEvents:e.length,successfulEvents:e.length,failedEvents:0,results:e.map(()=>i)};if(!i.retryable)return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)};t=i.error||new Error("Unknown error")}catch(e){t=e,this.config.debug&&console.log(`[Vircle SDK] error : ${JSON.stringify(t)}`)}if(i<this.options.retryAttempts){const e=x(i+1,this.options.retryDelay);this.config.debug&&console.log(`[Vircle SDK] Retry attempt ${i+1}/${this.options.retryAttempts} after ${e}ms delay`),await this.delay(e)}}const i={success:!1,error:t||new Error("Max retry attempts exceeded"),retryable:!1};return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)}})}catch(t){const i={success:!1,error:t,retryable:!1};return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)}}}async makeHttpRequest(e){this.config.debug&&console.log("[makeHttpRequest] config:",this.config);const t=this.config.environment||"production",i=O[t],s=(new Date).toISOString();let r={payload:{events:e},timestamp:s};const n={"Content-Type":"application/json","User-Agent":"Vircle-SDK-TypeScript/1.0.0",...this.config.headers,...this.options.headers};if(this.config.apiKey&&(n.Authorization=`Bearer ${this.config.apiKey}`,n["X-Vircle-Timestamp"]=s),this.encryptionConfig?.enabled&&this.encryptionConfig.publicKey)try{let e;this.config.debug&&console.log("[makeHttpRequest] start encryption - config: ",this.encryptionConfig),this.cryptoAdapter&&"function"==typeof this.cryptoAdapter.encryptPayload?(this.config.debug&&(console.log("[makeHttpRequest] Using platform-specific crypto adapter:",this.cryptoAdapter.constructor.name),console.log("[makeHttpRequest] Payload to encrypt:",JSON.stringify(r.payload).substring(0,100)+"..."),console.log("[makeHttpRequest] Public key available:",!!this.encryptionConfig.publicKey),console.log("[makeHttpRequest] Public key length:",this.encryptionConfig.publicKey.length)),e=await this.cryptoAdapter.encryptPayload(r.payload,this.encryptionConfig.publicKey)):(this.config.debug&&console.log("[makeHttpRequest] Fall back to built-in EncryptionUtils"),e=await R.encryptPayload(r.payload,this.encryptionConfig.publicKey)),r={encrypted:!0,payload:e,timestamp:s};const t=await async function(e,t,i){if(i&&"function"==typeof i.createHmacSignature)return i.createHmacSignature(e,t);if("undefined"!=typeof crypto&&crypto.subtle){const i=new TextEncoder,s=i.encode(JSON.stringify(e)),r=await crypto.subtle.importKey("raw",i.encode(t),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),n=await crypto.subtle.sign("HMAC",r,s);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join("")}throw new Error("No crypto implementation available for HMAC signature")}(r,this.config.apiKey,this.cryptoAdapter);this.config.debug&&console.debug("[makeHttpRequest] signature:",t),n["X-Vircle-Signature"]=t,n["X-Vircle-Encrypted"]="true",this.config.debug&&console.debug("[makeHttpRequest] headers:",n)}catch(e){const t=new o("Failed to encrypt payload. Aborting transmission for security.",void 0,{cause:e});return this.config.debug&&(console.error("[makeHttpRequest] Encryption failed:",e),console.error("[makeHttpRequest] Error type:",typeof e),console.error("[makeHttpRequest] Error name:",e instanceof Error?e.name:"Not an Error instance"),console.error("[makeHttpRequest] Error message:",e instanceof Error?e.message:String(e)),console.error("[makeHttpRequest] Error stack:",e instanceof Error?e.stack:"No stack trace"),console.error("[makeHttpRequest] Crypto adapter type:",this.cryptoAdapter?this.cryptoAdapter.constructor.name:"No adapter"),console.error("[makeHttpRequest] Public key preview:",this.encryptionConfig.publicKey.substring(0,50)+"...")),{success:!1,error:t,retryable:!1}}let a,c,l,u=!1;try{let e,t;"undefined"!=typeof AbortController&&(c=new AbortController,e=c.signal,l=setTimeout(()=>{c?.abort()},this.options.timeout));try{t=JSON.stringify(r)}catch(e){return this.config.debug&&console.log("[makeHttpRequest] Failed to stringify payload:",e),{success:!1,error:new o("Failed to serialize request payload",void 0,{cause:e,context:{errorName:e instanceof Error?e.name:"Unknown",isSerializationError:!0}}),retryable:!1}}const s={method:"POST",headers:n,body:t,signal:e};this.config.debug&&(console.log("[makeHttpRequest] fetch - url:",i),console.log("[makeHttpRequest] fetch - request:",s),console.log("[makeHttpRequest] fetch - starting request...")),a=setTimeout(()=>{!u&&this.config.debug&&(console.log("[makeHttpRequest] fetch - Promise still pending after 10 seconds"),console.log("[makeHttpRequest] fetch - Possible causes: ATS policy, network proxy, or fetch polyfill issue"))},1e4);const h=await this.fetch(i,s);let d;u=!0,a&&clearTimeout(a),l&&clearTimeout(l),this.config.debug&&(console.log("[makeHttpRequest] fetch - response received"),console.log("[makeHttpRequest] fetch - response status:",h.status),console.log("[makeHttpRequest] fetch - response ok:",h.ok));try{const e=h.text(),t=new Promise((e,t)=>{setTimeout(()=>t(new Error("Response body read timeout")),5e3)});d=await Promise.race([e,t])}catch(e){return this.config.debug&&console.log("[makeHttpRequest] Failed to read response body:",e),{success:h.ok,statusCode:h.status,responseBody:null,retryable:this.isRetryableHttpStatus(h.status)}}let g=null;try{g=JSON.parse(d)}catch{}if(h.ok)return{success:!0,statusCode:h.status,responseBody:g};{const e=new o(g?.message||`HTTP ${h.status}: ${h.statusText}`,h.status,{context:{responseBody:d}});return{success:!1,statusCode:h.status,responseBody:g,error:e,retryable:this.isRetryableHttpStatus(h.status)}}}catch(e){u=!0,a&&clearTimeout(a),l&&clearTimeout(l),this.config.debug&&(console.log("[makeHttpRequest] Request failed:",e),console.log("[makeHttpRequest] Error type:",typeof e),console.log("[makeHttpRequest] Error name:",e instanceof Error?e.name:"Unknown"),console.log("[makeHttpRequest] Error message:",e instanceof Error?e.message:String(e)),console.log("[makeHttpRequest] Error stack:",e instanceof Error?e.stack:"No stack"));const t=e instanceof Error?e.message:String(e),s=e instanceof Error&&"AbortError"===e.name,r=e instanceof Error&&"TypeError"===e.name,n=t.includes("Network request failed")||t.includes("Failed to fetch")||t.includes("Load failed");return{success:!1,error:new o(s?`Request timeout after ${this.options.timeout}ms`:`Network request failed: ${t}`,void 0,{cause:e,context:{errorName:e instanceof Error?e.name:"Unknown",isAbortError:s,isTypeError:r,isNetworkError:n,timeout:this.options.timeout,url:i,environment:"undefined"!=typeof window?"browser":"undefined"!=typeof global?"node/react-native":"unknown"}}),retryable:!s&&this.isRetryableError(e)}}}async fetch(e,t){if("undefined"!=typeof fetch)return this.config.debug&&console.log("[fetch] Using global fetch implementation"),fetch(e,t);if("undefined"!=typeof window&&window.fetch)return this.config.debug&&console.log("[fetch] Using window.fetch implementation"),window.fetch(e,t);if("undefined"!=typeof global)try{const i=await Promise.resolve().then(function(){return pe}),s=i.default||i;return this.config.debug&&console.log("[fetch] Using node-fetch implementation"),s(e,t)}catch{}throw new o("No fetch implementation available",void 0,{context:{environment:"undefined"!=typeof window?"browser":"node",hasFetch:"undefined"!=typeof fetch,hasWindowFetch:"undefined"!=typeof window&&void 0!==window.fetch}})}isRetryableHttpStatus(e){return e>=500||408===e||429===e}isRetryableError(e){const t=e.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused"].some(e=>t.includes(e))}delay(e){return new Promise(t=>setTimeout(t,e))}sendWithKeepalive(e){if("undefined"==typeof fetch)return!1;if(0===e.length)return!0;const t=this.config.environment||"production",i=O[t],s=(new Date).toISOString(),r={"Content-Type":"application/json","User-Agent":"Vircle-SDK-TypeScript/1.0.0"};this.config.apiKey&&(r.Authorization=`Bearer ${this.config.apiKey}`,r["X-Vircle-Timestamp"]=s);const n={payload:{events:e},timestamp:s};try{return fetch(i,{method:"POST",headers:r,body:JSON.stringify(n),keepalive:!0}).catch(()=>{}),!0}catch{return!1}}flushWithKeepalive(){const e=this.eventQueue.extractBatch(this.eventQueue.size());return 0===e.length||this.sendWithKeepalive(e)}getQueueStatus(){return{queueSize:this.requestQueue.length,isProcessing:this.isProcessingQueue}}async flush(){await this.flushPriorityQueue(),this.requestQueue.length>0&&await this.processQueue()}clearQueue(){this.eventQueue.clear();const e=new s("CLEANUP_ERROR","Transport queue cleared during shutdown");for(const t of this.requestQueue)t.reject(e);this.requestQueue=[]}updateConfig(e){this.config={...this.config,...e}}setEncryptionConfig(e){this.encryptionConfig=e}updateOptions(e){this.options={...this.options,...e}}dispose(){this.disposed||(this.disposed=!0,this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),this.pendingFlushTimer&&(clearTimeout(this.pendingFlushTimer),this.pendingFlushTimer=void 0),this.clearQueue(),this.circuitBreaker.reset(),this.config={},this.options={})}isDisposed(){return this.disposed}},D=class{constructor(){this.rules=[]}addRule(e){return this.rules.push(e),this}removeRule(e){return this.rules=this.rules.filter(t=>t.name!==e),this}validate(e){const t=[],i=[];for(const s of this.rules)try{const r=s.validate(e);t.push(...r.errors),i.push(...r.warnings)}catch(e){t.push(`Validation rule '${s.name}' failed: ${e.message}`)}return{isValid:0===t.length,errors:t,warnings:i}}validateRequired(e,t){return null==e||""===e?{isValid:!1,errors:[`${t} is required`],warnings:[]}:{isValid:!0,errors:[],warnings:[]}}validateStringLength(e,t,i,s="Field"){const r=[];return"string"!=typeof e?r.push(`${s} must be a string`):(void 0!==t&&e.length<t&&r.push(`${s} must be at least ${t} characters long`),void 0!==i&&e.length>i&&r.push(`${s} must be at most ${i} characters long`)),{isValid:0===r.length,errors:r,warnings:[]}}validateNumberRange(e,t,i,s="Field"){const r=[];return"number"!=typeof e||isNaN(e)?r.push(`${s} must be a valid number`):(void 0!==t&&e<t&&r.push(`${s} must be at least ${t}`),void 0!==i&&e>i&&r.push(`${s} must be at most ${i}`)),{isValid:0===r.length,errors:r,warnings:[]}}validateEnum(e,t,i="Field"){const s=Object.values(t);return s.includes(e)?{isValid:!0,errors:[],warnings:[]}:{isValid:!1,errors:[`${i} must be one of: ${s.join(", ")}`],warnings:[]}}validateUrl(e,t="URL"){try{return new URL(e),{isValid:!0,errors:[],warnings:[]}}catch{return{isValid:!1,errors:[`${t} must be a valid URL`],warnings:[]}}}validateEmail(e,t="Email"){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)?{isValid:!0,errors:[],warnings:[]}:{isValid:!1,errors:[`${t} must be a valid email address`],warnings:[]}}validateRequiredProperties(e,t,i="Object"){const s=[];if("object"!=typeof e||null===e)s.push(`${i} must be an object`);else for(const r of t)r in e&&null!==e[r]&&void 0!==e[r]||s.push(`${i}.${r} is required`);return{isValid:0===s.length,errors:s,warnings:[]}}validateArray(e,t,i="Array"){const s=[],r=[];return Array.isArray(e)?e.forEach((e,n)=>{const o=t(e,n);s.push(...o.errors.map(e=>`${i}[${n}]: ${e}`)),r.push(...o.warnings.map(e=>`${i}[${n}]: ${e}`))}):s.push(`${i} must be an array`),{isValid:0===s.length,errors:s,warnings:r}}checkSecurity(e,t){const i=[],s=[];if("string"==typeof e){/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi.test(e)&&s.push(`${t} contains potentially dangerous script content`);const r=[/javascript:/i,/data:text\/html/i,/vbscript:/i,/on\w+\s*=/i];for(const s of r)if(s.test(e)){i.push(`${t} contains potentially suspicious content`);break}}return{isValid:0===s.length,errors:s,warnings:i}}},L=class extends D{constructor(e={}){super(),this.config={maxEventNameLength:100,maxPropertyKeyLength:50,maxPropertyValueLength:1e3,maxPropertiesCount:100,maxEventSize:102400,allowedEventNamePattern:/^[a-zA-Z0-9_.-]+$/,forbiddenPropertyNames:["__proto__","constructor","prototype"],enableSecurityChecks:!0,...e},this.setupValidationRules()}validate(e){const t=super.validate(e);return{isValid:t.isValid,errors:t.errors,warnings:t.warnings}}setupValidationRules(){this.addRule({name:"required_fields",validate:e=>this.validateRequiredFields(e)}),this.addRule({name:"event_name",validate:e=>this.validateEventName(e.name)}),this.addRule({name:"properties",validate:e=>this.validateProperties(e.properties)}),this.addRule({name:"context",validate:e=>this.validateContext(e.context)}),this.addRule({name:"user_id",validate:e=>this.validateUserId(e.userId)}),this.addRule({name:"session_id",validate:e=>this.validateSessionId(e.sessionId)}),this.addRule({name:"timestamp",validate:e=>this.validateTimestamp(e.timestamp)}),this.addRule({name:"event_size",validate:e=>this.validateEventSize(e)}),this.config.enableSecurityChecks&&this.addRule({name:"security",validate:e=>this.validateSecurity(e)})}validateRequiredFields(e){const t=[];return e.name||t.push("Event name is required"),{isValid:0===t.length,errors:t,warnings:[]}}validateEventName(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};e.length>this.config.maxEventNameLength&&t.push(`Event name must not exceed ${this.config.maxEventNameLength} characters`),this.config.allowedEventNamePattern.test(e)||t.push("Event name contains invalid characters. Use only letters, numbers, underscores, dots, and hyphens");return["error","debug","log","warn","info"].includes(e.toLowerCase())&&i.push(`Event name '${e}' is reserved and may cause conflicts`),e.includes(" ")&&i.push("Event name contains spaces. Consider using underscores or camelCase"),e!==e.toLowerCase()&&e.includes("_")&&i.push("Mixing camelCase and snake_case in event name is not recommended"),{isValid:0===t.length,errors:t,warnings:i}}validateProperties(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e||Array.isArray(e))return t.push("Properties must be an object"),{isValid:!1,errors:t,warnings:i};const s=Object.keys(e);s.length>this.config.maxPropertiesCount&&t.push(`Too many properties. Maximum allowed: ${this.config.maxPropertiesCount}`);for(const r of s){const s=e[r];r.length>this.config.maxPropertyKeyLength&&t.push(`Property key '${r}' exceeds maximum length of ${this.config.maxPropertyKeyLength}`),this.config.forbiddenPropertyNames.includes(r)&&t.push(`Property name '${r}' is forbidden`),r.startsWith("_")&&!r.startsWith("_vircle_")&&i.push(`Property '${r}' starts with underscore. This may conflict with internal properties`);const n=this.validatePropertyValue(s,r);t.push(...n.errors),i.push(...n.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validatePropertyValue(e,t){const i=[],s=[];if(null==e)return s.push(`Property '${t}' has null/undefined value`),{isValid:!0,errors:i,warnings:s};const r=typeof e;if(!["string","number","boolean","object"].includes(r))return i.push(`Property '${t}' has unsupported type '${r}'`),{isValid:!1,errors:i,warnings:s};if("string"===r&&(e.length>this.config.maxPropertyValueLength&&i.push(`Property '${t}' value exceeds maximum length of ${this.config.maxPropertyValueLength}`),this.config.enableSecurityChecks)){const r=this.checkSecurity(e,`Property '${t}'`);i.push(...r.errors),s.push(...r.warnings)}if("number"===r&&(Number.isFinite(e)||i.push(`Property '${t}' has invalid number value (Infinity/NaN)`)),"object"===r&&null!==e)if(Array.isArray(e))e.length>100&&s.push(`Property '${t}' array is very large (${e.length} items)`);else{const r=this.validateProperties(e);i.push(...r.errors.map(e=>`${t}.${e}`)),s.push(...r.warnings.map(e=>`${t}.${e}`))}return{isValid:0===i.length,errors:i,warnings:s}}validateContext(e){return e?this.validateProperties(e):{isValid:!0,errors:[],warnings:[]}}validateUserId(e){return e?this.validateStringLength(e,1,255,"User ID"):{isValid:!0,errors:[],warnings:[]}}validateSessionId(e){return e?this.validateStringLength(e,1,255,"Session ID"):{isValid:!0,errors:[],warnings:[]}}validateTimestamp(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};let s;if(e instanceof Date)s=e;else{if("string"!=typeof e)return t.push("Timestamp must be a Date object or ISO string"),{isValid:!1,errors:t,warnings:i};if(s=new Date(e),isNaN(s.getTime()))return t.push("Invalid timestamp format"),{isValid:!1,errors:t,warnings:i}}const r=new Date,n=new Date(r.getFullYear()-1,r.getMonth(),r.getDate()),o=new Date(r.getTime()+36e5);return s<n&&i.push("Timestamp is more than a year old"),s>o&&i.push("Timestamp is in the future"),{isValid:0===t.length,errors:t,warnings:i}}validateEventSize(e){try{const t=JSON.stringify(e),i=new Blob([t]).size;if(i>this.config.maxEventSize)return{isValid:!1,errors:[`Event size (${i} bytes) exceeds maximum allowed size (${this.config.maxEventSize} bytes)`],warnings:[]};const s=[];return i>.8*this.config.maxEventSize&&s.push(`Event size (${i} bytes) is approaching the maximum limit`),{isValid:!0,errors:[],warnings:s}}catch(e){return{isValid:!1,errors:[`Failed to calculate event size: ${e.message}`],warnings:[]}}}validateSecurity(e){const t=[],i=[],s=this.checkSecurity(e.name,"Event name");if(t.push(...s.errors),i.push(...s.warnings),e.userId){const s=this.checkSecurity(e.userId,"User ID");t.push(...s.errors),i.push(...s.warnings)}if(e.sessionId){const s=this.checkSecurity(e.sessionId,"Session ID");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}},$=class extends D{constructor(e={}){super(),this.options={requireApiKey:!0,allowedEnvironments:["development","production"],maxBatchSize:1e3,maxQueueSize:1e4,maxRetryAttempts:10,...e},this.setupValidationRules()}validate(e){const t=super.validate(e);return{isValid:t.isValid,errors:t.errors,warnings:t.warnings}}setupValidationRules(){this.addRule({name:"api_key",validate:e=>this.validateApiKey(e.apiKey,e)}),this.addRule({name:"environment",validate:e=>this.validateEnvironment(e.environment)}),this.addRule({name:"batch_config",validate:e=>this.validateBatchConfig(e.batch)}),this.addRule({name:"queue_config",validate:e=>this.validateQueueConfig(e.queue)}),this.addRule({name:"retry_config",validate:e=>this.validateRetryConfig(e.retry)}),this.addRule({name:"transport_config",validate:e=>this.validateTransportConfig(e.transport)}),this.addRule({name:"storage_config",validate:e=>this.validateStorageConfig(e.storage)}),this.addRule({name:"plugin_config",validate:e=>this.validatePluginConfig(e.plugins)}),this.addRule({name:"auto_collect_config",validate:e=>this.validateAutoCollectConfig(e.autoCollect)}),this.addRule({name:"privacy_config",validate:e=>this.validatePrivacyConfig(e.privacy)}),this.addRule({name:"headers",validate:e=>this.validateHeaders(e.headers)})}validateApiKey(e,t){const i=[],s=[];if(this.options.requireApiKey&&!e)return i.push("API key is required"),{isValid:!1,errors:i,warnings:s};if(e){e.length<10&&i.push("API key seems too short (minimum 10 characters)"),e.length>500&&i.push("API key seems too long (maximum 500 characters)"),/^[a-zA-Z0-9_.-]+$/.test(e)||s.push("API key contains unusual characters");const t=function(e){const t=[];if(!e||"string"!=typeof e)return{isValid:!1,isTestKey:!1,warnings:["API key is required"]};e.length<10&&t.push("API key appears to be too short");const i=[/^test/i,/^demo/i,/^sample/i,/^example/i].some(t=>t.test(e));i&&t.push("API key appears to be a test key");const s=[/^[0-9]+$/,/^[a-zA-Z]+$/,/^(.)\1+$/,/password/i,/secret/i,/\s/].some(t=>t.test(e));return s&&t.push("API key format appears to be invalid"),{isValid:!s&&e.length>=10,isTestKey:i,warnings:t}}(e);t.isValid||i.push("Invalid API key format"),t.isTestKey&&s.push("Test API key detected - ensure you use a production key in production"),s.push(...t.warnings)}return{isValid:0===i.length,errors:i,warnings:s}}validateEnvironment(e){return e?this.validateEnum(e,this.options.allowedEnvironments.reduce((e,t)=>({...e,[t]:t}),{}),"Environment"):{isValid:!0,errors:[],warnings:[]}}validateBatchConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Batch configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.size){const s=this.validateNumberRange(e.size,1,this.options.maxBatchSize,"Batch size");t.push(...s.errors),i.push(...s.warnings),e.size>100&&i.push("Large batch sizes may impact performance")}if(void 0!==e.timeout){const s=this.validateNumberRange(e.timeout,100,3e5,"Batch timeout");t.push(...s.errors),i.push(...s.warnings),e.timeout<1e3&&i.push("Very short batch timeout may cause frequent network requests")}if(void 0!==e.maxBytes){const s=this.validateNumberRange(e.maxBytes,1024,52428800,"Batch max bytes");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateQueueConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Queue configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.maxSize){const s=this.validateNumberRange(e.maxSize,10,this.options.maxQueueSize,"Queue max size");t.push(...s.errors),i.push(...s.warnings),e.maxSize>5e3&&i.push("Large queue sizes may consume significant memory")}if(void 0!==e.workers){const s=this.validateNumberRange(e.workers,1,10,"Queue workers");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.strategy){const s={fifo:"fifo",lifo:"lifo",priority:"priority"},r=this.validateEnum(e.strategy,s,"Queue strategy");t.push(...r.errors),i.push(...r.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateRetryConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Retry configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.maxAttempts){const s=this.validateNumberRange(e.maxAttempts,0,this.options.maxRetryAttempts,"Max retry attempts");t.push(...s.errors),i.push(...s.warnings),e.maxAttempts>5&&i.push("High retry attempts may delay error reporting")}if(void 0!==e.initialDelay){const s=this.validateNumberRange(e.initialDelay,10,6e4,"Initial retry delay");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.maxDelay){const s=this.validateNumberRange(e.maxDelay,100,36e5,"Max retry delay");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.multiplier){const s=this.validateNumberRange(e.multiplier,1,10,"Retry multiplier");t.push(...s.errors),i.push(...s.warnings)}return e.initialDelay&&e.maxDelay&&e.initialDelay>=e.maxDelay&&t.push("Initial retry delay must be less than max retry delay"),{isValid:0===t.length,errors:t,warnings:i}}validateTransportConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Transport configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.timeout){const s=this.validateNumberRange(e.timeout,1e3,3e5,"Transport timeout");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.connectionTimeout){const s=this.validateNumberRange(e.connectionTimeout,1e3,6e4,"Connection timeout");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateStorageConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Storage configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.type){const s={memory:"memory",localStorage:"localStorage",indexedDB:"indexedDB",file:"file"},r=this.validateEnum(e.type,s,"Storage type");t.push(...r.errors),i.push(...r.warnings)}if(void 0!==e.maxSize){const s=this.validateNumberRange(e.maxSize,1024,1073741824,"Storage max size");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validatePluginConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if(!Array.isArray(e))return t.push("Plugins configuration must be an array"),{isValid:!1,errors:t,warnings:i};const s=new Set;for(let i=0;i<e.length;i++){const r=e[i];"object"==typeof r&&r?r.name?(s.has(r.name)?t.push(`Duplicate plugin name: ${r.name}`):s.add(r.name),"string"==typeof r.name&&0!==r.name.length||t.push(`Plugin at index ${i} must have a valid name`),void 0!==r.version&&"string"!=typeof r.version&&t.push(`Plugin '${r.name}' version must be a string`),void 0!==r.initialize&&"function"!=typeof r.initialize&&t.push(`Plugin '${r.name}' initialize must be a function`)):t.push(`Plugin at index ${i} must have a name`):t.push(`Plugin at index ${i} must be an object`)}return{isValid:0===t.length,errors:t,warnings:i}}validateAutoCollectConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Auto-collect configuration must be an object"),{isValid:!1,errors:t,warnings:i};const s=["device","app","page","userAgent","referrer","campaign","performance"];for(const i of s)void 0!==e[i]&&"boolean"!=typeof e[i]&&t.push(`Auto-collect ${i} must be a boolean`);return{isValid:0===t.length,errors:t,warnings:i}}validatePrivacyConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Privacy configuration must be an object"),{isValid:!1,errors:t,warnings:i};const s=["respectDoNotTrack","anonymizeIP","requireCookieConsent","gdprCompliant","requireOptIn"];for(const i of s)void 0!==e[i]&&"boolean"!=typeof e[i]&&t.push(`Privacy ${i} must be a boolean`);return{isValid:0===t.length,errors:t,warnings:i}}validateHeaders(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Headers must be an object"),{isValid:!1,errors:t,warnings:i};for(const[s,r]of Object.entries(e)){"string"==typeof s&&"string"==typeof r||t.push(`Header '${s}' must have string key and value`),/^[a-zA-Z0-9-_]+$/.test(s)||t.push(`Invalid header name format: ${s}`);["authorization","cookie","set-cookie"].includes(s.toLowerCase())&&i.push(`Setting sensitive header '${s}' may have security implications`)}return{isValid:0===t.length,errors:t,warnings:i}}};function B(e){return e.trim()}function F(e={},t={}){const i={};for(const[t,s]of Object.entries(e))i[t]=H(s);for(const[e,s]of Object.entries(t))"object"!=typeof s||null===s||Array.isArray(s)||"object"!=typeof i[e]||null===i[e]||Array.isArray(i[e])?i[e]=H(s):i[e]=F(i[e],s);return i}function U(e={},t={}){const i={};for(const[t,s]of Object.entries(e))i[t]=H(s);for(const[e,s]of Object.entries(t))"object"!=typeof s||null===s||Array.isArray(s)||"object"!=typeof i[e]||null===i[e]||Array.isArray(i[e])?i[e]=H(s):i[e]=F(i[e],s);return i}function H(e,t=new WeakSet){if(null===e||"object"!=typeof e)return e;if(t.has(e))return"[Circular]";if(e instanceof Date)return new Date(e);if(Array.isArray(e)){t.add(e);const i=e.map(e=>H(e,t));return t.delete(e),i}if("object"==typeof e){t.add(e);const i={};for(const[s,r]of Object.entries(e))i[s]=H(r,t);return t.delete(e),i}return e}function z(e){if(!e)return(new Date).toISOString();if(e instanceof Date)return e.toISOString();if("string"==typeof e){const t=new Date(e);return isNaN(t.getTime())?(new Date).toISOString():t.toISOString()}return"number"==typeof e?new Date(e).toISOString():(new Date).toISOString()}var q=class{constructor(e={}){this.cache=new Map,this.pendingCollectors=new Map,this.options={cacheTime:e.cacheTime??6e4,getCacheKey:e.getCacheKey??(()=>"default")}}async getOrCollect(e){const t=this.options.getCacheKey(),i=this.cache.get(t),s=Date.now();if(i&&s-i.timestamp<this.options.cacheTime)return i.context;const r=this.pendingCollectors.get(t);if(r)return r;const n=e();this.pendingCollectors.set(t,n);try{const e=await n;return this.cache.set(t,{context:e,timestamp:s}),e}catch(e){if(i)return console.warn("[ContextCache] Collection failed, returning stale cache:",e),i.context;throw e}finally{this.pendingCollectors.delete(t)}}invalidate(e){const t=e??this.options.getCacheKey();this.cache.delete(t)}clear(){this.cache.clear()}getStats(){return{size:this.cache.size,keys:Array.from(this.cache.keys())}}setCacheTime(e){this.options.cacheTime=e}cleanup(){const e=Date.now();for(const[t,i]of this.cache.entries())e-i.timestamp>=this.options.cacheTime&&this.cache.delete(t)}},j=class{},K=class extends j{constructor(){super(...arguments),this.handles=new Set}schedule(e,t){const i=t?.timeout??3e3;if("undefined"!=typeof window&&"requestIdleCallback"in window){const t=window.requestIdleCallback(async i=>{this.handles.delete(t);try{await e()}catch(e){console.error("[WebIdleScheduler] Callback error:",e)}},{timeout:i});return this.handles.add(t),t}{const t=setTimeout(async()=>{this.handles.delete(t);try{await e()}catch(e){console.error("[WebIdleScheduler] Callback error:",e)}},0);return this.handles.add(t),t}}cancel(e){"undefined"!=typeof window&&"cancelIdleCallback"in window?window.cancelIdleCallback(e):clearTimeout(e),this.handles.delete(e)}cancelAll(){for(const e of this.handles)this.cancel(e);this.handles.clear()}},M=class extends j{constructor(){super(...arguments),this.handles=new Map,this.nextId=0}schedule(e,t){const i=this.nextId++,s=setTimeout(async()=>{this.handles.delete(i);try{await e()}catch(e){console.error("[DefaultIdleScheduler] Callback error:",e)}},0);return this.handles.set(i,s),i}cancel(e){const t=this.handles.get(e);t&&(clearTimeout(t),this.handles.delete(e))}cancelAll(){for(const e of this.handles.values())clearTimeout(e);this.handles.clear()}},G=class{constructor(e,t=1e3){this.queue=[],this.isProcessing=!1,this.scheduler=e,this.maxQueueSize=t}enqueue(e,t=0,i){for(this.queue.push({task:e,priority:t,timestamp:Date.now()}),this.queue.sort((e,t)=>t.priority-e.priority);this.queue.length>this.maxQueueSize;)this.queue.pop();this.isProcessing||this.scheduleProcessing(i)}scheduleProcessing(e){this.handle&&this.scheduler.cancel(this.handle),this.handle=this.scheduler.schedule(async()=>{await this.processQueue()},e)}async processQueue(){if(!this.isProcessing&&0!==this.queue.length){this.isProcessing=!0;try{for(;this.queue.length>0;){const e=this.queue.shift();if(e)try{await e.task()}catch(e){console.error("[TaskScheduler] Task error:",e)}}}finally{this.isProcessing=!1,this.handle=void 0}}}clear(){this.queue=[],this.handle&&(this.scheduler.cancel(this.handle),this.handle=void 0),this.isProcessing=!1}getStats(){return{queueSize:this.queue.length,isProcessing:this.isProcessing}}};function W(e,t=""){return"undefined"!=typeof process&&process&&"object"==typeof process&&process.env&&"object"==typeof process.env&&process.env[e]||t}var Q="__vircle_config_",J=class e{constructor(){this.configCache=new Map,this.configPromises=new Map,this.CACHE_DURATION=3e5,this.cacheTimestamps=new Map}static getInstance(){return e.instance||(e.instance=new e),e.instance}async getProjectConfig(e,t="production"){const i=this.getCachedConfig(e);if(i)return i;const s=this.getStorageCachedConfig(e);if(s)return this.setCachedConfig(e,s),s;const r=this.configPromises.get(e);if(r)return r;const n=this.fetchConfig(e,t);this.configPromises.set(e,n);try{const t=await n;return this.setCachedConfig(e,t),this.setStorageCachedConfig(e,t),this.configPromises.delete(e),t}catch(t){throw this.configPromises.delete(e),t}}async fetchConfig(e,t){const i=this.extractProjectId(e);try{return await this.fetchFromCDN(i,e,t)}catch(e){throw new s("REMOTE_CONFIG_FETCH_FAILED",`Failed to fetch configuration for project ${i}. Please ensure the project is properly configured.`,{context:{projectId:i,cdnError:e instanceof Error?e.message:String(e),environment:t}})}}async fetchFromCDN(e,t,i){const s=`${W("VIRCLE_CONFIG_CDN_URL")||_[i]}/${e}/config.json`,r=await fetch(s,{method:"GET",headers:{Accept:"application/json"},cache:"default",mode:"cors"});if(!r.ok)throw new Error(`CDN returned ${r.status}`);const n=await r.json();return this.validateConfig(n,i)}extractProjectId(e){const t=e.match(/^pk_([^_]+)_/);return t&&t[1]?t[1]:this.hashApiKey(e).substring(0,8)}hashApiKey(e){let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(36)}validateConfig(e,t){if(!e||"object"!=typeof e)throw new s("INVALID_CONFIGURATION","Invalid project configuration format");if(!e.projectId)throw new s("INVALID_CONFIGURATION","Project ID is required");if(!e.environment)throw new s("INVALID_CONFIGURATION","Environment field is required in project configuration");if("development"!==e.environment&&"production"!==e.environment)throw new s("INVALID_CONFIGURATION",`Invalid environment value: ${e.environment}. Must be 'development' or 'production'`);if(e.environment!==t)throw new s("INVALID_CONFIGURATION",`Environment mismatch: requested '${t}' but config is for '${e.environment}'`);if(e.publicKey&&!this.isValidPublicKey(e.publicKey))throw new s("INVALID_CONFIGURATION","Invalid public key format");return{projectId:e.projectId,environment:e.environment,publicKey:e.publicKey,features:{encryption:e.features?.encryption??!1,compression:e.features?.compression??!0,batching:e.features?.batching??!0},settings:e.settings}}isValidPublicKey(e){try{return"undefined"!=typeof atob?atob(e):Buffer.from(e,"base64"),e.length>100}catch{return!1}}getDefaultConfig(e){return{projectId:e,environment:"production",features:{encryption:!1,compression:!0,batching:!0}}}getCachedConfig(e){const t=this.configCache.get(e),i=this.cacheTimestamps.get(e);if(t&&i){if(Date.now()-i<this.CACHE_DURATION)return t}return null}setCachedConfig(e,t){this.configCache.set(e,t),this.cacheTimestamps.set(e,Date.now())}getStorageCachedConfig(e){try{if("undefined"==typeof localStorage)return null;const t=localStorage.getItem(Q+e);if(!t)return null;const{config:i,timestamp:s}=JSON.parse(t);if(Date.now()-s<this.CACHE_DURATION)return i;localStorage.removeItem(Q+e)}catch{}return null}setStorageCachedConfig(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(Q+e,JSON.stringify({config:t,timestamp:Date.now()}))}catch{}}clearCache(){try{if("undefined"!=typeof localStorage){const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);i?.startsWith(Q)&&e.push(i)}for(const t of e)localStorage.removeItem(t)}}catch{}this.configCache.clear(),this.configPromises.clear(),this.cacheTimestamps.clear()}},Y=class e{constructor(e,t={}){this.isInitialized=!1,this.globalContext={},this.globalProperties={},this.lastSessionPersistTime=0,this.config={...e},this.options={enableValidation:!0,enableAutoContext:!0,enablePlugins:!0,pluginTimeout:5e3,storageType:"memory",debug:!1,...t},this.configService=new h(this.config),this.contextService=new d(this.config),this.pluginService=new g(this.config,{maxExecutionTime:this.options.pluginTimeout}),this.pluginService.setTrackFn((e,t)=>this.track(e,t)),this.pluginService.setIdentifyFn((e,t)=>this.identify(e,t)),this.storageService=new y({type:this.options.storageType,adapter:this.options.storageAdapter}),this.transportService=new V(this.config,{cryptoAdapter:this.options.cryptoAdapter}),this.remoteConfigService=J.getInstance(),this.eventService=new l(this.config,{contextService:this.contextService,pluginService:this.options.enablePlugins?this.pluginService:void 0,storageService:this.storageService,transportService:this.transportService}),this.options.enableValidation&&(this.eventValidator=new L,this.configValidator=new $),this.contextCache=new q({cacheTime:this.options.contextCacheTime||6e4});const i=this.options.idleScheduler||("undefined"!=typeof window?new K:new M);this.taskScheduler=new G(i)}async initialize(){if(!this.isInitialized)try{await this.validateConfiguration();try{const e=await this.remoteConfigService.getProjectConfig(this.config.apiKey,this.config.environment||"production");this.options.debug&&console.log("[VircleCore] Remote config loaded:",{projectId:e.projectId,environment:e.environment,features:e.features}),this.options.enableEncryption&&e.publicKey?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:e.publicKey}),this.options.debug&&console.log("[VircleCore] Applied remote encryption config")):e.features.encryption&&(console.warn("[VircleCore] Remote config has encryption enabled but no public key provided"),"true"===W("VIRCLE_ALLOW_FALLBACK_KEY","false")&&N.PUBLIC_KEY?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:N.PUBLIC_KEY}),this.options.debug&&console.log("[VircleCore] Using fallback encryption key")):(this.options.enableEncryption=!1,console.warn("[VircleCore] Encryption disabled - no valid public key available"))),e.settings&&(e.settings.batchSize&&!this.config.batch?this.config.batch={size:e.settings.batchSize}:e.settings.batchSize&&this.config.batch&&(this.config.batch.size=e.settings.batchSize),e.settings.flushInterval&&!this.config.batch?this.config.batch={flushInterval:e.settings.flushInterval}:e.settings.flushInterval&&this.config.batch&&(this.config.batch.flushInterval=e.settings.flushInterval),e.settings.maxRetries&&!this.config.retry?this.config.retry={maxAttempts:e.settings.maxRetries}:e.settings.maxRetries&&this.config.retry&&(this.config.retry.maxAttempts=e.settings.maxRetries),this.configService.updateConfig(this.config),this.transportService.updateConfig(this.config))}catch(e){this.options.debug&&console.log("[VircleCore] Failed to load remote config, using defaults",e),"true"===W("VIRCLE_ALLOW_FALLBACK_KEY","false")&&N.PUBLIC_KEY?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:N.PUBLIC_KEY}),this.options.debug&&console.log("[VircleCore] Using fallback encryption key after config fetch failure")):(this.options.enableEncryption=!1,console.warn("[VircleCore] Encryption disabled - remote config failed and no fallback key"))}await this.loadPersistedUser(),await this.restoreOrCreateSession(),this.isInitialized=!0,this.options.enablePlugins&&this.config.plugins&&await this.initializePlugins(),this.options.enablePlugins&&await this.pluginService.executeLifecycle("session-started",{sessionId:this.sessionId,user:this.currentUser}),this.options.debug&&console.log("[VircleCore] Initialized successfully",{config:w(this.config),sessionId:this.sessionId})}catch(e){throw new s("SDK_INITIALIZATION_FAILED",`Failed to initialize Vircle SDK: ${e.message}`,{cause:e})}}async track(e,t,i){this.ensureInitialized();try{const s={name:B(e),properties:F(this.globalProperties,F(t||{},this.currentUser?.anonymousId?{_vuid:this.currentUser.anonymousId}:{})),context:U(this.globalContext,i),userId:this.currentUser?.id,anonymousId:this.currentUser?.anonymousId,sessionId:this.sessionId,timestamp:z()};if(this.eventValidator){const e=this.eventValidator.validate(s);if(!e.isValid)throw new n("Event validation failed",e.errors);this.options.debug&&e.warnings.length>0&&console.warn("[VircleCore] Event validation warnings:",e.warnings)}await this.eventService.track(s),this.persistSession().catch(()=>{})}catch(t){throw this.options.debug&&console.error("[VircleCore] Track error:",t),new s("EVENT_TRACKING_FAILED",`Failed to track event "${e}"`,{cause:t})}}async trackBatch(e){this.ensureInitialized();try{const t=e.map(e=>({name:B(e.name),properties:F(this.globalProperties,F(e.properties||{},this.currentUser?.anonymousId?{_vuid:this.currentUser.anonymousId}:{})),context:U(this.globalContext,e.context),userId:e.userId||this.currentUser?.id,anonymousId:this.currentUser?.anonymousId,sessionId:e.sessionId||this.sessionId,timestamp:z(e.timestamp)}));if(this.eventValidator)for(const e of t){const t=this.eventValidator.validate(e);if(!t.isValid)throw new n(`Event validation failed for "${e.name}"`,t.errors)}for(const e of t)await this.eventService.track(e)}catch(e){throw this.options.debug&&console.error("[VircleCore] TrackBatch error:",e),new s("BATCH_PROCESSING_FAILED","Failed to track batch events",{cause:e})}}createEvent(e){return this.ensureInitialized(),this.eventService.createEvent(e)}async identify(e,i){this.ensureInitialized();try{this.options.debug&&console.log("[VircleCore] Creating user with factory...");const s=t.create(e,i||{},this.currentUser?.anonymousId);this.options.debug&&console.log("[VircleCore] User created successfully:",s),this.currentUser=s,this.options.debug&&console.log("[VircleCore] Persisting user to storage...");try{await this.storageService.set(T,s),this.options.debug&&console.log("[VircleCore] User persisted successfully")}catch(e){this.options.debug&&console.error("[VircleCore] Failed to persist user:",e)}this.options.debug&&console.log("[VircleCore] Sending identify event for user:",e);try{await this.track("identify",{userId:e,...i}),this.options.debug&&console.log("[VircleCore] Identify event tracked successfully")}catch(e){throw this.options.debug&&(console.error("[VircleCore] Failed to track identify event:",e),console.error("[VircleCore] Track error stack:",e instanceof Error?e.stack:"No stack")),e}this.options.enablePlugins&&await this.pluginService.executeLifecycle("user-identified",{user:s,sessionId:this.sessionId}),this.options.debug&&console.log("[VircleCore] User identified:",{userId:e,traits:i})}catch(t){throw this.options.debug&&console.error("[VircleCore] Identify error:",t),new s("USER_IDENTIFICATION_FAILED",`Failed to identify user "${e}"`,{cause:t})}}getAnonymousId(){return this.currentUser?.anonymousId}setAnonymousId(e){this.currentUser&&(this.currentUser={...this.currentUser,anonymousId:e},this.storageService.set(T,this.currentUser).catch(()=>{}),this.options.debug&&console.log("[VircleCore] Anonymous ID overridden:",e))}setSessionId(e){this.sessionId=e,this.options.debug&&console.log("[VircleCore] Session ID updated:",e)}setContext(e){this.globalContext=U(this.globalContext,e),this.options.debug&&console.log("[VircleCore] Global context updated:",this.globalContext)}clearContext(){this.globalContext={},this.options.debug&&console.log("[VircleCore] Global context cleared")}setGlobalProperties(e){this.globalProperties=F(this.globalProperties,e),this.options.debug&&console.log("[VircleCore] Global properties updated:",this.globalProperties)}clearGlobalProperties(){this.globalProperties={},this.options.debug&&console.log("[VircleCore] Global properties cleared")}async registerPlugin(e){if(this.ensureInitialized(),!this.options.enablePlugins)throw new s("PLUGIN_NOT_ENABLED","Plugins are not enabled in SDK configuration");await this.pluginService.register(e),this.options.debug&&console.log("[VircleCore] Plugin registered:",e.name)}async unregisterPlugin(e){if(this.ensureInitialized(),!this.options.enablePlugins)return!1;const t=await this.pluginService.unregister(e);return this.options.debug&&t&&console.log("[VircleCore] Plugin unregistered:",e),t}async updateConfig(e){this.ensureInitialized();try{const t={...this.config,...e};if(this.configValidator){const e=this.configValidator.validate(t);if(!e.isValid)throw new n("Configuration validation failed",e.errors)}this.config=t,this.configService.updateConfig(this.config),this.transportService.updateConfig(this.config),this.options.enablePlugins&&await this.pluginService.executeLifecycle("config-changed",{config:this.config}),this.options.debug&&console.log("[VircleCore] Configuration updated:",e)}catch(e){if(this.options.debug&&console.error("[VircleCore] Config update error:",e),e instanceof s)throw e;throw new s("CONFIG_UPDATE_FAILED","Failed to update configuration",{cause:e})}}async flush(e){if(this.ensureInitialized(),e){const t=new Promise((t,i)=>{setTimeout(()=>i(new Error("Flush timeout")),e)});await Promise.race([this.transportService.flush(),t])}else await this.transportService.flush();this.options.debug&&console.log("[VircleCore] Events flushed")}async reset(){this.ensureInitialized();try{this.currentUser=void 0,this.sessionId=this.generateSessionId(),this.globalContext={},this.globalProperties={},await this.persistSession(!0),await this.storageService.clear(),this.options.enablePlugins&&(await this.pluginService.executeLifecycle("session-ended"),await this.pluginService.executeLifecycle("session-started",{sessionId:this.sessionId})),this.options.debug&&console.log("[VircleCore] SDK reset completed")}catch(e){throw this.options.debug&&console.error("[VircleCore] Reset error:",e),e}}getStatus(){return{isInitialized:this.isInitialized,sessionId:this.sessionId,userId:this.currentUser?.id,pluginCount:this.options.enablePlugins?this.pluginService.getPluginCount():0,queueSize:this.transportService.getQueueStatus().queueSize}}getMetrics(){const e=this.transportService.getQueueStatus();return{queueSize:e.queueSize,isProcessing:e.isProcessing}}async cleanup(){if(!this.isInitialized)return;const e=[];try{await this.flush()}catch(t){e.push(new s("FLUSH_FAILED","Failed to flush events during cleanup",{cause:t}))}try{this.options.enablePlugins&&(await this.pluginService.executeLifecycle("session-ended"),await this.pluginService.cleanup())}catch(t){e.push(new s("PLUGIN_ERROR","Failed to cleanup plugins",{cause:t}))}this.transportService.clearQueue();try{this.eventService.dispose();const e=[this.storageService,this.contextService,this.transportService,this.pluginService];for(const t of e)if(t&&"dispose"in t&&"function"==typeof t.dispose)try{t.dispose()}catch(e){console.warn("[VircleCore] Error disposing service:",e)}this.taskScheduler.clear(),this.contextCache.clear()}catch(t){e.push(new s("CLEANUP_ERROR","Failed to dispose services",{cause:t}))}if(this.currentUser=void 0,this.sessionId=void 0,this.globalContext={},this.globalProperties={},this.isInitialized=!1,e.length>0){const t=`Cleanup completed with ${e.length} error(s): ${e.map(e=>e.message).join("; ")}`;throw this.options.debug&&console.error("[VircleCore] "+t,e),new s("CLEANUP_ERROR",t,{context:{errors:e}})}this.options.debug&&console.log("[VircleCore] Cleanup completed successfully")}ensureInitialized(){if(!this.isInitialized)throw new s("SDK_NOT_INITIALIZED","Vircle SDK must be initialized before use. Call initialize() first.")}async validateConfiguration(){if(!this.configValidator)return;const e=this.configValidator.validate(this.config);if(!e.isValid)throw new r("Invalid SDK configuration",{context:{errors:e.errors}});this.options.debug&&e.warnings.length>0&&console.warn("[VircleCore] Configuration warnings:",e.warnings)}async initializePlugins(){if(!this.config.plugins||!this.options.enablePlugins)return;const e=[];for(const t of this.config.plugins)try{await this.pluginService.register(t),this.options.debug&&console.log(`[VircleCore] Plugin auto-loaded: ${t.name}`)}catch(i){e.push(i),this.options.debug&&console.warn(`[VircleCore] Failed to auto-load plugin '${t.name}':`,i)}e.length>0&&this.options.debug&&console.warn(`[VircleCore] Plugin initialization completed with ${e.length} error(s)`)}async loadPersistedUser(){try{const e=await this.storageService.get(T);if(e)return this.currentUser=e,void(this.options.debug&&console.log("[VircleCore] Loaded persisted user:",e.id))}catch(e){this.options.debug&&console.warn("[VircleCore] Failed to load persisted user:",e)}const e=t.create("",{});this.currentUser=e;try{await this.storageService.set(T,e)}catch(e){this.options.debug&&console.warn("[VircleCore] Failed to persist anonymous user:",e)}this.options.debug&&console.log("[VircleCore] Created anonymous user:",e.anonymousId)}async restoreOrCreateSession(){try{const t=await this.storageService.get(k);if(t){if(Date.now()-t.lastActivity<e.SESSION_TIMEOUT_MS)return this.sessionId=t.id,void await this.persistSession(!0)}}catch{}this.sessionId=this.generateSessionId(),await this.persistSession(!0)}async persistSession(t=!1){if(!this.sessionId)return;const i=Date.now();if(t||!(i-this.lastSessionPersistTime<e.SESSION_PERSIST_THROTTLE_MS))try{await this.storageService.set(k,{id:this.sessionId,lastActivity:i}),this.lastSessionPersistTime=i}catch{}}generateSessionId(){return`sess_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}};Y.SESSION_TIMEOUT_MS=18e5,Y.SESSION_PERSIST_THROTTLE_MS=1e4;var Z=Y;class X{async collect(){const[e,t,i]=await Promise.all([this.collectDeviceContext(),this.collectPageContext(),this.collectAppContext()]),s={device:e,page:t,app:i,custom:this.collectCustomContext()},r=this.collectCampaignContext();return r&&(s.campaign=r),s}async collectDeviceContext(){const e=navigator.userAgent,t=navigator.platform||"unknown";return{type:this.getDeviceType(e),os:this.getOS(e,t),osVersion:this.getOSVersion(e),browser:this.getBrowser(e),browserVersion:this.getBrowserVersion(e),screenResolution:`${screen.width}x${screen.height}`,viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}async collectPageContext(){const e=new URL(window.location.href);return{url:e.href,title:document.title,path:e.pathname,search:e.search,hash:e.hash}}async collectAppContext(){return{name:this.getAppName(),version:this.getAppVersion(),environment:this.getEnvironment()}}collectCustomContext(){const e={};document.referrer&&(e.referrer=document.referrer),e.cookieEnabled=navigator.cookieEnabled,navigator.doNotTrack&&(e.doNotTrack="1"===navigator.doNotTrack);const t=navigator;t.connection&&(e.connection={effectiveType:t.connection.effectiveType,downlink:t.connection.downlink,rtt:t.connection.rtt,saveData:t.connection.saveData});const i=performance;return i.memory&&(e.memory={usedJSHeapSize:i.memory.usedJSHeapSize,totalJSHeapSize:i.memory.totalJSHeapSize,jsHeapSizeLimit:i.memory.jsHeapSizeLimit}),e}getDeviceType(e){return/mobile/i.test(e)&&!/ipad/i.test(e)?"mobile":/ipad|tablet|playbook|silk/i.test(e)?"tablet":"desktop"}getOS(e,t){return/windows/i.test(e)?"Windows":/macintosh|mac os x/i.test(e)?"macOS":/linux/i.test(e)?"Linux":/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/cros/i.test(e)?"Chrome OS":t}getOSVersion(e){let t=null;return/windows nt (\d+\.\d+)/i.test(e)?t=e.match(/windows nt (\d+\.\d+)/i):/mac os x (\d+[._]\d+)/i.test(e)?t=e.match(/mac os x (\d+[._]\d+)/i):/android (\d+\.\d+)/i.test(e)?t=e.match(/android (\d+\.\d+)/i):/os (\d+[._]\d+)/i.test(e)&&(t=e.match(/os (\d+[._]\d+)/i)),t?t[1].replace(/_/g,"."):void 0}getBrowser(e){return/edg/i.test(e)?"Edge":/chrome|chromium|crios/i.test(e)?"Chrome":/firefox|fxios/i.test(e)?"Firefox":/safari/i.test(e)&&!/chrome/i.test(e)?"Safari":/opr|opera/i.test(e)?"Opera":/trident/i.test(e)?"IE":"Unknown"}getBrowserVersion(e){let t=null;return/edg\/(\d+\.\d+)/i.test(e)?t=e.match(/edg\/(\d+\.\d+)/i):/chrome\/(\d+\.\d+)/i.test(e)?t=e.match(/chrome\/(\d+\.\d+)/i):/firefox\/(\d+\.\d+)/i.test(e)?t=e.match(/firefox\/(\d+\.\d+)/i):/version\/(\d+\.\d+).*safari/i.test(e)?t=e.match(/version\/(\d+\.\d+).*safari/i):/opr\/(\d+\.\d+)/i.test(e)&&(t=e.match(/opr\/(\d+\.\d+)/i)),t?t[1]:void 0}collectCampaignContext(){if("undefined"==typeof window)return;const e=new URLSearchParams(window.location.search),t=Object.keys(X.CAMPAIGN_PARAMS_MAP);let i=!1;for(const s of t)if(e.get(s)){i=!0;break}if(i){for(const e of t)try{sessionStorage.removeItem(X.STORAGE_PREFIX+e)}catch{}for(const i of t){const t=e.get(i);if(t)try{sessionStorage.setItem(X.STORAGE_PREFIX+i,t)}catch{}}}const s={};let r=!1;for(const[e,t]of Object.entries(X.CAMPAIGN_PARAMS_MAP))try{const i=sessionStorage.getItem(X.STORAGE_PREFIX+e);i&&(s[t]=i,r=!0)}catch{}return r?s:void 0}getAppName(){const e=document.querySelector('meta[name="application-name"]'),t=document.querySelector('meta[property="og:site_name"]');return e?.content||t?.content||document.title||"Web App"}getAppVersion(){const e=document.querySelector('meta[name="version"]');return e?.content||void 0}getEnvironment(){const e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e||e.includes(".local")||e.includes("staging")||e.includes("stage")||e.includes("test")?"development":"production"}}X.CAMPAIGN_PARAMS_MAP={utm_source:"source",utm_medium:"medium",utm_campaign:"campaign",utm_term:"term",utm_content:"content",gclid:"gclid",fbclid:"fbclid",msclkid:"msclkid",ttclid:"ttclid"},X.STORAGE_PREFIX="__vircle_campaign_";class ee extends Error{constructor(e,t,i){super(e),this.code=t,this.details=i,this.name="VircleWebError",Error.captureStackTrace&&Error.captureStackTrace(this,ee)}}class te extends ee{constructor(e,t){super(e,"CONFIG_ERROR",t),this.name="VircleConfigError"}}class ie extends ee{constructor(e,t){super(e,"INITIALIZATION_ERROR",t),this.name="VircleInitializationError"}}class se extends ee{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="VircleStorageError"}}class re extends ee{constructor(e,t){super(e,"BROWSER_COMPATIBILITY_ERROR",t),this.name="VircleBrowserCompatibilityError"}}class ne{constructor(e="vircle_"){this.prefix=e,this.isAvailable=this.checkAvailability()}checkAvailability(){try{const e=`${this.prefix}test`;return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return console.warn("[Vircle] LocalStorage를 사용할 수 없습니다. 메모리 스토리지로 대체됩니다."),!1}}getKey(e){return`${this.prefix}${e}`}getFullKey(e){return this.getKey(e)}async set(e,t){if(!this.isAvailable)return;const i={value:t,timestamp:Date.now()};try{const t=JSON.stringify(i);localStorage.setItem(this.getKey(e),t)}catch(t){if(t instanceof Error&&"QuotaExceededError"===t.name){console.warn("[Vircle] LocalStorage 용량 초과. 오래된 항목을 정리합니다."),await this.clearOldItems();try{const t=JSON.stringify(i);localStorage.setItem(this.getKey(e),t)}catch(t){throw new se("LocalStorage 저장 실패",{key:e,error:t instanceof Error?t.message:String(t)})}}}}async get(e){if(!this.isAvailable)return null;try{const t=localStorage.getItem(this.getKey(e));if(null===t)return null;try{const e=JSON.parse(t);return e&&"object"==typeof e&&"value"in e&&"timestamp"in e?e.value:e}catch(t){return console.warn(`[Vircle] Failed to parse stored value for key "${e}":`,t),null}}catch(t){return console.warn(`[Vircle] Failed to get value from localStorage for key "${e}":`,t),null}}async remove(e){if(!this.isAvailable)return!1;try{const t=this.getKey(e);return!!(null!==localStorage.getItem(t))&&(localStorage.removeItem(t),!0)}catch{return!1}}async clear(){if(this.isAvailable)try{const e=Object.keys(localStorage).filter(e=>e.startsWith(this.prefix));e.forEach(e=>{try{localStorage.removeItem(e)}catch(t){console.warn(`[Vircle] Failed to remove key "${e}" during clear:`,t)}})}catch(e){console.warn("[Vircle] Failed to clear localStorage:",e)}}async has(e){if(!this.isAvailable)return!1;try{return null!==localStorage.getItem(this.getKey(e))}catch{return!1}}async size(){if(!this.isAvailable)return 0;try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).length}catch{return 0}}async keys(){if(!this.isAvailable)return[];try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).map(e=>e.substring(this.prefix.length))}catch{return[]}}async clearOldItems(){try{const e=[],t=Object.keys(localStorage).filter(e=>e.startsWith(this.prefix));for(const i of t)try{const t=localStorage.getItem(i);if(t){const s=JSON.parse(t);s&&"object"==typeof s&&"timestamp"in s&&e.push({key:i,timestamp:s.timestamp||0})}}catch{}e.sort((e,t)=>e.timestamp-t.timestamp);const i=Math.max(1,Math.floor(.2*e.length));for(let t=0;t<i&&t<e.length;t++)localStorage.removeItem(e[t].key)}catch(e){console.error("[Vircle] LocalStorage 정리 중 오류:",e)}}async setWithTimestamp(e,t){await this.set(e,t)}}class oe{constructor(e="vircle_"){this.db=null,this.storeName="vircle_store",this.dbVersion=1,this.initPromise=null,this.isClosed=!1,this.prefix=e,this.dbName=`${e}db`}async init(){if(this.isClosed)throw new se("IndexedDB adapter가 이미 닫혔습니다");if(this.initPromise)return this.initPromise;if(this.db)return Promise.resolve();this.initPromise=this.openDB();try{await this.initPromise}catch(e){throw this.initPromise=null,e}return this.initPromise}async openDB(){return new Promise((e,t)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{t(new se("IndexedDB 열기 실패",{error:i.error?.message}))},i.onsuccess=()=>{this.db=i.result,e()},i.onupgradeneeded=e=>{const t=e.target.result;if(!t.objectStoreNames.contains(this.storeName)){t.createObjectStore(this.storeName,{keyPath:"key"}).createIndex("timestamp","timestamp",{unique:!1})}}})}getKey(e){return`${this.prefix}${e}`}async set(e,t){return await this.init(),new Promise((i,s)=>{if(!this.db)return void s(new se("IndexedDB가 초기화되지 않음"));const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),n={key:this.getKey(e),value:t,timestamp:Date.now()},o=r.put(n);o.onerror=()=>{s(new se("IndexedDB 저장 실패",{key:e,error:o.error?.message}))},o.onsuccess=()=>{i()}})}async get(e){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new se("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).get(this.getKey(e));s.onerror=()=>{i(new se("IndexedDB 읽기 실패",{key:e,error:s.error?.message}))},s.onsuccess=()=>{const e=s.result;t(e&&"value"in e?e.value:null)}})}async remove(e){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new se("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).delete(this.getKey(e));s.onerror=()=>{i(new se("IndexedDB 삭제 실패",{key:e,error:s.error?.message}))},s.onsuccess=()=>{t(!0)}})}async clear(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new se("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),s=i.openCursor(),r=[];s.onsuccess=()=>{const n=s.result;if(n)n.key.toString().startsWith(this.prefix)&&r.push(n.key),n.continue();else{const s=r.map(e=>new Promise((t,s)=>{const r=i.delete(e);r.onsuccess=()=>t(),r.onerror=()=>s(r.error)}));Promise.all(s).then(()=>e()).catch(e=>t(new se("일부 항목 삭제 실패",{error:e})))}},s.onerror=()=>{t(new se("IndexedDB 커서 열기 실패",{error:s.error?.message}))}})}async has(e){return null!==await this.get(e)}async size(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new se("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor();let s=0;i.onsuccess=()=>{const t=i.result;t?(t.key.toString().startsWith(this.prefix)&&s++,t.continue()):e(s)},i.onerror=()=>{t(new se("IndexedDB 카운트 실패",{error:i.error?.message}))}})}async keys(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new se("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor(),s=[];i.onsuccess=()=>{const t=i.result;if(t){const e=t.key.toString();e.startsWith(this.prefix)&&s.push(e.substring(this.prefix.length)),t.continue()}else e(s)},i.onerror=()=>{t(new se("IndexedDB 키 조회 실패",{error:i.error?.message}))}})}async clearOldItems(e=.2){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new se("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),r=s.index("timestamp").openCursor(),n=[];r.onsuccess=async()=>{const o=r.result;if(o){const e=o.primaryKey;e.startsWith(this.prefix)&&n.push({key:e,timestamp:o.value.timestamp}),o.continue()}else{n.sort((e,t)=>e.timestamp-t.timestamp);const r=Math.max(1,Math.floor(n.length*e)),o=n.slice(0,r).map(e=>e.key).map(e=>new Promise((t,i)=>{const r=s.delete(e);r.onsuccess=()=>t(),r.onerror=()=>i(r.error)}));Promise.all(o).then(()=>t()).catch(e=>i(new se("일부 항목 삭제 실패",{error:e})))}},r.onerror=()=>{i(new se("IndexedDB 인덱스 조회 실패",{error:r.error?.message}))}})}async close(){this.isClosed=!0,this.db&&(this.db.close(),this.db=null),this.initPromise=null}}class ae{static create(e="vircle_",t="auto"){switch(t){case"localStorage":return new ne(e);case"indexedDB":return new oe(e);default:return this.createAuto(e)}}static async createAsync(e="vircle_",t="auto"){switch(t){case"localStorage":return new ne(e);case"indexedDB":return new oe(e);default:return this.createAutoAsync(e)}}static async createAutoAsync(e){return await this.isIndexedDBAvailableAsync()?new oe(e):new ne(e)}static createAuto(e){if(this.isIndexedDBAvailable())try{return new oe(e)}catch(e){console.warn("[Vircle] IndexedDB 초기화 실패, LocalStorage로 폴백합니다:",e)}return new ne(e)}static isIndexedDBAvailable(){try{return"undefined"!=typeof window&&!!window.indexedDB}catch{return!1}}static async isIndexedDBAvailableAsync(){return!("undefined"==typeof window||!window.indexedDB)&&new Promise(e=>{try{const t=indexedDB.open("vircle_availability_test");t.onsuccess=()=>{t.result.close(),indexedDB.deleteDatabase("vircle_availability_test"),e(!0)},t.onerror=()=>{e(!1)},t.onblocked=()=>{e(!1)}}catch{e(!1)}})}static isLocalStorageAvailable(){try{const e="__vircle_test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}}class ce{constructor(){this.crypto=null,this.subtle=null,this.available=!1,this.initCrypto()}initCrypto(){try{"undefined"!=typeof window&&window.crypto&&window.crypto.subtle?(this.crypto=window.crypto,this.subtle=window.crypto.subtle,this.available=!0):"undefined"!=typeof globalThis&&globalThis.crypto&&globalThis.crypto.subtle&&(this.crypto=globalThis.crypto,this.subtle=globalThis.crypto.subtle,this.available=!0)}catch(e){console.warn("[Vircle] Web Crypto API를 사용할 수 없습니다:",e),this.available=!1}}generateUUID(){if(this.crypto&&"function"==typeof this.crypto.randomUUID)return this.crypto.randomUUID();if(this.crypto){const e=new Uint8Array(16);this.crypto.getRandomValues(e),e[6]=15&e[6]|64,e[8]=63&e[8]|128;const t=Array.from(e).map(e=>e.toString(16).padStart(2,"0")).join("");return[t.substring(0,8),t.substring(8,12),t.substring(12,16),t.substring(16,20),t.substring(20,32)].join("-")}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}async createHmacSignature(e,t){if(!this.subtle)throw new Error("Web Crypto API is required for HMAC operations");const i=new TextEncoder,s=JSON.stringify(e),r=i.encode(t),n=await this.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await this.subtle.sign("HMAC",n,i.encode(s));return this.arrayBufferToHex(o)}async encryptPayload(e,t){if(!this.subtle||!this.crypto)throw new Error("Web Crypto API is required for encryption operations");let i="initialization";try{i="JSON serialization";const s=JSON.stringify(e),r=(new TextEncoder).encode(s);i="AES key generation";const n=await this.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt"]);i="IV generation";const o=this.crypto.getRandomValues(new Uint8Array(12));i="AES-GCM encryption";const a=await this.subtle.encrypt({name:"AES-GCM",iv:o,tagLength:128},n,r),c=new Uint8Array(a),l=c.slice(0,-16),u=c.slice(-16);i="AES key export";const h=await this.subtle.exportKey("raw",n);i="RSA public key import";const d=await this.importRsaPublicKey(t);i="RSA-OAEP encryption";const g=await this.subtle.encrypt({name:"RSA-OAEP"},d,h);return i="Base64 encoding",{data:this.arrayBufferToBase64(l),key:this.arrayBufferToBase64(g),iv:this.arrayBufferToBase64(o),authTag:this.arrayBufferToBase64(u),metadata:{algorithm:"AES-256-GCM",keyAlgorithm:"RSA-OAEP",timestamp:(new Date).toISOString()}}}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`[WebExtendedCryptoAdapter] Encryption failed at step '${i}': ${t}`)}}isAvailable(){return this.available}async importRsaPublicKey(e){if(!this.subtle)throw new Error("Web Crypto API is not available");const t=e.replace(/-----BEGIN PUBLIC KEY-----/g,"").replace(/-----END PUBLIC KEY-----/g,"").replace(/-----BEGIN RSA PUBLIC KEY-----/g,"").replace(/-----END RSA PUBLIC KEY-----/g,"").replace(/\s/g,""),i=this.base64ToArrayBuffer(t);return await this.subtle.importKey("spki",i,{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"])}arrayBufferToBase64(e){const t=e instanceof Uint8Array?e:new Uint8Array(e);let i="";for(let e=0;e<t.length;e+=32768){const s=t.slice(e,Math.min(e+32768,t.length));i+=String.fromCharCode.apply(null,Array.from(s))}return btoa(i)}base64ToArrayBuffer(e){const t=atob(e),i=new Uint8Array(t.length);for(let e=0;e<t.length;e++)i[e]=t.charCodeAt(e);return i.buffer}arrayBufferToHex(e){const t=new Uint8Array(e);return Array.from(t).map(e=>e.toString(16).padStart(2,"0")).join("")}}class le extends Z{constructor(e,t={}){const i=ae.create(e.storagePrefix||"vircle_",e.storageType||"auto");let s;(e.enableEncryption||t.enableEncryption)&&(s=new ce,s.isAvailable()||(console.warn("[Vircle] Web Crypto API를 사용할 수 없습니다. 암호화를 비활성화합니다."),s=void 0));super(e,{...t,storageAdapter:i,cryptoAdapter:s,enableEncryption:s?.isAvailable()??!1}),this.pageViewTracked=!1,this.lastActivityTime=Date.now(),this.webConfig=e,this.webOptions={flushOnUnload:!0,contextCacheTime:3e5,idleScheduler:new K,...t},this.contextCollector=new X,this.sessionTimeout=e.sessionTimeout??18e5}async initialize(){try{await super.initialize(),this.applyUrlVuid(),this.setupAutoTracking();const e=await this.contextCollector.collect();this.setContext(e),this.webConfig.trackPageViews&&!this.pageViewTracked&&(await this.trackPageView(),this.pageViewTracked=!0)}catch(e){throw console.error("[Vircle] 초기화 실패:",e),e}}applyUrlVuid(){try{const e=new URLSearchParams(window.location.search).get("_vuid");e&&this.setAnonymousId(e)}catch{}}async identify(e,t){return this.contextCache.invalidate(),super.identify(e,t)}async trackPageView(e,t){const i=await this.contextCollector.collectPageContext();return this.track("page_view",{...i,...e},t)}async track(e,t,i){return this.lastActivityTime=Date.now(),new Promise(s=>{this.taskScheduler.enqueue(async()=>{try{const r={...await this.getCachedContext(),...i};await super.track(e,t,r),s()}catch(t){console.warn(`[Vircle] 이벤트 추적 실패 "${e}":`,t),s()}})})}async getCachedContext(){return this.contextCache.getOrCollect(()=>this.contextCollector.collect())}setupAutoTracking(){this.webOptions.flushOnUnload&&(this.unloadHandler=()=>{this.transportService.flushWithKeepalive()},window.addEventListener("beforeunload",this.unloadHandler),this.visibilityChangeHandler=()=>{"hidden"===document.visibilityState?this.transportService.flushWithKeepalive():"visible"===document.visibilityState&&this.checkSessionTimeout()},document.addEventListener("visibilitychange",this.visibilityChangeHandler)),this.webConfig.trackErrors&&this.setupErrorTracking(),this.webConfig.trackClicks&&this.setupClickTracking(),this.webConfig.trackForms&&this.setupFormTracking(),this.webConfig.singlePageApp&&this.setupSPATracking()}setupErrorTracking(){this.errorHandler=e=>{this.track("error",{message:e.message,source:e.filename,line:e.lineno,column:e.colno,stack:e.error?.stack}).catch(e=>{console.warn("[Vircle] 에러 추적 실패:",e)})},this.unhandledRejectionHandler=e=>{this.track("unhandled_rejection",{reason:e.reason?.toString(),promise:e.promise?.toString()}).catch(e=>{console.warn("[Vircle] Promise rejection 추적 실패:",e)})},window.addEventListener("error",this.errorHandler),window.addEventListener("unhandledrejection",this.unhandledRejectionHandler)}setupClickTracking(){this.clickHandler=e=>{const t=e.target;if(!this.shouldTrackElement(t))return;const i=this.extractElementProperties(t);this.track("element_clicked",i).catch(e=>{console.warn("[Vircle] 클릭 추적 실패:",e)})},document.addEventListener("click",this.clickHandler,!0)}setupFormTracking(){this.submitHandler=e=>{const t=e.target,i={form_id:t.id,form_name:t.name,form_action:t.action,form_method:t.method};this.track("form_submitted",i).catch(e=>{console.warn("[Vircle] 폼 제출 추적 실패:",e)})},document.addEventListener("submit",this.submitHandler,!0)}setupSPATracking(){this.originalPushState=history.pushState,this.originalReplaceState=history.replaceState;const e=(...e)=>{this.originalPushState.apply(history,e);try{this.handleRouteChange()}catch(e){}};e.__vircle_wrapped=!0,history.pushState=e;const t=(...e)=>{this.originalReplaceState.apply(history,e);try{this.handleRouteChange()}catch(e){}};t.__vircle_wrapped=!0,history.replaceState=t,this.popstateHandler=()=>{this.handleRouteChange()},window.addEventListener("popstate",this.popstateHandler)}handleRouteChange(){this.contextCache.invalidate(),this.webConfig.trackPageViews&&this.trackPageView().catch(e=>{console.warn("[Vircle] 라우트 변경 추적 실패:",e)})}checkSessionTimeout(){const e=Date.now(),t=e-this.lastActivityTime;if(t>=this.sessionTimeout){const i=`sess_${e}_${Math.random().toString(36).substr(2,9)}`;this.setSessionId(i),this.lastActivityTime=e,this.contextCache.invalidate(),this.track("session_start",{reason:"timeout",previous_session_duration:t}).catch(e=>{console.warn("[Vircle] 세션 시작 추적 실패:",e)})}else this.lastActivityTime=e}shouldTrackElement(e){if(e.hasAttribute("data-vircle-ignore"))return!1;let t=e.parentElement;for(;t;){if(t.hasAttribute("data-vircle-ignore"))return!1;t=t.parentElement}return["A","BUTTON","INPUT","SELECT","TEXTAREA"].includes(e.tagName)}extractElementProperties(e){const t={tag_name:e.tagName.toLowerCase(),element_id:e.id||void 0,element_class:e.className||void 0,element_href:e.href||void 0,element_text:e.textContent?.slice(0,100)||void 0};return this.taskScheduler.enqueue(()=>{const i={};Array.from(e.attributes).forEach(e=>{e.name.startsWith("data-")&&!e.name.startsWith("data-vircle-")&&(i[e.name]=e.value)}),Object.keys(i).length>0&&this.track("element_data_collected",{...t,data_attributes:i}).catch(()=>{})}),t}async cleanup(){try{this.unloadHandler&&window.removeEventListener("beforeunload",this.unloadHandler),this.errorHandler&&window.removeEventListener("error",this.errorHandler),this.unhandledRejectionHandler&&window.removeEventListener("unhandledrejection",this.unhandledRejectionHandler),this.clickHandler&&document.removeEventListener("click",this.clickHandler,!0),this.submitHandler&&document.removeEventListener("submit",this.submitHandler,!0),this.visibilityChangeHandler&&document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=void 0),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=void 0),await this.flush(),await super.cleanup()}catch(e){throw console.error("[Vircle] 정리 중 오류:",e),e}}getCurrentUrl(){return window.location.href}isOnline(){return navigator.onLine}}var ue="undefined"!=typeof fetch?fetch:()=>{throw new Error("Fetch API is not available")};const he=window.Headers,de=window.Request,ge=window.Response;var pe=Object.freeze({__proto__:null,Headers:he,Request:de,Response:ge,default:ue});export{oe as IndexedDBAdapter,ne as LocalStorageAdapter,ae as StorageFactory,re as VircleBrowserCompatibilityError,te as VircleConfigError,ie as VircleInitializationError,se as VircleStorageError,le as VircleWeb,ee as VircleWebError,X as WebContextCollector,ce as WebExtendedCryptoAdapter,le as default};
|
|
1
|
+
var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),t=class{static create(e,t,i){const s=(new Date).toISOString();return{id:e||void 0,anonymousId:i||this.generateAnonymousId(),traits:t||{},preferences:this.getDefaultPreferences(),createdAt:s,updatedAt:s}}static generateAnonymousId(){const e=globalThis.crypto;if(e?.randomUUID)return e.randomUUID();if(e?.getRandomValues){const t=e.getRandomValues(new Uint8Array(16));if(t){t[6]=15&t[6]|64,t[8]=63&t[8]|128;const e=Array.from(t,e=>e.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}static getDefaultPreferences(){let e="en";try{"undefined"!=typeof navigator&&navigator&&"language"in navigator&&"string"==typeof navigator.language&&navigator.language.length>0&&(e=navigator.language.split("-")[0])}catch(e){}let t="UTC";try{if("undefined"!=typeof Intl&&Intl&&Intl.DateTimeFormat){t=Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}}catch(e){}return{language:e,timezone:t,theme:"auto",notifications:{email:!1,push:!1,sms:!1},privacy:{analytics:!0,marketing:!1,functional:!0}}}},i={analytics:!0,marketing:!0,functional:!0};function s(e){if("string"!=typeof e)return null;const t=e.trim().toLowerCase();if(!t)return null;const i=t.indexOf("@");return i<=0||i===t.length-1?null:t}function n(e){if("string"!=typeof e)return null;const t=e.replace(/\D/g,"");return t.length<7?null:t}function r(e,t){if(null==e)return[];const i=Array.isArray(e)?e:[e],s=new Set,n=[];for(const e of i){const i=t(e);i&&!s.has(i)&&(s.add(i),n.push(i))}return n}function o(e){if(null==e)return[];const t=Array.isArray(e)?e:[e],i=new Set,s=[],n=/^[a-f0-9]{64}$/;for(const e of t){if("string"!=typeof e)continue;const t=e.toLowerCase().trim();n.test(t)&&!i.has(t)&&(i.add(t),s.push(t))}return s}var a={UNKNOWN_ERROR:{code:"UNKNOWN_ERROR",severity:"high",category:"system",retryable:!1,userMessage:"An unknown error occurred"},INITIALIZATION_ERROR:{code:"INITIALIZATION_ERROR",severity:"critical",category:"configuration",retryable:!1,userMessage:"Failed to initialize SDK"},MISSING_API_KEY:{code:"MISSING_API_KEY",severity:"critical",category:"configuration",retryable:!1,userMessage:"API key is required",troubleshooting:["Check that apiKey is provided in configuration","Verify API key is not empty or null"]},NETWORK_ERROR:{code:"NETWORK_ERROR",severity:"medium",category:"network",retryable:!0,userMessage:"Network connection failed"},REQUEST_TIMEOUT:{code:"REQUEST_TIMEOUT",severity:"medium",category:"network",retryable:!0,userMessage:"Request timed out"},VALIDATION_ERROR:{code:"VALIDATION_ERROR",severity:"medium",category:"validation",retryable:!1,userMessage:"Data validation failed"},EVENT_TOO_LARGE:{code:"EVENT_TOO_LARGE",severity:"medium",category:"validation",retryable:!1,userMessage:"Event size exceeds maximum limit",troubleshooting:["Reduce event payload size","Remove unnecessary properties","Consider splitting large events"]},STORAGE_UNAVAILABLE:{code:"STORAGE_UNAVAILABLE",severity:"high",category:"storage",retryable:!1,userMessage:"Storage is not available"},PLUGIN_NOT_FOUND:{code:"PLUGIN_NOT_FOUND",severity:"medium",category:"plugin",retryable:!1,userMessage:"Plugin not found"},FEATURE_NOT_SUPPORTED:{code:"FEATURE_NOT_SUPPORTED",severity:"low",category:"feature",retryable:!1,userMessage:"Feature is not supported in this environment"},CONSENT_REQUIRED:{code:"CONSENT_REQUIRED",severity:"medium",category:"privacy",retryable:!1,userMessage:"User consent is required for data collection"},ENCRYPTION_ERROR:{code:"ENCRYPTION_ERROR",severity:"high",category:"system",retryable:!1,userMessage:"Data encryption failed",troubleshooting:["Ensure the provided public key is valid and in the correct format (DER-encoded SPKI, then Base64)","Verify that the crypto environment (Web Crypto API or Node.js crypto) is available and not corrupted"]}},c=class e extends Error{constructor(t,i,s={}){const n=a[t]||a.UNKNOWN_ERROR;super(i||n.userMessage||`Error: ${t}`),this.name="VircleError",this.code=t,this.timestamp=s.timestamp||(new Date).toISOString(),this.context=s.context||{},this.requestId=s.requestId,this.userId=s.userId,this.sessionId=s.sessionId,this.cause=s.cause,this.metadata={...n,...s.metadata},this.severity=this.metadata.severity,this.category=this.metadata.category,this.retryable=this.metadata.retryable,Error.captureStackTrace&&Error.captureStackTrace(this,e)}toJSON(){return{name:this.name,code:this.code,message:this.message,severity:this.severity,category:this.category,retryable:this.retryable,timestamp:this.timestamp,context:this.context,requestId:this.requestId,userId:this.userId,sessionId:this.sessionId,stack:this.stack,cause:this.cause?{name:this.cause.name,message:this.cause.message,stack:this.cause.stack}:void 0,metadata:this.metadata}}getUserMessage(){return this.metadata.userMessage||this.message}getTroubleshooting(){return this.metadata.troubleshooting||[]}shouldRetry(){return this.retryable}static fromHttpError(t,i,s={}){let n;switch(t){case 400:n="VALIDATION_ERROR";break;case 401:n="UNAUTHORIZED";break;case 403:n="FORBIDDEN";break;case 404:n="NOT_FOUND";break;case 408:case 504:n="REQUEST_TIMEOUT";break;case 413:n="EVENT_TOO_LARGE";break;case 429:n="TOO_MANY_REQUESTS";break;case 500:case 502:n="SERVER_ERROR";break;case 503:n="SERVICE_UNAVAILABLE";break;default:n="NETWORK_ERROR"}return new e(n,i,{...s,context:{...s.context,httpStatus:t}})}static fromError(t,i="UNKNOWN_ERROR",s={}){return new e(i,t.message,{...s,cause:t})}},l=class extends c{constructor(e,t={}){super("INVALID_CONFIGURATION",e,t),this.name="ConfigurationError"}},u=class extends c{constructor(e,t=[],i={}){super("VALIDATION_ERROR",e,i),this.name="ValidationError",this.validationErrors=t}toJSON(){return{...super.toJSON(),validationErrors:this.validationErrors}}},h=class extends c{constructor(e,t,i={}){super(t&&t>=500?"SERVER_ERROR":"NETWORK_ERROR",e,i),this.name="NetworkError",this.httpStatus=t,this.responseBody=i.context?.responseBody}toJSON(){return{...super.toJSON(),httpStatus:this.httpStatus,responseBody:this.responseBody}}},d=class extends c{constructor(e,t,i="PLUGIN_ERROR",s={}){super(i,t,{...s,context:{...s.context,pluginName:e}}),this.name="PluginError",this.pluginName=e}toJSON(){return{...super.toJSON(),pluginName:this.pluginName}}},p=class extends c{constructor(e,t="STORAGE_ERROR",i={}){super(t,e,i),this.name="StorageError"}};function g(e){return e.trim()}function m(e={},t={}){const i={};for(const[t,s]of Object.entries(e))i[t]=y(s);for(const[e,s]of Object.entries(t))"object"!=typeof s||null===s||Array.isArray(s)||"object"!=typeof i[e]||null===i[e]||Array.isArray(i[e])?i[e]=y(s):i[e]=m(i[e],s);return i}function f(e={},t={}){const i={};for(const[t,s]of Object.entries(e))i[t]=y(s);for(const[e,s]of Object.entries(t))"object"!=typeof s||null===s||Array.isArray(s)||"object"!=typeof i[e]||null===i[e]||Array.isArray(i[e])?i[e]=y(s):i[e]=m(i[e],s);return i}function y(e,t=new WeakSet){if(null===e||"object"!=typeof e)return e;if(t.has(e))return"[Circular]";if(e instanceof Date)return new Date(e);if(Array.isArray(e)){t.add(e);const i=e.map(e=>y(e,t));return t.delete(e),i}if("object"==typeof e){t.add(e);const i={};for(const[s,n]of Object.entries(e))i[s]=y(n,t);return t.delete(e),i}return e}function v(e){if(!e)return(new Date).toISOString();if(e instanceof Date)return e.toISOString();if("string"==typeof e){const t=new Date(e);return isNaN(t.getTime())?(new Date).toISOString():t.toISOString()}return"number"==typeof e?new Date(e).toISOString():(new Date).toISOString()}function w(){const e=globalThis.crypto;if(e?.randomUUID)return e.randomUUID();if(e?.getRandomValues){const t=e.getRandomValues(new Uint8Array(16));if(t){t[6]=15&t[6]|64,t[8]=63&t[8]|128;const e=Array.from(t,e=>e.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}var b=["_vuid","em","ph","cafe24_member_id_crypt","cafe24_member_id_plain"],S={_vuid:{namespace:"vircle",type:"vuid"},em:{namespace:"meta",type:"em"},ph:{namespace:"meta",type:"ph"},cafe24_member_id_crypt:{namespace:"cafe24",type:"member_id_crypt"},cafe24_member_id_plain:{namespace:"cafe24",type:"member_id_plain"}},E={fbclid:{namespace:"meta",type:"fbclid"},gclid:{namespace:"google",type:"gclid"},msclkid:{namespace:"microsoft",type:"msclkid"},ttclid:{namespace:"tiktok",type:"ttclid"},kclid:{namespace:"kakao",type:"kclid"},n_media:{namespace:"naver",type:"n_media"},n_query:{namespace:"naver",type:"n_query"},n_ad:{namespace:"naver",type:"n_ad"},n_ad_group:{namespace:"naver",type:"n_ad_group"},n_keyword:{namespace:"naver",type:"n_keyword"},n_keyword_id:{namespace:"naver",type:"n_keyword_id"},n_rank:{namespace:"naver",type:"n_rank"},n_campaign_type:{namespace:"naver",type:"n_campaign_type"}};function I(e){const t={...e},i=[...e.identifiers??[]];if(e.properties){const{stripped:s,extracted:n}=function(e){const t=[],i={...e};for(const e of b){const s=i[e];if(null==s){delete i[e];continue}const n=S[e];if(n){if(Array.isArray(s))for(const e of s)"string"==typeof e&&e.length>0&&t.push({namespace:n.namespace,type:n.type,value:e});else"string"==typeof s&&s.length>0?t.push({namespace:n.namespace,type:n.type,value:s}):"number"==typeof s&&t.push({namespace:n.namespace,type:n.type,value:String(s)});delete i[e]}}return{stripped:i,extracted:t}}(e.properties);t.properties=s,i.push(...n)}if(e.context){const{strippedContext:s,extracted:n}=function(e){const t=[],i={...e};if(i.meta){const e={...i.meta};for(const i of["fbp","fbc"]){const s=e[i];"string"==typeof s&&s.length>0&&t.push({namespace:"meta",type:i,value:s}),delete e[i]}0===Object.keys(e).length?delete i.meta:i.meta=e}if(i.campaign){const e={...i.campaign},s=e;for(const e of Object.keys(E)){const i=s[e];if("string"==typeof i&&i.length>0){const s=E[e];t.push({namespace:s.namespace,type:s.type,value:i})}delete s[e]}0===Object.keys(e).length?delete i.campaign:i.campaign=e}return{strippedContext:i,extracted:t}}(e.context);t.context=s,i.push(...n)}let s=!1,n=i;return i.length>50&&(n=i.slice(0,50),s=!0),n.length>0&&(t.identifiers=n),{event:t,truncated:s}}var x=new Set(["meta","google","microsoft","tiktok","kakao","naver"]);var A,C,R="v2",k="vircle_user",_="vircle_session",P={PUBLIC_KEY:(A="VIRCLE_RSA_PUBLIC_KEY",C="","undefined"!=typeof process&&process.env&&"object"==typeof process.env&&process.env[A]||C)},T={development:"https://dev-integration.vircle.co.kr/v1/track/events",production:"https://integration.vircle.co.kr/v1/track/events"},N={development:"https://dstatic.vircle.co.kr/sdk/v1/config",production:"https://static.vircle.co.kr/sdk/v1/config"},O=class{constructor(e,t={}){this.disposed=!1,this.config=e,this.options={autoEnrich:!0,enableValidation:!0,maxEventSize:102400,...t},this.contextService=t.contextService,this.pluginService=t.pluginService,this.storageService=t.storageService,this.transportService=t.transportService}async track(e){if(this.disposed)throw new c("SERVICE_DISPOSED","EventService has been disposed");const t=this.options.getConsent?.();if(!t||t.analytics)try{let t=await this.processEvent(e);this.pluginService&&(t=await this.pluginService.executeHook("beforeEventSend",t));const i=I(t);i.truncated&&console.warn(`[EventService] identifiers array truncated to 50 (event: ${t.name})`),t=i.event,t=this.applyConsentGating(t),this.transportService?(this.config.debug&&console.log("[EventService] Sending event to transport:",t.name),await this.transportService.send(t),this.config.debug&&console.log("[EventService] Event sent to transport successfully:",t.name)):this.config.debug&&console.warn("[EventService] No transport service available"),this.pluginService&&await this.pluginService.executeHook("afterEventSend",t)}catch(t){throw this.pluginService&&await this.pluginService.executeHook("onError",{error:t,context:{event:e}}),t}else this.config.debug&&console.log("[EventService] track() no-op — analytics consent absent:",e.name)}createEvent(e){return new D(this,e)}async processEvent(e){let t={...e};if(t.id||(t.id=this.options.cryptoAdapter?.generateUUID?.()??w()),t.schema_version||(t.schema_version=R),this.options.autoEnrich&&(t=await this.enrichEvent(t)),this.options.maxEventSize){const e=this.calculateEventSize(t);if(e>this.options.maxEventSize)throw new c("EVENT_TOO_LARGE",`Event size (${e} bytes) exceeds maximum allowed size (${this.options.maxEventSize} bytes)`)}return t}async enrichEvent(e){const t={...e};if(t.timestamp||(t.timestamp=(new Date).toISOString()),this.contextService)try{const e=await this.contextService.collectAutoContext();e.context&&(t.context=this.mergeContext(e.context,t.context||{}))}catch(e){const t=new Error(`Failed to collect auto context: ${e.message}`);this.options.onNonCriticalError&&this.options.onNonCriticalError(t)}return t}mergeContext(e,t){return{...e,...t}}applyConsentGating(e){const t=this.options.getConsent?.();if(!t||t.marketing)return e;const i={...e};if(i.identifiers&&i.identifiers.length>0){const e=i.identifiers.filter(e=>!x.has(e.namespace));i.identifiers=e.length>0?e:void 0}if(i.properties){const{em:e,ph:t,...s}=i.properties;i.properties=s}if(i.context){const e={...i.context};if(e.meta){const t={...e.meta};delete t.fbp,delete t.fbc,e.meta=t}if(e.campaign){const t={...e.campaign};delete t.fbclid,e.campaign=t}i.context=e}return i}calculateEventSize(e){try{return new Blob([JSON.stringify(e)]).size}catch{return 2*JSON.stringify(e).length}}dispose(){this.disposed||(this.disposed=!0,this.contextService=void 0,this.pluginService=void 0,this.storageService=void 0,this.transportService=void 0,this.config={},this.options={})}isDisposed(){return this.disposed}},D=class{constructor(e,t){this.event={},this.eventService=e,t&&(this.event.name=t)}name(e){return this.event.name=e,this}userId(e){return this.event.userId=e,this}sessionId(e){return this.event.sessionId=e,this}properties(e){return this.event.properties={...this.event.properties,...e},this}property(e,t){return this.event.properties||(this.event.properties={}),this.event.properties[e]=t,this}context(e){return this.event.context={...this.event.context,...e},this}device(e){return this.event.context||(this.event.context={}),this.event.context.device={...this.event.context.device,...e},this}app(e){return this.event.context||(this.event.context={}),this.event.context.app={...this.event.context.app,...e},this}page(e){return this.event.context||(this.event.context={}),this.event.context.page={...this.event.context.page,...e},this}campaign(e){return this.event.context||(this.event.context={}),this.event.context.campaign={...this.event.context.campaign,...e},this}custom(e,t){return this.event.context||(this.event.context={}),this.event.context.custom||(this.event.context.custom={}),this.event.context.custom[e]=t,this}track(){const e=this.build();return this.eventService.track(e)}build(){if(!this.event.name)throw new c("VALIDATION_ERROR","Event name is required");return{name:this.event.name,timestamp:this.event.timestamp,userId:this.event.userId,sessionId:this.event.sessionId,properties:this.event.properties||{},context:this.event.context||{}}}},V=class{constructor(e){this.config={...e}}getConfig(){return{...this.config}}updateConfig(e){this.config={...this.config,...e}}get(e){return this.config[e]}set(e,t){this.config[e]=t}},L=class{constructor(e){this.config=e}async collectAutoContext(){const e={},t=[],i=[],s=this.config.autoCollect||{};try{if(s.device){const s=await this.collectDeviceInfo();s.device&&(e.device=s.device),t.push(...s.warnings||[]),i.push(...s.errors||[])}if(s.app){const s=await this.collectAppInfo();s.app&&(e.app=s.app),t.push(...s.warnings||[]),i.push(...s.errors||[])}if(s.page&&this.isWebEnvironment()){const i=this.collectPageInfo();i.page&&(e.page=i.page),t.push(...i.warnings||[])}if(s.userAgent){const t=this.collectUserAgent();t.userAgent&&(e.userAgent=t.userAgent)}if(s.referrer&&this.isWebEnvironment()){const t=this.collectReferrer();t.referrer&&(e.referrer=t.referrer)}if(s.campaign){const t=this.collectCampaignInfo();t.campaign&&(e.campaign=t.campaign)}if(s.performance&&this.isWebEnvironment()){const i=this.collectPerformanceInfo();i.performance&&(e.performance=i.performance),t.push(...i.warnings||[])}}catch(e){i.push(`Failed to collect auto context: ${e.message}`)}return{context:e,warnings:t,errors:i}}async collectDeviceInfo(){if(this.cachedDeviceInfo)return{device:this.cachedDeviceInfo};const e=[],t=[],i={};try{if(this.isReactNativeEnvironment()){e.push("Limited device info available in React Native - use platform-specific adapter for full info"),i.type="mobile";try{"undefined"!=typeof Intl&&Intl&&Intl.DateTimeFormat&&(i.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone)}catch(e){i.timezone="UTC"}return this.cachedDeviceInfo=i,{device:this.cachedDeviceInfo,warnings:e}}if(this.isWebEnvironment()&&"undefined"!=typeof navigator){const t=navigator.userAgent;if(t.includes("Chrome")){i.browser="Chrome";const e=t.match(/Chrome\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}else if(t.includes("Firefox")){i.browser="Firefox";const e=t.match(/Firefox\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}else if(t.includes("Safari")){i.browser="Safari";const e=t.match(/Version\/(\d+\.?\d*)/);e&&(i.browserVersion=e[1])}if(t.includes("Windows")){i.os="Windows";const e=t.match(/Windows NT (\d+\.?\d*)/);e&&(i.osVersion=e[1])}else if(t.includes("Mac OS")){i.os="macOS";const e=t.match(/Mac OS X (\d+_?\d*)/);e&&(i.osVersion=e[1].replace("_","."))}else t.includes("Linux")&&(i.os="Linux");this.isMobileEnvironment()?i.type="mobile":t.includes("Tablet")||t.includes("iPad")?i.type="tablet":i.type="desktop";try{"language"in navigator&&"string"==typeof navigator.language&&navigator.language.length>0&&(i.language=navigator.language)}catch(e){}"undefined"!=typeof screen?i.screenResolution=`${screen.width}x${screen.height}`:"undefined"!=typeof window&&window.screen&&(i.screenResolution=`${window.screen.width}x${window.screen.height}`),"undefined"!=typeof window&&window.innerWidth&&window.innerHeight&&(i.viewport={width:window.innerWidth,height:window.innerHeight});try{i.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(t){e.push("Failed to detect timezone")}}else e.push("Navigator API not available - limited device info");return this.cachedDeviceInfo=i,{device:this.cachedDeviceInfo,warnings:e,errors:t}}catch(i){return t.push(`Failed to collect device info: ${i.message}`),{warnings:e,errors:t}}}async collectAppInfo(){if(this.cachedAppInfo)return{app:this.cachedAppInfo};const e=[],t=[],i={};try{if(this.isWebEnvironment()&&"undefined"!=typeof document&&(i.name=document.title||"Unknown Web App"),"undefined"!=typeof process&&process.env){i.version=process.env.npm_package_version||process.env.APP_VERSION,i.build=process.env.BUILD_NUMBER;const e=process.env.NODE_ENV;"development"!==e&&"production"!==e||(i.environment=e)}return this.cachedAppInfo=i,{app:this.cachedAppInfo,warnings:e,errors:t}}catch(i){return t.push(`Failed to collect app info: ${i.message}`),{warnings:e,errors:t}}}collectPageInfo(){if(!this.isWebEnvironment()||"undefined"==typeof document)return{warnings:["Page info collection only available in web environment"]};const e={},t=[];try{e.title=document.title,e.url=window.location.href,e.path=window.location.pathname,e.search=window.location.search,e.hash=window.location.hash,e.referrer=document.referrer;const i={};return document.querySelectorAll("meta[name], meta[property]").forEach(e=>{const t=e.getAttribute("name")||e.getAttribute("property"),s=e.getAttribute("content");t&&s&&(i[t]=s)}),Object.keys(i).length>0&&(e.meta=i),{page:e,warnings:t}}catch(e){return t.push(`Failed to collect page info: ${e.message}`),{warnings:t}}}collectUserAgent(){return"undefined"!=typeof navigator&&navigator.userAgent?{userAgent:navigator.userAgent}:{}}collectReferrer(){return this.isWebEnvironment()&&"undefined"!=typeof document&&document.referrer?{referrer:document.referrer}:{}}collectCampaignInfo(){if(!this.isWebEnvironment()||"undefined"==typeof window)return{};const e={},t=new URLSearchParams(window.location.search);let i=!1;["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(s=>{const n=t.get(s);n&&(e[s]=n,i=!0)});return["gclid","fbclid","msclkid","ttclid"].forEach(s=>{const n=t.get(s);n&&(e[s]=n,i=!0)}),i?{campaign:e}:{}}collectPerformanceInfo(){if(!this.isWebEnvironment()||"undefined"==typeof window||!window.performance)return{warnings:["Performance API not available"]};const e={},t=[];try{const i=window.performance.timing,s=window.performance.navigation;if(i&&(e.loadTime=i.loadEventEnd-i.navigationStart,e.domReadyTime=i.domContentLoadedEventEnd-i.navigationStart,e.responseTime=i.responseEnd-i.requestStart,e.renderTime=i.loadEventEnd-i.responseEnd),s&&(e.navigationType=s.type,e.redirectCount=s.redirectCount),"connection"in navigator){const t=navigator.connection;e.connectionType=t.effectiveType,e.downlink=t.downlink,e.rtt=t.rtt}return{performance:e,warnings:t}}catch(e){return t.push(`Failed to collect performance info: ${e.message}`),{warnings:t}}}mergeContext(e,t={}){return{...e,...t,device:{...e.device,...t.device},app:{...e.app,...t.app},page:{...e.page,...t.page},campaign:{...e.campaign,...t.campaign},performance:{...e.performance,...t.performance}}}clearCache(){this.cachedAppInfo=void 0}isReactNativeEnvironment(){return"undefined"!=typeof navigator&&"ReactNative"===navigator.product}isWebEnvironment(){return"undefined"!=typeof window&&"undefined"!=typeof document&&!this.isReactNativeEnvironment()}isMobileEnvironment(){return!!this.isReactNativeEnvironment()||!(!this.isWebEnvironment()||"undefined"==typeof navigator)&&(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||"undefined"!=typeof window&&window.innerWidth<=768)}},$=class{constructor(e,t={}){this.plugins=new Map,this.eventHandlers=new Map,this.pluginEventHandlers=new Map,this.pluginStorage=new Map,this.config=e,this.options={maxExecutionTime:5e3,enableTimeout:!0,errorHandling:"lenient",...t}}setTrackFn(e){this.trackFn=e}setIdentifyFn(e){this.identifyFn=e}setResetFn(e){this.resetFn=e}setSetAnonymousIdFn(e){this.setAnonymousIdFn=e}setGetConsentFn(e){this.getConsentFn=e}setGetRemoteConfigFn(e){this.getRemoteConfigFn=e}setGetAnonymousIdFn(e){this.getAnonymousIdFn=e}setGetCookieDomainFn(e){this.getCookieDomainFn=e}async register(e){if(this.validatePlugin(e),this.plugins.has(e.name))throw new d(e.name,`Plugin '${e.name}' is already registered`,"PLUGIN_ALREADY_REGISTERED");try{const t=this.createPluginContext(e.name);e.initialize&&await this.executeWithTimeout(()=>e.initialize(this.config,t),`Plugin '${e.name}' initialization`),this.plugins.set(e.name,e)}catch(t){throw new d(e.name,`Failed to register plugin: ${t.message}`,"PLUGIN_INITIALIZATION_FAILED",{cause:t})}}async unregister(e){const t=this.plugins.get(e);if(!t)return!1;let i;try{t.cleanup&&await this.executeWithTimeout(()=>t.cleanup(),`Plugin '${e}' cleanup`)}catch(e){i=e}finally{this.plugins.delete(e),this.pluginStorage.delete(e),this.removePluginEventHandlers(e)}if(i)throw new c("PLUGIN_ERROR",`Plugin cleanup failed for '${e}': ${i.message}`,{cause:i});return!0}async executeHook(e,t){const i=[],s=[],n=Array.from(this.plugins.values()).filter(t=>t.hooks&&t.hooks[e]);if(0===n.length)return t;for(const r of n)try{const s=this.createPluginContext(r.name),n=r.hooks[e],o=await this.executeWithTimeout(()=>n(t,s),`Plugin '${r.name}' ${e} hook`);i.push(o),"beforeEventSend"!==e&&"afterEventSend"!==e||(t=o||t)}catch(t){const i=new d(r.name,`Hook '${e}' failed: ${t.message}`,"PLUGIN_HOOK_FAILED",{cause:t});if(s.push(i),"strict"===this.options.errorHandling)throw i}return s.length>0&&"lenient"===this.options.errorHandling?{results:i,errors:s,data:"beforeEventSend"===e||"afterEventSend"===e?t:void 0}:"beforeEventSend"===e||"afterEventSend"===e?t:i}getPlugin(e){return this.plugins.get(e)}getPlugins(){return Array.from(this.plugins.values())}getPluginNames(){return Array.from(this.plugins.keys())}hasPlugin(e){return this.plugins.has(e)}getPluginCount(){return this.plugins.size}async executeLifecycle(e,t){const i=this.getLifecycleHook(e);i&&await this.executeHook(i,t)}async cleanup(){const e=Array.from(this.plugins.keys()).map(e=>this.unregister(e));await Promise.all(e)}getPluginHealth(){const e={};for(const[t,i]of this.plugins)try{i.name&&i.version?e[t]={status:"healthy"}:e[t]={status:"error",error:"Missing required plugin properties"}}catch(i){e[t]={status:"error",error:i.message}}return e}validatePlugin(e){if(!e.name)throw new d("","Plugin must have a name","PLUGIN_VALIDATION_FAILED");if(!e.version)throw new d(e.name,"Plugin must have a version","PLUGIN_VALIDATION_FAILED");if(!/^[a-zA-Z0-9_-]+$/.test(e.name))throw new d(e.name,"Plugin name must contain only letters, numbers, underscores, and hyphens","PLUGIN_VALIDATION_FAILED");if(!/^\d+\.\d+\.\d+/.test(e.version))throw new d(e.name,"Plugin version must be in semver format (x.y.z)","PLUGIN_VALIDATION_FAILED");if(e.hooks){const t=["beforeEvent","afterEvent","beforeBatch","afterBatch","onError","beforeStart","afterStart","beforeStop","afterStop","beforeEventSend","afterEventSend","onConfigChange","onUserIdentify","onSessionStart","onSessionEnd"];for(const i of Object.keys(e.hooks)){if(!t.includes(i))throw new d(e.name,`Invalid plugin hook: ${i}`,"PLUGIN_VALIDATION_FAILED");if("function"!=typeof e.hooks[i])throw new d(e.name,`Plugin hook '${i}' must be a function`,"PLUGIN_VALIDATION_FAILED")}}}createPluginContext(e){const t=this;return{getConfig:()=>({...this.config}),on:(t,i)=>{this.eventHandlers.has(t)||this.eventHandlers.set(t,new Set),this.eventHandlers.get(t).add(i),this.pluginEventHandlers.has(e)||this.pluginEventHandlers.set(e,[]),this.pluginEventHandlers.get(e).push({event:t,handler:i})},off:(t,i)=>{const s=this.eventHandlers.get(t);s&&s.delete(i);const n=this.pluginEventHandlers.get(e);if(n){const e=n.findIndex(e=>e.event===t&&e.handler===i);-1!==e&&n.splice(e,1)}},emit:(e,t)=>{const i=this.eventHandlers.get(e);i&&i.forEach(i=>{try{i(t)}catch(t){this.config.debug&&console.error(`Error in event handler for '${e}':`,t)}})},use:e=>{this.config.debug&&console.warn("Middleware registration is not yet implemented")},getPlugin:e=>t.plugins.get(e),track:(i,s)=>{t.trackFn?t.trackFn(i,s).catch(t=>{console.error(`[Plugin:${e}] track() failed:`,t)}):this.config.debug&&console.warn(`[Plugin:${e}] track() called but SDK track function not injected`)},identify:(i,s)=>{t.identifyFn?t.identifyFn(i,s).catch(t=>{console.error(`[Plugin:${e}] identify() failed:`,t)}):this.config.debug&&console.warn(`[Plugin:${e}] identify() called but SDK identify function not injected`)},reset:async()=>{t.resetFn?await t.resetFn():this.config.debug&&console.warn(`[Plugin:${e}] reset() called but SDK reset function not injected`)},setAnonymousId:i=>{t.setAnonymousIdFn?t.setAnonymousIdFn(i):this.config.debug&&console.warn(`[Plugin:${e}] setAnonymousId() called but SDK function not injected`)},getConsent:()=>t.getConsentFn?.(),getRemoteConfig:()=>t.getRemoteConfigFn?t.getRemoteConfigFn():Promise.resolve(void 0),getAnonymousId:()=>t.getAnonymousIdFn?.(),getCookieDomain:()=>t.getCookieDomainFn?.(),logger:{debug:(t,...i)=>{this.config.debug&&console.debug(`[Plugin:${e}] ${t}`,...i)},info:(t,...i)=>{this.config.debug&&console.info(`[Plugin:${e}] ${t}`,...i)},warn:(t,...i)=>{this.config.debug&&console.warn(`[Plugin:${e}] ${t}`,...i)},error:(t,...i)=>{this.config.debug&&console.error(`[Plugin:${e}] ${t}`,...i)}},storage:{get:async i=>{if(t.pluginStorage.has(e))return t.pluginStorage.get(e).get(i)},set:async(i,s)=>{t.pluginStorage.has(e)||t.pluginStorage.set(e,new Map),t.pluginStorage.get(e).set(i,s)},remove:async i=>{const s=t.pluginStorage.get(e);s&&s.delete(i)}}}}async executeWithTimeout(e,t){return this.options.enableTimeout?new Promise((i,s)=>{const n=setTimeout(()=>{s(new Error(`${t} timed out after ${this.options.maxExecutionTime}ms`))},this.options.maxExecutionTime);Promise.resolve(e()).then(e=>{clearTimeout(n),i(e)}).catch(e=>{clearTimeout(n),s(e)})}):await e()}removePluginEventHandlers(e){const t=this.pluginEventHandlers.get(e);if(t){for(const{event:e,handler:i}of t){const t=this.eventHandlers.get(e);t&&t.delete(i)}this.pluginEventHandlers.delete(e)}}getLifecycleHook(e){return{"config-changed":"onConfigChange","user-identified":"onUserIdentify","session-started":"onSessionStart","session-ended":"onSessionEnd"}[e]}},F=class{constructor(e=1e3){this.store=new Map,this.maxSize=e}async get(e){const t=this.store.get(e);return t?t.ttl&&Date.now()>t.timestamp+1e3*t.ttl?(this.store.delete(e),null):t.value:null}async set(e,t,i){if(this.store.size>=this.maxSize&&!this.store.has(e)){const e=this.store.keys().next().value;e&&this.store.delete(e)}this.store.set(e,{value:t,timestamp:Date.now(),ttl:i})}async remove(e){return this.store.delete(e)}async clear(){this.store.clear()}async keys(){return Array.from(this.store.keys())}async size(){return this.store.size}},U=class{constructor(e="vircle_"){if(this.prefix=e,"undefined"==typeof localStorage)throw new p("localStorage is not available","STORAGE_NOT_AVAILABLE")}async get(e){try{const t=localStorage.getItem(this.prefix+e);if(!t)return null;const i=JSON.parse(t);return i.ttl&&Date.now()>i.timestamp+1e3*i.ttl?(await this.remove(e),null):i.value}catch(t){throw new p(`Failed to get item '${e}': ${t.message}`)}}async set(e,t,i){try{const s={value:t,timestamp:Date.now(),ttl:i};localStorage.setItem(this.prefix+e,JSON.stringify(s))}catch(t){if("QuotaExceededError"===t.name)throw new p("Storage quota exceeded","STORAGE_QUOTA_EXCEEDED");throw new p(`Failed to set item '${e}': ${t.message}`)}}async remove(e){try{const t=this.prefix+e,i=null!==localStorage.getItem(t);return localStorage.removeItem(t),i}catch(t){throw new p(`Failed to remove item '${e}': ${t.message}`)}}async clear(){try{const e=Object.keys(localStorage).filter(e=>e.startsWith(this.prefix));e.forEach(e=>localStorage.removeItem(e))}catch(e){throw new p(`Failed to clear storage: ${e.message}`)}}async keys(){try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).map(e=>e.substring(this.prefix.length))}catch(e){throw new p(`Failed to get keys: ${e.message}`)}}async size(){try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).length}catch(e){throw new p(`Failed to get size: ${e.message}`)}}},B=class{constructor(e="vircle_db"){if(this.dbVersion=1,this.storeName="vircle_store",this.db=null,this.dbName=e,"undefined"==typeof indexedDB)throw new p("IndexedDB is not available","STORAGE_NOT_AVAILABLE")}async initDB(){return this.db?this.db:new Promise((e,t)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{t(new p("Failed to open IndexedDB","STORAGE_ERROR"))},i.onsuccess=()=>{this.db=i.result,e(this.db)},i.onupgradeneeded=()=>{const e=i.result;e.objectStoreNames.contains(this.storeName)||e.createObjectStore(this.storeName,{keyPath:"key"})}})}async get(e){try{const t=await this.initDB(),i=t.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((t,s)=>{const n=i.get(e);n.onerror=()=>{s(new p(`Failed to get item '${e}'`,"STORAGE_ERROR"))},n.onsuccess=()=>{const i=n.result;if(!i)return void t(null);const s=i.data;if(s.ttl&&Date.now()>s.timestamp+1e3*s.ttl)return this.remove(e),void t(null);t(s.value)}})}catch(t){throw new p(`Failed to get item '${e}': ${t.message}`)}}async set(e,t,i){try{const s=await this.initDB(),n=s.transaction([this.storeName],"readwrite").objectStore(this.storeName),r={value:t,timestamp:Date.now(),ttl:i};return new Promise((t,i)=>{const s=n.put({key:e,data:r});s.onerror=()=>{i(new p(`Failed to set item '${e}'`,"STORAGE_ERROR"))},s.onsuccess=()=>{t()}})}catch(t){throw new p(`Failed to set item '${e}': ${t.message}`)}}async remove(e){try{const t=await this.initDB(),i=t.transaction([this.storeName],"readwrite").objectStore(this.storeName);return new Promise((t,s)=>{const n=i.get(e);n.onsuccess=()=>{const r=void 0!==n.result,o=i.delete(e);o.onerror=()=>{s(new p(`Failed to remove item '${e}'`,"STORAGE_ERROR"))},o.onsuccess=()=>{t(r)}},n.onerror=()=>{s(new p(`Failed to check item '${e}'`,"STORAGE_ERROR"))}})}catch(t){throw new p(`Failed to remove item '${e}': ${t.message}`)}}async clear(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readwrite").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.clear();s.onerror=()=>{i(new p("Failed to clear storage","STORAGE_ERROR"))},s.onsuccess=()=>{e()}})}catch(e){throw new p(`Failed to clear storage: ${e.message}`)}}async keys(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.getAllKeys();s.onerror=()=>{i(new p("Failed to get keys","STORAGE_ERROR"))},s.onsuccess=()=>{e(s.result)}})}catch(e){throw new p(`Failed to get keys: ${e.message}`)}}async size(){try{const e=await this.initDB(),t=e.transaction([this.storeName],"readonly").objectStore(this.storeName);return new Promise((e,i)=>{const s=t.count();s.onerror=()=>{i(new p("Failed to get size","STORAGE_ERROR"))},s.onsuccess=()=>{e(s.result)}})}catch(e){throw new p(`Failed to get size: ${e.message}`)}}},H=class{constructor(e={}){this.options={type:"memory",maxSize:10485760,keyPrefix:"vircle_",...e},this.adapter=e.adapter||this.createAdapter()}async get(e){try{return await this.adapter.get(e)}catch(t){throw new p(`Failed to get '${e}': ${t.message}`)}}async set(e,t,i){try{const s=i??this.options.ttl;await this.adapter.set(e,t,s)}catch(t){throw new p(`Failed to set '${e}': ${t.message}`)}}async remove(e){try{return await this.adapter.remove(e)}catch(t){throw new p(`Failed to remove '${e}': ${t.message}`)}}async clear(){try{await this.adapter.clear()}catch(e){throw new p(`Failed to clear storage: ${e.message}`)}}async keys(){try{return await this.adapter.keys()}catch(e){throw new p(`Failed to get keys: ${e.message}`)}}async size(){try{return await this.adapter.size()}catch(e){throw new p(`Failed to get size: ${e.message}`)}}async has(e){try{return null!==await this.adapter.get(e)}catch(t){throw new p(`Failed to check key '${e}': ${t.message}`)}}async getMultiple(e){const t={};return await Promise.all(e.map(async e=>{try{t[e]=await this.adapter.get(e)}catch(i){t[e]=null}})),t}async setMultiple(e,t){await Promise.all(Object.entries(e).map(([e,i])=>this.adapter.set(e,i,t??this.options.ttl)))}createAdapter(){switch(this.options.type){case"localStorage":return new U(this.options.keyPrefix);case"indexedDB":return new B(`${this.options.keyPrefix}db`);default:return new F(this.options.maxSize||1e3)}}static async testStorageAvailability(e){try{switch(e){case"localStorage":return"undefined"!=typeof localStorage&&(localStorage.setItem("vircle_test","test"),localStorage.removeItem("vircle_test"),!0);case"indexedDB":return"undefined"!=typeof indexedDB;case"memory":return!0;default:return!1}}catch{return!1}}static getRecommendedStorageType(){return"undefined"!=typeof window?"undefined"!=typeof indexedDB?"indexedDB":"undefined"!=typeof localStorage?"localStorage":"memory":"memory"}};function z(e){if(!e)return"***";const t=e.length;return t<8?"***":t<=16?`${e.substring(0,2)}...${e.substring(t-2)}`:`${e.substring(0,4)}...${e.substring(t-4)}`}function q(e){if(!e||"object"!=typeof e)return e;const t={...e};if("apiKey"in t&&(t.apiKey=z(t.apiKey)),t.headers){const e={...t.headers};Object.keys(e).forEach(t=>{if("authorization"===t.toLowerCase()){const i=e[t];"string"==typeof i&&(i.startsWith("Bearer ")?e[t]=`Bearer ${z(i.substring(7))}`:e[t]=z(i))}}),t.headers=e}return Object.keys(t).forEach(e=>{"object"==typeof t[e]&&null!==t[e]&&(t[e]=q(t[e]))}),t}var j=class{constructor(e){this.items=[],this.maxSize=e}enqueue(e,t=0){const i={data:e,priority:t,timestamp:Date.now()},s=this.findInsertIndex(t);this.items.splice(s,0,i),this.maxSize&&this.items.length>this.maxSize&&this.items.pop()}dequeue(){const e=this.items.shift();return e?.data}extractByPriority(e){const t=[],i=[];for(const s of this.items)s.priority>=e?t.push(s.data):i.push(s);return this.items=i,t}extractBatch(e){const t=[];for(let i=0;i<e&&this.items.length>0;i++){const e=this.items.shift();e&&t.push(e.data)}return t}extractOldItems(e){const t=Date.now(),i=[],s=[];for(const n of this.items)t-n.timestamp>e?i.push(n.data):s.push(n);return this.items=s,i}peek(){return this.items[0]?.data}size(){return this.items.length}isEmpty(){return 0===this.items.length}clear(){this.items=[]}getStatsByPriority(){const e=new Map;for(const t of this.items){const i=e.get(t.priority)||0;e.set(t.priority,i+1)}return e}findInsertIndex(e){let t=0,i=this.items.length;for(;t<i;){const s=Math.floor((t+i)/2);this.items[s].priority>=e?t=s+1:i=s}return t}},K={purchase:100,payment:100,error:100,crash:100,identify:75,signup:75,login:75,logout:75,click:75,submit:75,page_view:50,screen_view:50,scroll:50,heartbeat:25,session_extend:25,background_sync:0,cache_update:0};function M(e,t){const i=K[e.toLowerCase()];return void 0!==i?i:e.includes("error")||e.includes("fail")?100:e.includes("click")||e.includes("tap")?75:(e.includes("view")||e.includes("load"),50)}var G,W=class{constructor(e={}){this.state="CLOSED",this.failures=0,this.successes=0,this.lastFailureTime=0,this.halfOpenRetries=0,this.requestVolume=[],this.options={failureThreshold:5,resetTimeout:6e4,halfOpenRetries:3,volumeThreshold:10,errorThresholdPercentage:50,onStateChange:()=>{},...e}}async execute(e){if(this.isOpen())throw new Error(`Circuit breaker is OPEN. Next retry at ${new Date(this.getNextRetryTime()).toISOString()}`);try{const t=await e();return this.onSuccess(),t}catch(e){throw this.onFailure(),e}}isOpen(){return"OPEN"===this.state&&(!(Date.now()>=this.getNextRetryTime())||(this.transitionTo("HALF_OPEN"),!1))}onSuccess(){switch(this.recordRequest(!0),this.successes++,this.state){case"CLOSED":this.failures=0;break;case"HALF_OPEN":this.successes>=this.options.halfOpenRetries&&this.transitionTo("CLOSED")}}onFailure(){switch(this.recordRequest(!1),this.lastFailureTime=Date.now(),this.state){case"CLOSED":this.failures++,this.shouldOpen()&&this.transitionTo("OPEN");break;case"HALF_OPEN":this.transitionTo("OPEN")}}transitionTo(e){const t=this.state;switch(this.state=e,e){case"CLOSED":this.failures=0,this.successes=0;break;case"OPEN":this.halfOpenRetries=0;break;case"HALF_OPEN":this.successes=0,this.failures=0}t!==e&&this.options.onStateChange(e)}shouldOpen(){if(this.failures>=this.options.failureThreshold)return!0;const e=this.getRecentRequests();if(e.length>=this.options.volumeThreshold){return this.calculateErrorRate(e)>=this.options.errorThresholdPercentage}return!1}recordRequest(e){const t=Date.now();this.requestVolume.push({timestamp:t,success:e});const i=t-3e5;this.requestVolume=this.requestVolume.filter(e=>e.timestamp>i)}getRecentRequests(){const e=Date.now()-6e4;return this.requestVolume.filter(t=>t.timestamp>e)}calculateErrorRate(e){if(0===e.length)return 0;return e.filter(e=>!e.success).length/e.length*100}getNextRetryTime(){return this.lastFailureTime+this.options.resetTimeout}getStats(){const e=this.getRecentRequests(),t=this.calculateErrorRate(e);return{state:this.state,failures:this.failures,successes:this.successes,lastFailureTime:this.lastFailureTime||void 0,nextRetryTime:"OPEN"===this.state?this.getNextRetryTime():void 0,errorRate:t}}reset(){this.transitionTo("CLOSED"),this.failures=0,this.successes=0,this.lastFailureTime=0,this.halfOpenRetries=0,this.requestVolume=[]}trip(){this.transitionTo("OPEN"),this.lastFailureTime=Date.now()}};function Q(e,t=1e3,i=3e4){const s=Math.min(t*Math.pow(2,e-1),i),n=.2*s*(2*Math.random()-1);return Math.round(s+n)}if("undefined"==typeof window&&"undefined"!=typeof global)try{G=e("crypto")}catch(e){}var J=class{static safeBase64Encode(e){if("undefined"!=typeof Buffer){return(e instanceof ArrayBuffer?Buffer.from(e):Buffer.from(e.buffer,e.byteOffset,e.byteLength)).toString("base64")}{const t=e instanceof ArrayBuffer?new Uint8Array(e):e,i=[],s=32768;for(let e=0;e<t.length;e+=s){const n=t.subarray(e,e+s);i.push(String.fromCharCode.apply(null,Array.from(n)))}return btoa(i.join(""))}}static safeBase64Decode(e){if("undefined"!=typeof Buffer)return new Uint8Array(Buffer.from(e,"base64"));{const t=atob(e),i=new Uint8Array(t.length);for(let e=0;e<t.length;e++)i[e]=t.charCodeAt(e);return i}}static async encrypt(e,t){try{if("undefined"!=typeof window&&window.crypto?.subtle)return this.encryptWebCrypto(e,t);if("undefined"!=typeof global&&global.crypto)return this.encryptNodeCrypto(e,t);throw new Error("No crypto implementation available")}catch(e){throw new c("ENCRYPTION_ERROR","Failed to encrypt data",{cause:e})}}static async encryptWebCrypto(e,t){const i=(new TextEncoder).encode(e),s=this.safeBase64Decode(t),n=await crypto.subtle.importKey("raw",s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength),{name:this.ALGORITHM,length:this.KEY_LENGTH},!1,["encrypt"]),r=crypto.getRandomValues(new Uint8Array(this.IV_LENGTH)),o=await crypto.subtle.encrypt({name:this.ALGORITHM,iv:r},n,i),a=new Uint8Array(r.length+o.byteLength);return a.set(r,0),a.set(new Uint8Array(o),r.length),this.safeBase64Encode(a)}static async encryptNodeCrypto(e,t){const i=G,s=Buffer.from(t,"base64"),n=i.randomBytes(this.IV_LENGTH),r=i.createCipheriv("aes-256-gcm",s,n);let o=r.update(e,"utf8");o=Buffer.concat([o,r.final()]);const a=r.getAuthTag();return Buffer.concat([n,o,a]).toString("base64")}static async generateAESKey(){if("undefined"!=typeof window&&window.crypto?.subtle)return crypto.subtle.generateKey({name:this.ALGORITHM,length:this.KEY_LENGTH},!0,["encrypt","decrypt"]);if(G)return G.randomBytes(32);throw new Error("No crypto implementation available")}static async encryptAESKey(e,t){if("undefined"!=typeof window&&window.crypto?.subtle){const i=this.safeBase64Decode(t),s=await crypto.subtle.importKey("spki",i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength),{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"]),n=await crypto.subtle.exportKey("raw",e),r=await crypto.subtle.encrypt({name:"RSA-OAEP"},s,n);return this.safeBase64Encode(new Uint8Array(r))}if(G){const i=G.createPublicKey({key:Buffer.from(t,"base64"),format:"der",type:"spki"});return G.publicEncrypt({key:i,oaepHash:"sha256",padding:G.constants.RSA_PKCS1_OAEP_PADDING},e).toString("base64")}throw new Error("No crypto implementation available")}static async encryptPayload(e,t){try{const i=JSON.stringify(e),s=await this.generateAESKey();let n,r,o;if("undefined"!=typeof window&&window.crypto?.subtle){const e=(new TextEncoder).encode(i),t=crypto.getRandomValues(new Uint8Array(this.IV_LENGTH)),a=await crypto.subtle.encrypt({name:this.ALGORITHM,iv:t},s,e),c=16,l=a.byteLength-c,u=a.slice(0,l),h=a.slice(l);n=this.safeBase64Encode(new Uint8Array(u)),o=this.safeBase64Encode(new Uint8Array(h)),r=this.safeBase64Encode(t)}else{if(!G)throw new Error("No crypto implementation available");{const e=G.randomBytes(this.IV_LENGTH),t=G.createCipheriv("aes-256-gcm",s,e);let a=t.update(i,"utf8");a=Buffer.concat([a,t.final()]),o=t.getAuthTag(),n=Buffer.concat([a,o]).toString("base64"),r=e.toString("base64")}}return{data:n,key:await this.encryptAESKey(s,t),iv:r,authTag:o,metadata:{algorithm:this.ALGORITHM,keyAlgorithm:"RSA-OAEP",timestamp:(new Date).toISOString()}}}catch(e){throw new c("ENCRYPTION_ERROR","Failed to encrypt payload",{cause:e})}}};J.ALGORITHM="AES-GCM",J.KEY_LENGTH=256,J.IV_LENGTH=12,J.TAG_LENGTH=16;var Y=class{constructor(e,t={}){this.eventQueue=new j,this.requestQueue=[],this.isProcessingQueue=!1,this.isFlushingQueue=!1,this.disposed=!1,this.config=e,this.options={timeout:3e4,retryAttempts:3,retryDelay:1e3,batchSize:50,enableBatching:!0,enableCompression:!1,...t},this.cryptoAdapter=t.cryptoAdapter,this.circuitBreaker=new W({failureThreshold:5,resetTimeout:6e4,errorThresholdPercentage:50,onStateChange:e=>{this.config.debug&&console.warn(`[TransportService] Circuit breaker state changed to: ${e}`)}}),this.setupAutoFlush()}setupAutoFlush(){this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(async()=>{try{await this.flushPriorityQueue()}catch(e){this.config.debug&&console.error("[TransportService] Auto-flush error:",e)}},this.config.batch?.flushInterval||1e4)}async send(e){if(this.disposed)throw new c("SERVICE_DISPOSED","TransportService has been disposed");this.config.debug&&console.log("[TransportService] Received event:",e.name);const t=M(e.name);if(this.eventQueue.enqueue(e,t),this.config.debug&&console.log("[TransportService] Event enqueued with priority:",t,"Queue size:",this.eventQueue.size()),t>=100){return(await this.flushPriorityQueue()).results[0]||{success:!0}}if(this.eventQueue.size()>=(this.options.batchSize||50)){return(await this.flushPriorityQueue()).results[0]||{success:!0}}if(this.config.debug||"development"===this.config.environment){this.config.debug&&console.log("[TransportService] Debug mode: flushing immediately");return(await this.flushPriorityQueue()).results[0]||{success:!0}}return this.scheduleNextTickFlush(),{success:!0}}scheduleNextTickFlush(){this.pendingFlushTimer||(this.pendingFlushTimer=setTimeout(()=>{this.pendingFlushTimer=void 0,this.flushPriorityQueue().catch(()=>{})},0))}async sendBatch(e){if(this.disposed)throw new c("SERVICE_DISPOSED","TransportService has been disposed");if(0===e.length)return{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};for(const t of e){const e=M(t.name);this.eventQueue.enqueue(t,e)}return this.flushPriorityQueue()}async flushPriorityQueue(){if(this.isFlushingQueue)return this.config.debug&&console.log("[TransportService] Already flushing queue, skipping..."),{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};if(this.eventQueue.isEmpty())return{totalEvents:0,successfulEvents:0,failedEvents:0,results:[]};this.isFlushingQueue=!0;try{const e=this.eventQueue.extractByPriority(100),t=this.eventQueue.extractByPriority(75),i=this.eventQueue.extractBatch(this.options.batchSize||50),s=[];let n=0,r=0;if(e.length>0){const t=await this.executeBatchRequest(e);s.push(...t.results),n+=t.successfulEvents,r+=t.failedEvents}if(t.length>0){const e=await this.executeBatchRequest(t);s.push(...e.results),n+=e.successfulEvents,r+=e.failedEvents}if(i.length>0){const e=await this.executeBatchRequest(i);s.push(...e.results),n+=e.successfulEvents,r+=e.failedEvents}return{totalEvents:s.length,successfulEvents:n,failedEvents:r,results:s}}finally{this.isFlushingQueue=!1}}async processQueue(){if(!this.isProcessingQueue&&0!==this.requestQueue.length){this.isProcessingQueue=!0;try{for(;this.requestQueue.length>0;){const e=[],t=[];let i=0;for(;this.requestQueue.length>0&&i<this.options.batchSize;){const s=this.requestQueue.shift(),n=this.options.batchSize-i;if(!(s.events.length<=n)){const r=s.events.slice(0,n),o=s.events.slice(n);e.push({events:r,resolve:s.resolve,reject:s.reject}),t.push(...r),i+=r.length,this.requestQueue.unshift({events:o,resolve:s.resolve,reject:s.reject});break}e.push(s),t.push(...s.events),i+=s.events.length}try{const i=await this.executeBatchRequest(t);let s=0;for(const t of e){const e=i.results.slice(s,s+t.events.length),n={totalEvents:t.events.length,successfulEvents:e.filter(e=>e.success).length,failedEvents:e.filter(e=>!e.success).length,results:e};t.resolve(n),s+=t.events.length}}catch(t){for(const i of e)i.reject(t)}}}finally{this.isProcessingQueue=!1}}}async executeBatchRequest(e){let t=null;this.config.debug&&console.log("[Vircle SDK] executeBatchRequest start - events :",e);try{return await this.circuitBreaker.execute(async()=>{for(let i=0;i<=this.options.retryAttempts;i++){try{const i=await this.makeHttpRequest(e);if(i.success)return{totalEvents:e.length,successfulEvents:e.length,failedEvents:0,results:e.map(()=>i)};if(!i.retryable)return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)};t=i.error||new Error("Unknown error")}catch(e){t=e,this.config.debug&&console.log(`[Vircle SDK] error : ${JSON.stringify(t)}`)}if(i<this.options.retryAttempts){const e=Q(i+1,this.options.retryDelay);this.config.debug&&console.log(`[Vircle SDK] Retry attempt ${i+1}/${this.options.retryAttempts} after ${e}ms delay`),await this.delay(e)}}const i={success:!1,error:t||new Error("Max retry attempts exceeded"),retryable:!1};return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)}})}catch(t){const i={success:!1,error:t,retryable:!1};return{totalEvents:e.length,successfulEvents:0,failedEvents:e.length,results:e.map(()=>i)}}}async makeHttpRequest(e){this.config.debug&&console.log("[makeHttpRequest] config:",this.config);const t=this.config.environment||"production",i=T[t],s=(new Date).toISOString();let n={payload:{events:e},timestamp:s};const r={"Content-Type":"application/json","User-Agent":"Vircle-SDK-TypeScript/1.0.0",...this.config.headers,...this.options.headers};if(this.config.apiKey&&(r.Authorization=`Bearer ${this.config.apiKey}`,r["X-Vircle-Timestamp"]=s),this.encryptionConfig?.enabled&&this.encryptionConfig.publicKey)try{let e;this.config.debug&&console.log("[makeHttpRequest] start encryption - config: ",this.encryptionConfig),this.cryptoAdapter&&"function"==typeof this.cryptoAdapter.encryptPayload?(this.config.debug&&(console.log("[makeHttpRequest] Using platform-specific crypto adapter:",this.cryptoAdapter.constructor.name),console.log("[makeHttpRequest] Payload to encrypt:",JSON.stringify(n.payload).substring(0,100)+"..."),console.log("[makeHttpRequest] Public key available:",!!this.encryptionConfig.publicKey),console.log("[makeHttpRequest] Public key length:",this.encryptionConfig.publicKey.length)),e=await this.cryptoAdapter.encryptPayload(n.payload,this.encryptionConfig.publicKey)):(this.config.debug&&console.log("[makeHttpRequest] Fall back to built-in EncryptionUtils"),e=await J.encryptPayload(n.payload,this.encryptionConfig.publicKey)),n={encrypted:!0,payload:e,timestamp:s};const t=await async function(e,t,i){if(i&&"function"==typeof i.createHmacSignature)return i.createHmacSignature(e,t);if("undefined"!=typeof crypto&&crypto.subtle){const i=new TextEncoder,s=i.encode(JSON.stringify(e)),n=await crypto.subtle.importKey("raw",i.encode(t),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),r=await crypto.subtle.sign("HMAC",n,s);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("")}throw new Error("No crypto implementation available for HMAC signature")}(n,this.config.apiKey,this.cryptoAdapter);this.config.debug&&console.debug("[makeHttpRequest] signature:",t),r["X-Vircle-Signature"]=t,r["X-Vircle-Encrypted"]="true",this.config.debug&&console.debug("[makeHttpRequest] headers:",r)}catch(e){const t=new h("Failed to encrypt payload. Aborting transmission for security.",void 0,{cause:e});return this.config.debug&&(console.error("[makeHttpRequest] Encryption failed:",e),console.error("[makeHttpRequest] Error type:",typeof e),console.error("[makeHttpRequest] Error name:",e instanceof Error?e.name:"Not an Error instance"),console.error("[makeHttpRequest] Error message:",e instanceof Error?e.message:String(e)),console.error("[makeHttpRequest] Error stack:",e instanceof Error?e.stack:"No stack trace"),console.error("[makeHttpRequest] Crypto adapter type:",this.cryptoAdapter?this.cryptoAdapter.constructor.name:"No adapter"),console.error("[makeHttpRequest] Public key preview:",this.encryptionConfig.publicKey.substring(0,50)+"...")),{success:!1,error:t,retryable:!1}}let o,a,c,l=!1;try{let e,t;"undefined"!=typeof AbortController&&(a=new AbortController,e=a.signal,c=setTimeout(()=>{a?.abort()},this.options.timeout));try{t=JSON.stringify(n)}catch(e){return this.config.debug&&console.log("[makeHttpRequest] Failed to stringify payload:",e),{success:!1,error:new h("Failed to serialize request payload",void 0,{cause:e,context:{errorName:e instanceof Error?e.name:"Unknown",isSerializationError:!0}}),retryable:!1}}const s={method:"POST",headers:r,body:t,signal:e};this.config.debug&&(console.log("[makeHttpRequest] fetch - url:",i),console.log("[makeHttpRequest] fetch - request:",s),console.log("[makeHttpRequest] fetch - starting request...")),o=setTimeout(()=>{!l&&this.config.debug&&(console.log("[makeHttpRequest] fetch - Promise still pending after 10 seconds"),console.log("[makeHttpRequest] fetch - Possible causes: ATS policy, network proxy, or fetch polyfill issue"))},1e4);const u=await this.fetch(i,s);let d;l=!0,o&&clearTimeout(o),c&&clearTimeout(c),this.config.debug&&(console.log("[makeHttpRequest] fetch - response received"),console.log("[makeHttpRequest] fetch - response status:",u.status),console.log("[makeHttpRequest] fetch - response ok:",u.ok));try{const e=u.text(),t=new Promise((e,t)=>{setTimeout(()=>t(new Error("Response body read timeout")),5e3)});d=await Promise.race([e,t])}catch(e){return this.config.debug&&console.log("[makeHttpRequest] Failed to read response body:",e),{success:u.ok,statusCode:u.status,responseBody:null,retryable:this.isRetryableHttpStatus(u.status)}}let p=null;try{p=JSON.parse(d)}catch{}if(u.ok)return{success:!0,statusCode:u.status,responseBody:p};{const e=new h(p?.message||`HTTP ${u.status}: ${u.statusText}`,u.status,{context:{responseBody:d}});return{success:!1,statusCode:u.status,responseBody:p,error:e,retryable:this.isRetryableHttpStatus(u.status)}}}catch(e){l=!0,o&&clearTimeout(o),c&&clearTimeout(c),this.config.debug&&(console.log("[makeHttpRequest] Request failed:",e),console.log("[makeHttpRequest] Error type:",typeof e),console.log("[makeHttpRequest] Error name:",e instanceof Error?e.name:"Unknown"),console.log("[makeHttpRequest] Error message:",e instanceof Error?e.message:String(e)),console.log("[makeHttpRequest] Error stack:",e instanceof Error?e.stack:"No stack"));const t=e instanceof Error?e.message:String(e),s=e instanceof Error&&"AbortError"===e.name,n=e instanceof Error&&"TypeError"===e.name,r=t.includes("Network request failed")||t.includes("Failed to fetch")||t.includes("Load failed");return{success:!1,error:new h(s?`Request timeout after ${this.options.timeout}ms`:`Network request failed: ${t}`,void 0,{cause:e,context:{errorName:e instanceof Error?e.name:"Unknown",isAbortError:s,isTypeError:n,isNetworkError:r,timeout:this.options.timeout,url:i,environment:"undefined"!=typeof window?"browser":"undefined"!=typeof global?"node/react-native":"unknown"}}),retryable:!s&&this.isRetryableError(e)}}}async fetch(e,t){if("undefined"!=typeof fetch)return this.config.debug&&console.log("[fetch] Using global fetch implementation"),fetch(e,t);if("undefined"!=typeof window&&window.fetch)return this.config.debug&&console.log("[fetch] Using window.fetch implementation"),window.fetch(e,t);if("undefined"!=typeof global)try{const i=await Promise.resolve().then(function(){return Pe}),s=i.default||i;return this.config.debug&&console.log("[fetch] Using node-fetch implementation"),s(e,t)}catch{}throw new h("No fetch implementation available",void 0,{context:{environment:"undefined"!=typeof window?"browser":"node",hasFetch:"undefined"!=typeof fetch,hasWindowFetch:"undefined"!=typeof window&&void 0!==window.fetch}})}isRetryableHttpStatus(e){return e>=500||408===e||429===e}isRetryableError(e){const t=e.message.toLowerCase();return["timeout","network","connection","econnreset","enotfound","econnrefused"].some(e=>t.includes(e))}delay(e){return new Promise(t=>setTimeout(t,e))}sendWithKeepalive(e){if("undefined"==typeof fetch)return!1;if(0===e.length)return!0;const t=this.config.environment||"production",i=T[t],s=(new Date).toISOString(),n={"Content-Type":"application/json","User-Agent":"Vircle-SDK-TypeScript/1.0.0"};this.config.apiKey&&(n.Authorization=`Bearer ${this.config.apiKey}`,n["X-Vircle-Timestamp"]=s);const r={payload:{events:e},timestamp:s};try{return fetch(i,{method:"POST",headers:n,body:JSON.stringify(r),keepalive:!0}).catch(()=>{}),!0}catch{return!1}}flushWithKeepalive(){const e=this.eventQueue.extractBatch(this.eventQueue.size());return 0===e.length||this.sendWithKeepalive(e)}getQueueStatus(){return{queueSize:this.requestQueue.length,isProcessing:this.isProcessingQueue}}async flush(){await this.flushPriorityQueue(),this.requestQueue.length>0&&await this.processQueue()}clearQueue(){this.eventQueue.clear();const e=new c("CLEANUP_ERROR","Transport queue cleared during shutdown");for(const t of this.requestQueue)t.reject(e);this.requestQueue=[]}updateConfig(e){this.config={...this.config,...e}}setEncryptionConfig(e){this.encryptionConfig=e}updateOptions(e){this.options={...this.options,...e}}dispose(){this.disposed||(this.disposed=!0,this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=void 0),this.pendingFlushTimer&&(clearTimeout(this.pendingFlushTimer),this.pendingFlushTimer=void 0),this.clearQueue(),this.circuitBreaker.reset(),this.config={},this.options={})}isDisposed(){return this.disposed}},Z=class{constructor(){this.rules=[]}addRule(e){return this.rules.push(e),this}removeRule(e){return this.rules=this.rules.filter(t=>t.name!==e),this}validate(e){const t=[],i=[];for(const s of this.rules)try{const n=s.validate(e);t.push(...n.errors),i.push(...n.warnings)}catch(e){t.push(`Validation rule '${s.name}' failed: ${e.message}`)}return{isValid:0===t.length,errors:t,warnings:i}}validateRequired(e,t){return null==e||""===e?{isValid:!1,errors:[`${t} is required`],warnings:[]}:{isValid:!0,errors:[],warnings:[]}}validateStringLength(e,t,i,s="Field"){const n=[];return"string"!=typeof e?n.push(`${s} must be a string`):(void 0!==t&&e.length<t&&n.push(`${s} must be at least ${t} characters long`),void 0!==i&&e.length>i&&n.push(`${s} must be at most ${i} characters long`)),{isValid:0===n.length,errors:n,warnings:[]}}validateNumberRange(e,t,i,s="Field"){const n=[];return"number"!=typeof e||isNaN(e)?n.push(`${s} must be a valid number`):(void 0!==t&&e<t&&n.push(`${s} must be at least ${t}`),void 0!==i&&e>i&&n.push(`${s} must be at most ${i}`)),{isValid:0===n.length,errors:n,warnings:[]}}validateEnum(e,t,i="Field"){const s=Object.values(t);return s.includes(e)?{isValid:!0,errors:[],warnings:[]}:{isValid:!1,errors:[`${i} must be one of: ${s.join(", ")}`],warnings:[]}}validateUrl(e,t="URL"){try{return new URL(e),{isValid:!0,errors:[],warnings:[]}}catch{return{isValid:!1,errors:[`${t} must be a valid URL`],warnings:[]}}}validateEmail(e,t="Email"){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)?{isValid:!0,errors:[],warnings:[]}:{isValid:!1,errors:[`${t} must be a valid email address`],warnings:[]}}validateRequiredProperties(e,t,i="Object"){const s=[];if("object"!=typeof e||null===e)s.push(`${i} must be an object`);else for(const n of t)n in e&&null!==e[n]&&void 0!==e[n]||s.push(`${i}.${n} is required`);return{isValid:0===s.length,errors:s,warnings:[]}}validateArray(e,t,i="Array"){const s=[],n=[];return Array.isArray(e)?e.forEach((e,r)=>{const o=t(e,r);s.push(...o.errors.map(e=>`${i}[${r}]: ${e}`)),n.push(...o.warnings.map(e=>`${i}[${r}]: ${e}`))}):s.push(`${i} must be an array`),{isValid:0===s.length,errors:s,warnings:n}}checkSecurity(e,t){const i=[],s=[];if("string"==typeof e){/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi.test(e)&&s.push(`${t} contains potentially dangerous script content`);const n=[/javascript:/i,/data:text\/html/i,/vbscript:/i,/on\w+\s*=/i];for(const s of n)if(s.test(e)){i.push(`${t} contains potentially suspicious content`);break}}return{isValid:0===s.length,errors:s,warnings:i}}},X=class extends Z{constructor(e={}){super(),this.config={maxEventNameLength:100,maxPropertyKeyLength:50,maxPropertyValueLength:1e3,maxPropertiesCount:100,maxEventSize:102400,allowedEventNamePattern:/^[a-zA-Z0-9_.-]+$/,forbiddenPropertyNames:["__proto__","constructor","prototype"],enableSecurityChecks:!0,...e},this.setupValidationRules()}validate(e){const t=super.validate(e);return{isValid:t.isValid,errors:t.errors,warnings:t.warnings}}setupValidationRules(){this.addRule({name:"required_fields",validate:e=>this.validateRequiredFields(e)}),this.addRule({name:"event_name",validate:e=>this.validateEventName(e.name)}),this.addRule({name:"properties",validate:e=>this.validateProperties(e.properties)}),this.addRule({name:"context",validate:e=>this.validateContext(e.context)}),this.addRule({name:"user_id",validate:e=>this.validateUserId(e.userId)}),this.addRule({name:"session_id",validate:e=>this.validateSessionId(e.sessionId)}),this.addRule({name:"timestamp",validate:e=>this.validateTimestamp(e.timestamp)}),this.addRule({name:"event_size",validate:e=>this.validateEventSize(e)}),this.config.enableSecurityChecks&&this.addRule({name:"security",validate:e=>this.validateSecurity(e)})}validateRequiredFields(e){const t=[];return e.name||t.push("Event name is required"),{isValid:0===t.length,errors:t,warnings:[]}}validateEventName(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};e.length>this.config.maxEventNameLength&&t.push(`Event name must not exceed ${this.config.maxEventNameLength} characters`),this.config.allowedEventNamePattern.test(e)||t.push("Event name contains invalid characters. Use only letters, numbers, underscores, dots, and hyphens");return["error","debug","log","warn","info"].includes(e.toLowerCase())&&i.push(`Event name '${e}' is reserved and may cause conflicts`),e.includes(" ")&&i.push("Event name contains spaces. Consider using underscores or camelCase"),e!==e.toLowerCase()&&e.includes("_")&&i.push("Mixing camelCase and snake_case in event name is not recommended"),{isValid:0===t.length,errors:t,warnings:i}}validateProperties(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e||Array.isArray(e))return t.push("Properties must be an object"),{isValid:!1,errors:t,warnings:i};const s=Object.keys(e);s.length>this.config.maxPropertiesCount&&t.push(`Too many properties. Maximum allowed: ${this.config.maxPropertiesCount}`);for(const n of s){const s=e[n];n.length>this.config.maxPropertyKeyLength&&t.push(`Property key '${n}' exceeds maximum length of ${this.config.maxPropertyKeyLength}`),this.config.forbiddenPropertyNames.includes(n)&&t.push(`Property name '${n}' is forbidden`),n.startsWith("_")&&!n.startsWith("_vircle_")&&i.push(`Property '${n}' starts with underscore. This may conflict with internal properties`);const r=this.validatePropertyValue(s,n);t.push(...r.errors),i.push(...r.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validatePropertyValue(e,t){const i=[],s=[];if(null==e)return s.push(`Property '${t}' has null/undefined value`),{isValid:!0,errors:i,warnings:s};const n=typeof e;if(!["string","number","boolean","object"].includes(n))return i.push(`Property '${t}' has unsupported type '${n}'`),{isValid:!1,errors:i,warnings:s};if("string"===n&&(e.length>this.config.maxPropertyValueLength&&i.push(`Property '${t}' value exceeds maximum length of ${this.config.maxPropertyValueLength}`),this.config.enableSecurityChecks)){const n=this.checkSecurity(e,`Property '${t}'`);i.push(...n.errors),s.push(...n.warnings)}if("number"===n&&(Number.isFinite(e)||i.push(`Property '${t}' has invalid number value (Infinity/NaN)`)),"object"===n&&null!==e)if(Array.isArray(e))e.length>100&&s.push(`Property '${t}' array is very large (${e.length} items)`);else{const n=this.validateProperties(e);i.push(...n.errors.map(e=>`${t}.${e}`)),s.push(...n.warnings.map(e=>`${t}.${e}`))}return{isValid:0===i.length,errors:i,warnings:s}}validateContext(e){return e?this.validateProperties(e):{isValid:!0,errors:[],warnings:[]}}validateUserId(e){return e?this.validateStringLength(e,1,255,"User ID"):{isValid:!0,errors:[],warnings:[]}}validateSessionId(e){return e?this.validateStringLength(e,1,255,"Session ID"):{isValid:!0,errors:[],warnings:[]}}validateTimestamp(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};let s;if(e instanceof Date)s=e;else{if("string"!=typeof e)return t.push("Timestamp must be a Date object or ISO string"),{isValid:!1,errors:t,warnings:i};if(s=new Date(e),isNaN(s.getTime()))return t.push("Invalid timestamp format"),{isValid:!1,errors:t,warnings:i}}const n=new Date,r=new Date(n.getFullYear()-1,n.getMonth(),n.getDate()),o=new Date(n.getTime()+36e5);return s<r&&i.push("Timestamp is more than a year old"),s>o&&i.push("Timestamp is in the future"),{isValid:0===t.length,errors:t,warnings:i}}validateEventSize(e){try{const t=JSON.stringify(e),i=new Blob([t]).size;if(i>this.config.maxEventSize)return{isValid:!1,errors:[`Event size (${i} bytes) exceeds maximum allowed size (${this.config.maxEventSize} bytes)`],warnings:[]};const s=[];return i>.8*this.config.maxEventSize&&s.push(`Event size (${i} bytes) is approaching the maximum limit`),{isValid:!0,errors:[],warnings:s}}catch(e){return{isValid:!1,errors:[`Failed to calculate event size: ${e.message}`],warnings:[]}}}validateSecurity(e){const t=[],i=[],s=this.checkSecurity(e.name,"Event name");if(t.push(...s.errors),i.push(...s.warnings),e.userId){const s=this.checkSecurity(e.userId,"User ID");t.push(...s.errors),i.push(...s.warnings)}if(e.sessionId){const s=this.checkSecurity(e.sessionId,"Session ID");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}},ee=class extends Z{constructor(e={}){super(),this.options={requireApiKey:!0,allowedEnvironments:["development","production"],maxBatchSize:1e3,maxQueueSize:1e4,maxRetryAttempts:10,...e},this.setupValidationRules()}validate(e){const t=super.validate(e);return{isValid:t.isValid,errors:t.errors,warnings:t.warnings}}setupValidationRules(){this.addRule({name:"api_key",validate:e=>this.validateApiKey(e.apiKey,e)}),this.addRule({name:"environment",validate:e=>this.validateEnvironment(e.environment)}),this.addRule({name:"batch_config",validate:e=>this.validateBatchConfig(e.batch)}),this.addRule({name:"queue_config",validate:e=>this.validateQueueConfig(e.queue)}),this.addRule({name:"retry_config",validate:e=>this.validateRetryConfig(e.retry)}),this.addRule({name:"transport_config",validate:e=>this.validateTransportConfig(e.transport)}),this.addRule({name:"storage_config",validate:e=>this.validateStorageConfig(e.storage)}),this.addRule({name:"plugin_config",validate:e=>this.validatePluginConfig(e.plugins)}),this.addRule({name:"auto_collect_config",validate:e=>this.validateAutoCollectConfig(e.autoCollect)}),this.addRule({name:"privacy_config",validate:e=>this.validatePrivacyConfig(e.privacy)}),this.addRule({name:"headers",validate:e=>this.validateHeaders(e.headers)})}validateApiKey(e,t){const i=[],s=[];if(this.options.requireApiKey&&!e)return i.push("API key is required"),{isValid:!1,errors:i,warnings:s};if(e){e.length<10&&i.push("API key seems too short (minimum 10 characters)"),e.length>500&&i.push("API key seems too long (maximum 500 characters)"),/^[a-zA-Z0-9_.-]+$/.test(e)||s.push("API key contains unusual characters");const t=function(e){const t=[];if(!e||"string"!=typeof e)return{isValid:!1,isTestKey:!1,warnings:["API key is required"]};e.length<10&&t.push("API key appears to be too short");const i=[/^test/i,/^demo/i,/^sample/i,/^example/i].some(t=>t.test(e));i&&t.push("API key appears to be a test key");const s=[/^[0-9]+$/,/^[a-zA-Z]+$/,/^(.)\1+$/,/password/i,/secret/i,/\s/].some(t=>t.test(e));return s&&t.push("API key format appears to be invalid"),{isValid:!s&&e.length>=10,isTestKey:i,warnings:t}}(e);t.isValid||i.push("Invalid API key format"),t.isTestKey&&s.push("Test API key detected - ensure you use a production key in production"),s.push(...t.warnings)}return{isValid:0===i.length,errors:i,warnings:s}}validateEnvironment(e){return e?this.validateEnum(e,this.options.allowedEnvironments.reduce((e,t)=>({...e,[t]:t}),{}),"Environment"):{isValid:!0,errors:[],warnings:[]}}validateBatchConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Batch configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.size){const s=this.validateNumberRange(e.size,1,this.options.maxBatchSize,"Batch size");t.push(...s.errors),i.push(...s.warnings),e.size>100&&i.push("Large batch sizes may impact performance")}if(void 0!==e.timeout){const s=this.validateNumberRange(e.timeout,100,3e5,"Batch timeout");t.push(...s.errors),i.push(...s.warnings),e.timeout<1e3&&i.push("Very short batch timeout may cause frequent network requests")}if(void 0!==e.maxBytes){const s=this.validateNumberRange(e.maxBytes,1024,52428800,"Batch max bytes");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateQueueConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Queue configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.maxSize){const s=this.validateNumberRange(e.maxSize,10,this.options.maxQueueSize,"Queue max size");t.push(...s.errors),i.push(...s.warnings),e.maxSize>5e3&&i.push("Large queue sizes may consume significant memory")}if(void 0!==e.workers){const s=this.validateNumberRange(e.workers,1,10,"Queue workers");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.strategy){const s={fifo:"fifo",lifo:"lifo",priority:"priority"},n=this.validateEnum(e.strategy,s,"Queue strategy");t.push(...n.errors),i.push(...n.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateRetryConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Retry configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.maxAttempts){const s=this.validateNumberRange(e.maxAttempts,0,this.options.maxRetryAttempts,"Max retry attempts");t.push(...s.errors),i.push(...s.warnings),e.maxAttempts>5&&i.push("High retry attempts may delay error reporting")}if(void 0!==e.initialDelay){const s=this.validateNumberRange(e.initialDelay,10,6e4,"Initial retry delay");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.maxDelay){const s=this.validateNumberRange(e.maxDelay,100,36e5,"Max retry delay");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.multiplier){const s=this.validateNumberRange(e.multiplier,1,10,"Retry multiplier");t.push(...s.errors),i.push(...s.warnings)}return e.initialDelay&&e.maxDelay&&e.initialDelay>=e.maxDelay&&t.push("Initial retry delay must be less than max retry delay"),{isValid:0===t.length,errors:t,warnings:i}}validateTransportConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Transport configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.timeout){const s=this.validateNumberRange(e.timeout,1e3,3e5,"Transport timeout");t.push(...s.errors),i.push(...s.warnings)}if(void 0!==e.connectionTimeout){const s=this.validateNumberRange(e.connectionTimeout,1e3,6e4,"Connection timeout");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validateStorageConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Storage configuration must be an object"),{isValid:!1,errors:t,warnings:i};if(void 0!==e.type){const s={memory:"memory",localStorage:"localStorage",indexedDB:"indexedDB",file:"file"},n=this.validateEnum(e.type,s,"Storage type");t.push(...n.errors),i.push(...n.warnings)}if(void 0!==e.maxSize){const s=this.validateNumberRange(e.maxSize,1024,1073741824,"Storage max size");t.push(...s.errors),i.push(...s.warnings)}return{isValid:0===t.length,errors:t,warnings:i}}validatePluginConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if(!Array.isArray(e))return t.push("Plugins configuration must be an array"),{isValid:!1,errors:t,warnings:i};const s=new Set;for(let i=0;i<e.length;i++){const n=e[i];"object"==typeof n&&n?n.name?(s.has(n.name)?t.push(`Duplicate plugin name: ${n.name}`):s.add(n.name),"string"==typeof n.name&&0!==n.name.length||t.push(`Plugin at index ${i} must have a valid name`),void 0!==n.version&&"string"!=typeof n.version&&t.push(`Plugin '${n.name}' version must be a string`),void 0!==n.initialize&&"function"!=typeof n.initialize&&t.push(`Plugin '${n.name}' initialize must be a function`)):t.push(`Plugin at index ${i} must have a name`):t.push(`Plugin at index ${i} must be an object`)}return{isValid:0===t.length,errors:t,warnings:i}}validateAutoCollectConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Auto-collect configuration must be an object"),{isValid:!1,errors:t,warnings:i};const s=["device","app","page","userAgent","referrer","campaign","performance"];for(const i of s)void 0!==e[i]&&"boolean"!=typeof e[i]&&t.push(`Auto-collect ${i} must be a boolean`);return{isValid:0===t.length,errors:t,warnings:i}}validatePrivacyConfig(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Privacy configuration must be an object"),{isValid:!1,errors:t,warnings:i};const s=["respectDoNotTrack","anonymizeIP","requireCookieConsent","gdprCompliant","requireOptIn"];for(const i of s)void 0!==e[i]&&"boolean"!=typeof e[i]&&t.push(`Privacy ${i} must be a boolean`);return{isValid:0===t.length,errors:t,warnings:i}}validateHeaders(e){const t=[],i=[];if(!e)return{isValid:!0,errors:t,warnings:i};if("object"!=typeof e)return t.push("Headers must be an object"),{isValid:!1,errors:t,warnings:i};for(const[s,n]of Object.entries(e)){"string"==typeof s&&"string"==typeof n||t.push(`Header '${s}' must have string key and value`),/^[a-zA-Z0-9-_]+$/.test(s)||t.push(`Invalid header name format: ${s}`);["authorization","cookie","set-cookie"].includes(s.toLowerCase())&&i.push(`Setting sensitive header '${s}' may have security implications`)}return{isValid:0===t.length,errors:t,warnings:i}}},te=class{constructor(e={}){this.cache=new Map,this.pendingCollectors=new Map,this.options={cacheTime:e.cacheTime??6e4,getCacheKey:e.getCacheKey??(()=>"default")}}async getOrCollect(e){const t=this.options.getCacheKey(),i=this.cache.get(t),s=Date.now();if(i&&s-i.timestamp<this.options.cacheTime)return i.context;const n=this.pendingCollectors.get(t);if(n)return n;const r=e();this.pendingCollectors.set(t,r);try{const e=await r;return this.cache.set(t,{context:e,timestamp:s}),e}catch(e){if(i)return console.warn("[ContextCache] Collection failed, returning stale cache:",e),i.context;throw e}finally{this.pendingCollectors.delete(t)}}invalidate(e){const t=e??this.options.getCacheKey();this.cache.delete(t)}clear(){this.cache.clear()}getStats(){return{size:this.cache.size,keys:Array.from(this.cache.keys())}}setCacheTime(e){this.options.cacheTime=e}cleanup(){const e=Date.now();for(const[t,i]of this.cache.entries())e-i.timestamp>=this.options.cacheTime&&this.cache.delete(t)}},ie=class{},se=class extends ie{constructor(){super(...arguments),this.handles=new Set}schedule(e,t){const i=t?.timeout??3e3;if("undefined"!=typeof window&&"requestIdleCallback"in window){const t=window.requestIdleCallback(async i=>{this.handles.delete(t);try{await e()}catch(e){console.error("[WebIdleScheduler] Callback error:",e)}},{timeout:i});return this.handles.add(t),t}{const t=setTimeout(async()=>{this.handles.delete(t);try{await e()}catch(e){console.error("[WebIdleScheduler] Callback error:",e)}},0);return this.handles.add(t),t}}cancel(e){"undefined"!=typeof window&&"cancelIdleCallback"in window?window.cancelIdleCallback(e):clearTimeout(e),this.handles.delete(e)}cancelAll(){for(const e of this.handles)this.cancel(e);this.handles.clear()}},ne=class extends ie{constructor(){super(...arguments),this.handles=new Map,this.nextId=0}schedule(e,t){const i=this.nextId++,s=setTimeout(async()=>{this.handles.delete(i);try{await e()}catch(e){console.error("[DefaultIdleScheduler] Callback error:",e)}},0);return this.handles.set(i,s),i}cancel(e){const t=this.handles.get(e);t&&(clearTimeout(t),this.handles.delete(e))}cancelAll(){for(const e of this.handles.values())clearTimeout(e);this.handles.clear()}},re=class{constructor(e,t=1e3){this.queue=[],this.isProcessing=!1,this.scheduler=e,this.maxQueueSize=t}enqueue(e,t=0,i){for(this.queue.push({task:e,priority:t,timestamp:Date.now()}),this.queue.sort((e,t)=>t.priority-e.priority);this.queue.length>this.maxQueueSize;)this.queue.pop();this.isProcessing||this.scheduleProcessing(i)}scheduleProcessing(e){this.handle&&this.scheduler.cancel(this.handle),this.handle=this.scheduler.schedule(async()=>{await this.processQueue()},e)}async processQueue(){if(!this.isProcessing&&0!==this.queue.length){this.isProcessing=!0;try{for(;this.queue.length>0;){const e=this.queue.shift();if(e)try{await e.task()}catch(e){console.error("[TaskScheduler] Task error:",e)}}}finally{this.isProcessing=!1,this.handle=void 0}}}clear(){this.queue=[],this.handle&&(this.scheduler.cancel(this.handle),this.handle=void 0),this.isProcessing=!1}getStats(){return{queueSize:this.queue.length,isProcessing:this.isProcessing}}};function oe(e,t=""){return"undefined"!=typeof process&&process&&"object"==typeof process&&process.env&&"object"==typeof process.env&&process.env[e]||t}var ae="__vircle_config_",ce=class e{constructor(){this.configCache=new Map,this.configPromises=new Map,this.CACHE_DURATION=3e5,this.cacheTimestamps=new Map}static getInstance(){return e.instance||(e.instance=new e),e.instance}async getProjectConfig(e,t="production"){const i=this.getCachedConfig(e);if(i)return i;const s=this.getStorageCachedConfig(e);if(s)return this.setCachedConfig(e,s),s;const n=this.configPromises.get(e);if(n)return n;const r=this.fetchConfig(e,t);this.configPromises.set(e,r);try{const t=await r;return this.setCachedConfig(e,t),this.setStorageCachedConfig(e,t),this.configPromises.delete(e),t}catch(t){throw this.configPromises.delete(e),t}}async fetchConfig(e,t){const i=this.extractProjectId(e);try{return await this.fetchFromCDN(i,e,t)}catch(e){throw new c("REMOTE_CONFIG_FETCH_FAILED",`Failed to fetch configuration for project ${i}. Please ensure the project is properly configured.`,{context:{projectId:i,cdnError:e instanceof Error?e.message:String(e),environment:t}})}}async fetchFromCDN(e,t,i){const s=`${oe("VIRCLE_CONFIG_CDN_URL")||N[i]}/${e}/config.json`,n=await fetch(s,{method:"GET",headers:{Accept:"application/json"},cache:"default",mode:"cors"});if(!n.ok)throw new Error(`CDN returned ${n.status}`);const r=await n.json();return this.validateConfig(r,i)}extractProjectId(e){const t=e.match(/^pk_([^_]+)_/);return t&&t[1]?t[1]:this.hashApiKey(e).substring(0,8)}hashApiKey(e){let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(36)}validateConfig(e,t){if(!e||"object"!=typeof e)throw new c("INVALID_CONFIGURATION","Invalid project configuration format");if(!e.projectId)throw new c("INVALID_CONFIGURATION","Project ID is required");if(!e.environment)throw new c("INVALID_CONFIGURATION","Environment field is required in project configuration");if("development"!==e.environment&&"production"!==e.environment)throw new c("INVALID_CONFIGURATION",`Invalid environment value: ${e.environment}. Must be 'development' or 'production'`);if(e.environment!==t)throw new c("INVALID_CONFIGURATION",`Environment mismatch: requested '${t}' but config is for '${e.environment}'`);if(e.publicKey&&!this.isValidPublicKey(e.publicKey))throw new c("INVALID_CONFIGURATION","Invalid public key format");return{projectId:e.projectId,environment:e.environment,publicKey:e.publicKey,features:{encryption:e.features?.encryption??!1,compression:e.features?.compression??!0,batching:e.features?.batching??!0},settings:e.settings,enable_pixel:e.enable_pixel??!1,vircle_pixel_id:e.vircle_pixel_id}}isValidPublicKey(e){try{return"undefined"!=typeof atob?atob(e):Buffer.from(e,"base64"),e.length>100}catch{return!1}}getDefaultConfig(e){return{projectId:e,environment:"production",features:{encryption:!1,compression:!0,batching:!0}}}getCachedConfig(e){const t=this.configCache.get(e),i=this.cacheTimestamps.get(e);if(t&&i){if(Date.now()-i<this.CACHE_DURATION)return t}return null}setCachedConfig(e,t){this.configCache.set(e,t),this.cacheTimestamps.set(e,Date.now())}getStorageCachedConfig(e){try{if("undefined"==typeof localStorage)return null;const t=localStorage.getItem(ae+e);if(!t)return null;const{config:i,timestamp:s}=JSON.parse(t);if(Date.now()-s<this.CACHE_DURATION)return i;localStorage.removeItem(ae+e)}catch{}return null}setStorageCachedConfig(e,t){try{if("undefined"==typeof localStorage)return;localStorage.setItem(ae+e,JSON.stringify({config:t,timestamp:Date.now()}))}catch{}}clearCache(){try{if("undefined"!=typeof localStorage){const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);i?.startsWith(ae)&&e.push(i)}for(const t of e)localStorage.removeItem(t)}}catch{}this.configCache.clear(),this.configPromises.clear(),this.cacheTimestamps.clear()}},le=class e{constructor(e,t={}){this.isInitialized=!1,this.globalContext={},this.globalProperties={},this.lastSessionPersistTime=0,this.config={...e};const s=void 0!==t.storageType;this.options={enableValidation:!0,enableAutoContext:!0,enablePlugins:!0,pluginTimeout:5e3,storageType:"localStorage",debug:!1,...t};var n;("localStorage"===this.options.storageType||"indexedDB"===this.options.storageType)&&!this.options.accountSwitchDetectionEnabled&&(s&&console.warn(`[VircleCore] storageType=${this.options.storageType}는 accountSwitchDetectionEnabled=true와 함께 사용해야 합니다. 다중 사용자 환경에서 vuid 오염 방지를 위해 memory로 폴백합니다. 계정 전환 감지가 가능한 플러그인(예: @vircle/plugin-cafe24)을 사용 중이면 accountSwitchDetectionEnabled: true를 명시하세요.`),this.options.storageType="memory"),this.consent=(n=this.config.defaultConsent,{...i,...n??{}}),this.configService=new V(this.config),this.contextService=new L(this.config),this.pluginService=new $(this.config,{maxExecutionTime:this.options.pluginTimeout}),this.pluginService.setTrackFn((e,t)=>this.track(e,t)),this.pluginService.setIdentifyFn((e,t)=>this.identify(e,t)),this.pluginService.setResetFn(()=>this.reset()),this.pluginService.setSetAnonymousIdFn(e=>this.setAnonymousId(e)),this.pluginService.setGetConsentFn(()=>this.consent),this.pluginService.setGetRemoteConfigFn(()=>ce.getInstance().getProjectConfig(this.config.apiKey,this.config.environment||"production")),this.pluginService.setGetAnonymousIdFn(()=>this.currentUser?.anonymousId),this.pluginService.setGetCookieDomainFn(()=>this.config.cookieDomain),this.storageService=new H({type:this.options.storageType,adapter:this.options.storageAdapter}),this.transportService=new Y(this.config,{cryptoAdapter:this.options.cryptoAdapter}),this.remoteConfigService=ce.getInstance(),this.eventService=new O(this.config,{contextService:this.contextService,pluginService:this.options.enablePlugins?this.pluginService:void 0,storageService:this.storageService,transportService:this.transportService,getConsent:()=>this.consent,cryptoAdapter:this.options.cryptoAdapter}),this.options.enableValidation&&(this.eventValidator=new X,this.configValidator=new ee),this.contextCache=new te({cacheTime:this.options.contextCacheTime||6e4});const r=this.options.idleScheduler||("undefined"!=typeof window?new se:new ne);this.taskScheduler=new re(r)}async initialize(){if(!this.isInitialized)try{await this.validateConfiguration();try{const e=await this.remoteConfigService.getProjectConfig(this.config.apiKey,this.config.environment||"production");this.options.debug&&console.log("[VircleCore] Remote config loaded:",{projectId:e.projectId,environment:e.environment,features:e.features}),this.options.enableEncryption&&e.publicKey?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:e.publicKey}),this.options.debug&&console.log("[VircleCore] Applied remote encryption config")):e.features.encryption&&(console.warn("[VircleCore] Remote config has encryption enabled but no public key provided"),"true"===oe("VIRCLE_ALLOW_FALLBACK_KEY","false")&&P.PUBLIC_KEY?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:P.PUBLIC_KEY}),this.options.debug&&console.log("[VircleCore] Using fallback encryption key")):(this.options.enableEncryption=!1,console.warn("[VircleCore] Encryption disabled - no valid public key available"))),e.settings&&(e.settings.batchSize&&!this.config.batch?this.config.batch={size:e.settings.batchSize}:e.settings.batchSize&&this.config.batch&&(this.config.batch.size=e.settings.batchSize),e.settings.flushInterval&&!this.config.batch?this.config.batch={flushInterval:e.settings.flushInterval}:e.settings.flushInterval&&this.config.batch&&(this.config.batch.flushInterval=e.settings.flushInterval),e.settings.maxRetries&&!this.config.retry?this.config.retry={maxAttempts:e.settings.maxRetries}:e.settings.maxRetries&&this.config.retry&&(this.config.retry.maxAttempts=e.settings.maxRetries),this.configService.updateConfig(this.config),this.transportService.updateConfig(this.config))}catch(e){this.options.debug&&console.log("[VircleCore] Failed to load remote config, using defaults",e),"true"===oe("VIRCLE_ALLOW_FALLBACK_KEY","false")&&P.PUBLIC_KEY?(this.transportService.setEncryptionConfig({enabled:!0,publicKey:P.PUBLIC_KEY}),this.options.debug&&console.log("[VircleCore] Using fallback encryption key after config fetch failure")):(this.options.enableEncryption=!1,console.warn("[VircleCore] Encryption disabled - remote config failed and no fallback key"))}await this.loadPersistedUser();const e=await this.restoreOrCreateSession();if(this.isInitialized=!0,"restored"!==e)try{await this.track("session_start",{reason:e})}catch(e){this.options.debug&&console.warn("[VircleCore] session_start 추적 실패:",e)}this.options.enablePlugins&&this.config.plugins&&await this.initializePlugins(),this.options.enablePlugins&&await this.pluginService.executeLifecycle("session-started",{sessionId:this.sessionId,user:this.currentUser}),this.options.debug&&console.log("[VircleCore] Initialized successfully",{config:q(this.config),sessionId:this.sessionId})}catch(e){throw new c("SDK_INITIALIZATION_FAILED",`Failed to initialize Vircle SDK: ${e.message}`,{cause:e})}}async track(e,t,i){this.ensureInitialized();try{const s={id:this.generateEventId(),schema_version:R,name:g(e),properties:m(this.globalProperties,m(t||{},this.currentUser?.anonymousId?{_vuid:this.currentUser.anonymousId}:{})),context:f(this.globalContext,i),userId:this.currentUser?.id,anonymousId:this.currentUser?.anonymousId,sessionId:this.sessionId,timestamp:v()};if(this.eventValidator){const e=this.eventValidator.validate(s);if(!e.isValid)throw new u("Event validation failed",e.errors);this.options.debug&&e.warnings.length>0&&console.warn("[VircleCore] Event validation warnings:",e.warnings)}await this.eventService.track(s),this.persistSession().catch(()=>{})}catch(t){throw this.options.debug&&console.error("[VircleCore] Track error:",t),new c("EVENT_TRACKING_FAILED",`Failed to track event "${e}"`,{cause:t})}}async trackBatch(e){this.ensureInitialized();try{const t=e.map(e=>({id:this.generateEventId(),schema_version:R,name:g(e.name),properties:m(this.globalProperties,m(e.properties||{},this.currentUser?.anonymousId?{_vuid:this.currentUser.anonymousId}:{})),context:f(this.globalContext,e.context),userId:e.userId||this.currentUser?.id,anonymousId:this.currentUser?.anonymousId,sessionId:e.sessionId||this.sessionId,timestamp:v(e.timestamp)}));if(this.eventValidator)for(const e of t){const t=this.eventValidator.validate(e);if(!t.isValid)throw new u(`Event validation failed for "${e.name}"`,t.errors)}for(const e of t)await this.eventService.track(e)}catch(e){throw this.options.debug&&console.error("[VircleCore] TrackBatch error:",e),new c("BATCH_PROCESSING_FAILED","Failed to track batch events",{cause:e})}}createEvent(e){return this.ensureInitialized(),this.eventService.createEvent(e)}async identify(e,i){this.ensureInitialized();try{const s=await this.transformIdentifyTraits(i),n=t.create(e,s||{},this.currentUser?.anonymousId);this.currentUser=n;try{await this.storageService.set(k,n)}catch(e){this.options.debug&&console.error("[VircleCore] Failed to persist user:",e)}await this.track("identify",{userId:e,...s}),this.options.enablePlugins&&await this.pluginService.executeLifecycle("user-identified",{user:n,sessionId:this.sessionId}),this.options.debug&&console.log("[VircleCore] User identified:",{userId:e})}catch(t){throw this.options.debug&&console.error("[VircleCore] Identify error:",t),new c("USER_IDENTIFICATION_FAILED",`Failed to identify user "${e}"`,{cause:t})}}setConsent(e){this.consent={analytics:e.analytics??this.consent.analytics,marketing:e.marketing??this.consent.marketing,functional:e.functional??this.consent.functional},this.options.debug&&console.log("[VircleCore] Consent updated:",this.consent)}getConsent(){return{...this.consent}}async transformIdentifyTraits(e){if(!e)return e;const{email:t,phone:i,em:a,ph:c,...l}=e;if(!this.consent.marketing)return l;const u=this.options.cryptoAdapter?.sha256?.bind(this.options.cryptoAdapter),h=o(a),d=o(c),p=u?await async function(e,t){const i=r(e,s);return Promise.all(i.map(e=>t(e)))}(t,u):[],g=u?await async function(e,t){const i=r(e,n);return Promise.all(i.map(e=>t(e)))}(i,u):[],m=e=>Array.from(new Set(e)),f=m([...h,...p]),y=m([...d,...g]);return{...l,...f.length>0?{em:f}:{},...y.length>0?{ph:y}:{}}}getAnonymousId(){return this.currentUser?.anonymousId}setAnonymousId(e){if(!this.currentUser)return;const t=this.currentUser.anonymousId;t!==e&&(this.currentUser={...this.currentUser,anonymousId:e},this.storageService.set(k,this.currentUser).catch(()=>{}),t&&this.track("vuid_alias",{previous_vuid:t,vuid:e}).catch(()=>{}),this.options.debug&&console.log("[VircleCore] Anonymous ID overridden:",{previous:t,current:e}))}generateEventId(){const e=this.options.cryptoAdapter?.generateUUID?.();return e??w()}setSessionId(e){this.sessionId=e,this.options.debug&&console.log("[VircleCore] Session ID updated:",e)}setContext(e){this.globalContext=f(this.globalContext,e),this.options.debug&&console.log("[VircleCore] Global context updated:",this.globalContext)}clearContext(){this.globalContext={},this.options.debug&&console.log("[VircleCore] Global context cleared")}setGlobalProperties(e){this.globalProperties=m(this.globalProperties,e),this.options.debug&&console.log("[VircleCore] Global properties updated:",this.globalProperties)}clearGlobalProperties(){this.globalProperties={},this.options.debug&&console.log("[VircleCore] Global properties cleared")}async registerPlugin(e){if(this.ensureInitialized(),!this.options.enablePlugins)throw new c("PLUGIN_NOT_ENABLED","Plugins are not enabled in SDK configuration");await this.pluginService.register(e),this.options.debug&&console.log("[VircleCore] Plugin registered:",e.name)}async unregisterPlugin(e){if(this.ensureInitialized(),!this.options.enablePlugins)return!1;const t=await this.pluginService.unregister(e);return this.options.debug&&t&&console.log("[VircleCore] Plugin unregistered:",e),t}async updateConfig(e){this.ensureInitialized();try{const t={...this.config,...e};if(this.configValidator){const e=this.configValidator.validate(t);if(!e.isValid)throw new u("Configuration validation failed",e.errors)}this.config=t,this.configService.updateConfig(this.config),this.transportService.updateConfig(this.config),this.options.enablePlugins&&await this.pluginService.executeLifecycle("config-changed",{config:this.config}),this.options.debug&&console.log("[VircleCore] Configuration updated:",e)}catch(e){if(this.options.debug&&console.error("[VircleCore] Config update error:",e),e instanceof c)throw e;throw new c("CONFIG_UPDATE_FAILED","Failed to update configuration",{cause:e})}}async flush(e){if(this.ensureInitialized(),e){const t=new Promise((t,i)=>{setTimeout(()=>i(new Error("Flush timeout")),e)});await Promise.race([this.transportService.flush(),t])}else await this.transportService.flush();this.options.debug&&console.log("[VircleCore] Events flushed")}async reset(){this.ensureInitialized();try{this.currentUser=void 0,this.sessionId=this.generateSessionId(),this.globalContext={},this.globalProperties={},await this.persistSession(!0),await this.storageService.clear(),this.options.enablePlugins&&(await this.pluginService.executeLifecycle("session-ended"),await this.pluginService.executeLifecycle("session-started",{sessionId:this.sessionId})),this.options.debug&&console.log("[VircleCore] SDK reset completed")}catch(e){throw this.options.debug&&console.error("[VircleCore] Reset error:",e),e}}getStatus(){return{isInitialized:this.isInitialized,sessionId:this.sessionId,userId:this.currentUser?.id,pluginCount:this.options.enablePlugins?this.pluginService.getPluginCount():0,queueSize:this.transportService.getQueueStatus().queueSize}}getMetrics(){const e=this.transportService.getQueueStatus();return{queueSize:e.queueSize,isProcessing:e.isProcessing}}async cleanup(){if(!this.isInitialized)return;const e=[];try{await this.flush()}catch(t){e.push(new c("FLUSH_FAILED","Failed to flush events during cleanup",{cause:t}))}try{this.options.enablePlugins&&(await this.pluginService.executeLifecycle("session-ended"),await this.pluginService.cleanup())}catch(t){e.push(new c("PLUGIN_ERROR","Failed to cleanup plugins",{cause:t}))}this.transportService.clearQueue();try{this.eventService.dispose();const e=[this.storageService,this.contextService,this.transportService,this.pluginService];for(const t of e)if(t&&"dispose"in t&&"function"==typeof t.dispose)try{t.dispose()}catch(e){console.warn("[VircleCore] Error disposing service:",e)}this.taskScheduler.clear(),this.contextCache.clear()}catch(t){e.push(new c("CLEANUP_ERROR","Failed to dispose services",{cause:t}))}if(this.currentUser=void 0,this.sessionId=void 0,this.globalContext={},this.globalProperties={},this.isInitialized=!1,e.length>0){const t=`Cleanup completed with ${e.length} error(s): ${e.map(e=>e.message).join("; ")}`;throw this.options.debug&&console.error("[VircleCore] "+t,e),new c("CLEANUP_ERROR",t,{context:{errors:e}})}this.options.debug&&console.log("[VircleCore] Cleanup completed successfully")}ensureInitialized(){if(!this.isInitialized)throw new c("SDK_NOT_INITIALIZED","Vircle SDK must be initialized before use. Call initialize() first.")}async validateConfiguration(){if(!this.configValidator)return;const e=this.configValidator.validate(this.config);if(!e.isValid)throw new l("Invalid SDK configuration",{context:{errors:e.errors}});this.options.debug&&e.warnings.length>0&&console.warn("[VircleCore] Configuration warnings:",e.warnings)}async initializePlugins(){if(!this.config.plugins||!this.options.enablePlugins)return;const e=[];for(const t of this.config.plugins)try{await this.pluginService.register(t),this.options.debug&&console.log(`[VircleCore] Plugin auto-loaded: ${t.name}`)}catch(i){e.push(i),this.options.debug&&console.warn(`[VircleCore] Failed to auto-load plugin '${t.name}':`,i)}e.length>0&&this.options.debug&&console.warn(`[VircleCore] Plugin initialization completed with ${e.length} error(s)`)}async loadPersistedUser(){try{const e=await this.storageService.get(k);if(e)return this.currentUser=e,void(this.options.debug&&console.log("[VircleCore] Loaded persisted user:",e.id))}catch(e){this.options.debug&&console.warn("[VircleCore] Failed to load persisted user:",e)}const e=t.create("",{});this.currentUser=e;try{await this.storageService.set(k,e)}catch(e){this.options.debug&&console.warn("[VircleCore] Failed to persist anonymous user:",e)}this.options.debug&&console.log("[VircleCore] Created anonymous user:",e.anonymousId)}async restoreOrCreateSession(){let t="new";try{const i=await this.storageService.get(_);if(i){if(Date.now()-i.lastActivity<e.SESSION_TIMEOUT_MS)return this.sessionId=i.id,await this.persistSession(!0),"restored";t="expired"}}catch{}return this.sessionId=this.generateSessionId(),await this.persistSession(!0),t}async persistSession(t=!1){if(!this.sessionId)return;const i=Date.now();if(t||!(i-this.lastSessionPersistTime<e.SESSION_PERSIST_THROTTLE_MS))try{await this.storageService.set(_,{id:this.sessionId,lastActivity:i}),this.lastSessionPersistTime=i}catch{}}generateSessionId(){return`sess_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}};le.SESSION_TIMEOUT_MS=18e5,le.SESSION_PERSIST_THROTTLE_MS=1e4;var ue=le;const he="_fbp",de="_fbc";function pe(){if("undefined"==typeof document||!document.cookie)return{};const e=function(e){const t={},i=e.split(";");for(const e of i){const i=e.indexOf("=");if(i<=0)continue;const s=e.slice(0,i).trim(),n=e.slice(i+1).trim();if(s&&n)try{t[s]=decodeURIComponent(n)}catch{t[s]=n}}return t}(document.cookie),t={};return e[he]&&(t.fbp=e[he]),e[de]&&(t.fbc=e[de]),t}class ge{async collect(){const[e,t,i]=await Promise.all([this.collectDeviceContext(),this.collectPageContext(),this.collectAppContext()]),s={device:e,page:t,app:i,custom:this.collectCustomContext()},n=this.collectCampaignContext();n&&(s.campaign=n);const r=this.collectMetaContext();return r&&(s.meta=r),s}collectMetaContext(){const e=pe();if(e.fbp||e.fbc)return e}async collectDeviceContext(){const e=navigator.userAgent,t=navigator.platform||"unknown";return{type:this.getDeviceType(e),os:this.getOS(e,t),osVersion:this.getOSVersion(e),browser:this.getBrowser(e),browserVersion:this.getBrowserVersion(e),screenResolution:`${screen.width}x${screen.height}`,viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}async collectPageContext(){const e=new URL(window.location.href);return{url:e.href,title:document.title,path:e.pathname,search:e.search,hash:e.hash}}async collectAppContext(){return{name:this.getAppName(),version:this.getAppVersion(),environment:this.getEnvironment()}}collectCustomContext(){const e={};document.referrer&&(e.referrer=document.referrer),e.cookieEnabled=navigator.cookieEnabled,navigator.doNotTrack&&(e.doNotTrack="1"===navigator.doNotTrack);const t=navigator;t.connection&&(e.connection={effectiveType:t.connection.effectiveType,downlink:t.connection.downlink,rtt:t.connection.rtt,saveData:t.connection.saveData});const i=performance;return i.memory&&(e.memory={usedJSHeapSize:i.memory.usedJSHeapSize,totalJSHeapSize:i.memory.totalJSHeapSize,jsHeapSizeLimit:i.memory.jsHeapSizeLimit}),e}getDeviceType(e){return/mobile/i.test(e)&&!/ipad/i.test(e)?"mobile":/ipad|tablet|playbook|silk/i.test(e)?"tablet":"desktop"}getOS(e,t){return/windows/i.test(e)?"Windows":/macintosh|mac os x/i.test(e)?"macOS":/android/i.test(e)?"Android":/linux/i.test(e)?"Linux":/iphone|ipad|ipod/i.test(e)?"iOS":/cros/i.test(e)?"Chrome OS":t}getOSVersion(e){let t=null;return/windows nt (\d+\.\d+)/i.test(e)?t=e.match(/windows nt (\d+\.\d+)/i):/mac os x (\d+[._]\d+)/i.test(e)?t=e.match(/mac os x (\d+[._]\d+)/i):/android (\d+\.\d+)/i.test(e)?t=e.match(/android (\d+\.\d+)/i):/os (\d+[._]\d+)/i.test(e)&&(t=e.match(/os (\d+[._]\d+)/i)),t?t[1].replace(/_/g,"."):void 0}getBrowser(e){return/edg/i.test(e)?"Edge":/chrome|chromium|crios/i.test(e)?"Chrome":/firefox|fxios/i.test(e)?"Firefox":/safari/i.test(e)&&!/chrome/i.test(e)?"Safari":/opr|opera/i.test(e)?"Opera":/trident/i.test(e)?"IE":"Unknown"}getBrowserVersion(e){let t=null;return/edg\/(\d+\.\d+)/i.test(e)?t=e.match(/edg\/(\d+\.\d+)/i):/chrome\/(\d+\.\d+)/i.test(e)?t=e.match(/chrome\/(\d+\.\d+)/i):/firefox\/(\d+\.\d+)/i.test(e)?t=e.match(/firefox\/(\d+\.\d+)/i):/version\/(\d+\.\d+).*safari/i.test(e)?t=e.match(/version\/(\d+\.\d+).*safari/i):/opr\/(\d+\.\d+)/i.test(e)&&(t=e.match(/opr\/(\d+\.\d+)/i)),t?t[1]:void 0}collectCampaignContext(){if("undefined"==typeof window)return;const e=new URLSearchParams(window.location.search),t=Object.keys(ge.CAMPAIGN_PARAMS_MAP);let i=!1;for(const s of t)if(e.get(s)){i=!0;break}if(i){const i={};for(const e of t)try{sessionStorage.removeItem(ge.STORAGE_PREFIX+e)}catch{}for(const s of t){const t=e.get(s);if(t){try{sessionStorage.setItem(ge.STORAGE_PREFIX+s,t)}catch{}i[s]=t}}this.persistCampaignToLocalStorage(i)}const s={};let n=!1;for(const[e,t]of Object.entries(ge.CAMPAIGN_PARAMS_MAP))try{const i=sessionStorage.getItem(ge.STORAGE_PREFIX+e);i&&(s[t]=i,n=!0)}catch{}if(!n){const e=this.restoreCampaignFromLocalStorage();if(e)for(const[t,i]of Object.entries(ge.CAMPAIGN_PARAMS_MAP)){const r=e[t];if(r){s[i]=r,n=!0;try{sessionStorage.setItem(ge.STORAGE_PREFIX+t,r)}catch{}}}}return n?s:void 0}persistCampaignToLocalStorage(e){try{localStorage.setItem(ge.CAMPAIGN_PERSIST_KEY,JSON.stringify({params:e,timestamp:Date.now()}))}catch{}}restoreCampaignFromLocalStorage(){try{const e=localStorage.getItem(ge.CAMPAIGN_PERSIST_KEY);if(!e)return null;const t=JSON.parse(e);return Date.now()-t.timestamp>ge.CAMPAIGN_PERSIST_TTL_MS?(localStorage.removeItem(ge.CAMPAIGN_PERSIST_KEY),null):t.params}catch{return null}}getAppName(){const e=document.querySelector('meta[name="application-name"]'),t=document.querySelector('meta[property="og:site_name"]');return e?.content||t?.content||document.title||"Web App"}getAppVersion(){const e=document.querySelector('meta[name="version"]');return e?.content||void 0}getEnvironment(){const e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e||e.includes(".local")||e.includes("staging")||e.includes("stage")||e.includes("test")?"development":"production"}}ge.CAMPAIGN_PARAMS_MAP={utm_source:"source",utm_medium:"medium",utm_campaign:"campaign",utm_term:"term",utm_content:"content",gclid:"gclid",fbclid:"fbclid",msclkid:"msclkid",ttclid:"ttclid",kclid:"kclid",n_media:"n_media",n_query:"n_query",n_ad:"n_ad",n_ad_group:"n_ad_group",n_keyword:"n_keyword",n_keyword_id:"n_keyword_id",n_rank:"n_rank",n_campaign_type:"n_campaign_type"},ge.STORAGE_PREFIX="__vircle_campaign_",ge.CAMPAIGN_PERSIST_KEY="__vircle_campaign_persist",ge.CAMPAIGN_PERSIST_TTL_MS=6048e5;class me extends Error{constructor(e,t,i){super(e),this.code=t,this.details=i,this.name="VircleWebError",Error.captureStackTrace&&Error.captureStackTrace(this,me)}}class fe extends me{constructor(e,t){super(e,"CONFIG_ERROR",t),this.name="VircleConfigError"}}class ye extends me{constructor(e,t){super(e,"INITIALIZATION_ERROR",t),this.name="VircleInitializationError"}}class ve extends me{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="VircleStorageError"}}class we extends me{constructor(e,t){super(e,"BROWSER_COMPATIBILITY_ERROR",t),this.name="VircleBrowserCompatibilityError"}}class be{constructor(e="vircle_"){this.prefix=e,this.isAvailable=this.checkAvailability()}checkAvailability(){try{const e=`${this.prefix}test`;return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return console.warn("[Vircle] LocalStorage를 사용할 수 없습니다. 메모리 스토리지로 대체됩니다."),!1}}getKey(e){return`${this.prefix}${e}`}getFullKey(e){return this.getKey(e)}async set(e,t){if(!this.isAvailable)return;const i={value:t,timestamp:Date.now()};try{const t=JSON.stringify(i);localStorage.setItem(this.getKey(e),t)}catch(t){if(t instanceof Error&&"QuotaExceededError"===t.name){console.warn("[Vircle] LocalStorage 용량 초과. 오래된 항목을 정리합니다."),await this.clearOldItems();try{const t=JSON.stringify(i);localStorage.setItem(this.getKey(e),t)}catch(t){throw new ve("LocalStorage 저장 실패",{key:e,error:t instanceof Error?t.message:String(t)})}}}}async get(e){if(!this.isAvailable)return null;try{const t=localStorage.getItem(this.getKey(e));if(null===t)return null;try{const e=JSON.parse(t);return e&&"object"==typeof e&&"value"in e&&"timestamp"in e?e.value:e}catch(t){return console.warn(`[Vircle] Failed to parse stored value for key "${e}":`,t),null}}catch(t){return console.warn(`[Vircle] Failed to get value from localStorage for key "${e}":`,t),null}}async remove(e){if(!this.isAvailable)return!1;try{const t=this.getKey(e);return!!(null!==localStorage.getItem(t))&&(localStorage.removeItem(t),!0)}catch{return!1}}async clear(){if(this.isAvailable)try{const e=Object.keys(localStorage).filter(e=>e.startsWith(this.prefix));e.forEach(e=>{try{localStorage.removeItem(e)}catch(t){console.warn(`[Vircle] Failed to remove key "${e}" during clear:`,t)}})}catch(e){console.warn("[Vircle] Failed to clear localStorage:",e)}}async has(e){if(!this.isAvailable)return!1;try{return null!==localStorage.getItem(this.getKey(e))}catch{return!1}}async size(){if(!this.isAvailable)return 0;try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).length}catch{return 0}}async keys(){if(!this.isAvailable)return[];try{return Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).map(e=>e.substring(this.prefix.length))}catch{return[]}}async clearOldItems(){try{const e=[],t=Object.keys(localStorage).filter(e=>e.startsWith(this.prefix));for(const i of t)try{const t=localStorage.getItem(i);if(t){const s=JSON.parse(t);s&&"object"==typeof s&&"timestamp"in s&&e.push({key:i,timestamp:s.timestamp||0})}}catch{}e.sort((e,t)=>e.timestamp-t.timestamp);const i=Math.max(1,Math.floor(.2*e.length));for(let t=0;t<i&&t<e.length;t++)localStorage.removeItem(e[t].key)}catch(e){console.error("[Vircle] LocalStorage 정리 중 오류:",e)}}async setWithTimestamp(e,t){await this.set(e,t)}}class Se{constructor(e="vircle_"){this.db=null,this.storeName="vircle_store",this.dbVersion=1,this.initPromise=null,this.isClosed=!1,this.prefix=e,this.dbName=`${e}db`}async init(){if(this.isClosed)throw new ve("IndexedDB adapter가 이미 닫혔습니다");if(this.initPromise)return this.initPromise;if(this.db)return Promise.resolve();this.initPromise=this.openDB();try{await this.initPromise}catch(e){throw this.initPromise=null,e}return this.initPromise}async openDB(){return new Promise((e,t)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{t(new ve("IndexedDB 열기 실패",{error:i.error?.message}))},i.onsuccess=()=>{this.db=i.result,e()},i.onupgradeneeded=e=>{const t=e.target.result;if(!t.objectStoreNames.contains(this.storeName)){t.createObjectStore(this.storeName,{keyPath:"key"}).createIndex("timestamp","timestamp",{unique:!1})}}})}getKey(e){return`${this.prefix}${e}`}async set(e,t){return await this.init(),new Promise((i,s)=>{if(!this.db)return void s(new ve("IndexedDB가 초기화되지 않음"));const n=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),r={key:this.getKey(e),value:t,timestamp:Date.now()},o=n.put(r);o.onerror=()=>{s(new ve("IndexedDB 저장 실패",{key:e,error:o.error?.message}))},o.onsuccess=()=>{i()}})}async get(e){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new ve("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).get(this.getKey(e));s.onerror=()=>{i(new ve("IndexedDB 읽기 실패",{key:e,error:s.error?.message}))},s.onsuccess=()=>{const e=s.result;t(e&&"value"in e?e.value:null)}})}async remove(e){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new ve("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).delete(this.getKey(e));s.onerror=()=>{i(new ve("IndexedDB 삭제 실패",{key:e,error:s.error?.message}))},s.onsuccess=()=>{t(!0)}})}async clear(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new ve("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),s=i.openCursor(),n=[];s.onsuccess=()=>{const r=s.result;if(r)r.key.toString().startsWith(this.prefix)&&n.push(r.key),r.continue();else{const s=n.map(e=>new Promise((t,s)=>{const n=i.delete(e);n.onsuccess=()=>t(),n.onerror=()=>s(n.error)}));Promise.all(s).then(()=>e()).catch(e=>t(new ve("일부 항목 삭제 실패",{error:e})))}},s.onerror=()=>{t(new ve("IndexedDB 커서 열기 실패",{error:s.error?.message}))}})}async has(e){return null!==await this.get(e)}async size(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new ve("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor();let s=0;i.onsuccess=()=>{const t=i.result;t?(t.key.toString().startsWith(this.prefix)&&s++,t.continue()):e(s)},i.onerror=()=>{t(new ve("IndexedDB 카운트 실패",{error:i.error?.message}))}})}async keys(){return await this.init(),new Promise((e,t)=>{if(!this.db)return void t(new ve("IndexedDB가 초기화되지 않음"));const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).openCursor(),s=[];i.onsuccess=()=>{const t=i.result;if(t){const e=t.key.toString();e.startsWith(this.prefix)&&s.push(e.substring(this.prefix.length)),t.continue()}else e(s)},i.onerror=()=>{t(new ve("IndexedDB 키 조회 실패",{error:i.error?.message}))}})}async clearOldItems(e=.2){return await this.init(),new Promise((t,i)=>{if(!this.db)return void i(new ve("IndexedDB가 초기화되지 않음"));const s=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),n=s.index("timestamp").openCursor(),r=[];n.onsuccess=async()=>{const o=n.result;if(o){const e=o.primaryKey;e.startsWith(this.prefix)&&r.push({key:e,timestamp:o.value.timestamp}),o.continue()}else{r.sort((e,t)=>e.timestamp-t.timestamp);const n=Math.max(1,Math.floor(r.length*e)),o=r.slice(0,n).map(e=>e.key).map(e=>new Promise((t,i)=>{const n=s.delete(e);n.onsuccess=()=>t(),n.onerror=()=>i(n.error)}));Promise.all(o).then(()=>t()).catch(e=>i(new ve("일부 항목 삭제 실패",{error:e})))}},n.onerror=()=>{i(new ve("IndexedDB 인덱스 조회 실패",{error:n.error?.message}))}})}async close(){this.isClosed=!0,this.db&&(this.db.close(),this.db=null),this.initPromise=null}}class Ee{static create(e="vircle_",t="auto"){switch(t){case"localStorage":return new be(e);case"indexedDB":return new Se(e);default:return this.createAuto(e)}}static async createAsync(e="vircle_",t="auto"){switch(t){case"localStorage":return new be(e);case"indexedDB":return new Se(e);default:return this.createAutoAsync(e)}}static async createAutoAsync(e){return await this.isIndexedDBAvailableAsync()?new Se(e):new be(e)}static createAuto(e){if(this.isIndexedDBAvailable())try{return new Se(e)}catch(e){console.warn("[Vircle] IndexedDB 초기화 실패, LocalStorage로 폴백합니다:",e)}return new be(e)}static isIndexedDBAvailable(){try{return"undefined"!=typeof window&&!!window.indexedDB}catch{return!1}}static async isIndexedDBAvailableAsync(){return!("undefined"==typeof window||!window.indexedDB)&&new Promise(e=>{try{const t=indexedDB.open("vircle_availability_test");t.onsuccess=()=>{t.result.close(),indexedDB.deleteDatabase("vircle_availability_test"),e(!0)},t.onerror=()=>{e(!1)},t.onblocked=()=>{e(!1)}}catch{e(!1)}})}static isLocalStorageAvailable(){try{const e="__vircle_test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}}class Ie{constructor(){this.crypto=null,this.subtle=null,this.available=!1,this.initCrypto()}initCrypto(){try{"undefined"!=typeof window&&window.crypto&&window.crypto.subtle?(this.crypto=window.crypto,this.subtle=window.crypto.subtle,this.available=!0):"undefined"!=typeof globalThis&&globalThis.crypto&&globalThis.crypto.subtle&&(this.crypto=globalThis.crypto,this.subtle=globalThis.crypto.subtle,this.available=!0)}catch(e){console.warn("[Vircle] Web Crypto API를 사용할 수 없습니다:",e),this.available=!1}}generateUUID(){if(this.crypto&&"function"==typeof this.crypto.randomUUID)return this.crypto.randomUUID();if(this.crypto){const e=new Uint8Array(16);this.crypto.getRandomValues(e),e[6]=15&e[6]|64,e[8]=63&e[8]|128;const t=Array.from(e).map(e=>e.toString(16).padStart(2,"0")).join("");return[t.substring(0,8),t.substring(8,12),t.substring(12,16),t.substring(16,20),t.substring(20,32)].join("-")}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}async createHmacSignature(e,t){if(!this.subtle)throw new Error("Web Crypto API is required for HMAC operations");const i=new TextEncoder,s=JSON.stringify(e),n=i.encode(t),r=await this.subtle.importKey("raw",n,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await this.subtle.sign("HMAC",r,i.encode(s));return this.arrayBufferToHex(o)}async encryptPayload(e,t){if(!this.subtle||!this.crypto)throw new Error("Web Crypto API is required for encryption operations");let i="initialization";try{i="JSON serialization";const s=JSON.stringify(e),n=(new TextEncoder).encode(s);i="AES key generation";const r=await this.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt"]);i="IV generation";const o=this.crypto.getRandomValues(new Uint8Array(12));i="AES-GCM encryption";const a=await this.subtle.encrypt({name:"AES-GCM",iv:o,tagLength:128},r,n),c=new Uint8Array(a),l=c.slice(0,-16),u=c.slice(-16);i="AES key export";const h=await this.subtle.exportKey("raw",r);i="RSA public key import";const d=await this.importRsaPublicKey(t);i="RSA-OAEP encryption";const p=await this.subtle.encrypt({name:"RSA-OAEP"},d,h);return i="Base64 encoding",{data:this.arrayBufferToBase64(l),key:this.arrayBufferToBase64(p),iv:this.arrayBufferToBase64(o),authTag:this.arrayBufferToBase64(u),metadata:{algorithm:"AES-256-GCM",keyAlgorithm:"RSA-OAEP",timestamp:(new Date).toISOString()}}}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`[WebExtendedCryptoAdapter] Encryption failed at step '${i}': ${t}`)}}async sha256(e){if(!this.subtle)throw new Error("Web Crypto API is required for SHA-256 hashing");const t=new TextEncoder,i=await this.subtle.digest("SHA-256",t.encode(e));return this.arrayBufferToHex(i)}isAvailable(){return this.available}async importRsaPublicKey(e){if(!this.subtle)throw new Error("Web Crypto API is not available");const t=e.replace(/-----BEGIN PUBLIC KEY-----/g,"").replace(/-----END PUBLIC KEY-----/g,"").replace(/-----BEGIN RSA PUBLIC KEY-----/g,"").replace(/-----END RSA PUBLIC KEY-----/g,"").replace(/\s/g,""),i=this.base64ToArrayBuffer(t);return await this.subtle.importKey("spki",i,{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"])}arrayBufferToBase64(e){const t=e instanceof Uint8Array?e:new Uint8Array(e);let i="";for(let e=0;e<t.length;e+=32768){const s=t.slice(e,Math.min(e+32768,t.length));i+=String.fromCharCode.apply(null,Array.from(s))}return btoa(i)}base64ToArrayBuffer(e){const t=atob(e),i=new Uint8Array(t.length);for(let e=0;e<t.length;e++)i[e]=t.charCodeAt(e);return i.buffer}arrayBufferToHex(e){const t=new Uint8Array(e);return Array.from(t).map(e=>e.toString(16).padStart(2,"0")).join("")}}class xe{constructor(e){this.allowedDomains=(e.allowedDomains??[]).map(e=>e.toLowerCase()),this.paramName=e.paramName??"_vuid",this.getAnonymousId=e.getAnonymousId}start(){"undefined"!=typeof document&&0!==this.allowedDomains.length&&(this.clickHandler||(this.clickHandler=this.handleClick.bind(this),document.addEventListener("mousedown",this.clickHandler,{capture:!0}),document.addEventListener("click",this.clickHandler,{capture:!0}),document.addEventListener("auxclick",this.clickHandler,{capture:!0})))}stop(){"undefined"!=typeof document&&this.clickHandler&&(document.removeEventListener("mousedown",this.clickHandler,{capture:!0}),document.removeEventListener("click",this.clickHandler,{capture:!0}),document.removeEventListener("auxclick",this.clickHandler,{capture:!0}),this.clickHandler=void 0)}decorate(e){const t=this.getAnonymousId();if(!t)return e;let i;try{i=new URL(e,"undefined"!=typeof location?location.href:"http://localhost")}catch{return e}return"http:"!==i.protocol&&"https:"!==i.protocol?e:this.isAllowedDomain(i.hostname)?"undefined"!=typeof location&&i.origin===location.origin||i.searchParams.get(this.paramName)?e:(i.searchParams.set(this.paramName,t),i.toString()):e}handleClick(e){const t=e.target;if(!t||"function"!=typeof t.closest)return;const i=t.closest("a[href]");if(!i)return;const s=i.getAttribute("href");if(!s)return;if(/^(mailto:|javascript:|tel:|sms:|#)/i.test(s))return;const n=this.decorate(s);n!==s&&i.setAttribute("href",n)}isAllowedDomain(e){const t=e.toLowerCase();for(const e of this.allowedDomains)if(e.startsWith(".")){if(t===e.slice(1)||t.endsWith(e))return!0}else if(t===e)return!0;return!1}}class Ae extends ue{constructor(e,t={}){const i=Ee.create(e.storagePrefix||"vircle_",e.storageType||"auto");let s;(e.enableEncryption||t.enableEncryption)&&(s=new Ie,s.isAvailable()||(console.warn("[Vircle] Web Crypto API를 사용할 수 없습니다. 암호화를 비활성화합니다."),s=void 0));super(e,{...t,storageAdapter:i,cryptoAdapter:s,enableEncryption:s?.isAvailable()??!1}),this.pageViewTracked=!1,this.lastActivityTime=Date.now(),this.webConfig=e,this.webOptions={flushOnUnload:!0,contextCacheTime:3e5,idleScheduler:new se,...t},this.contextCollector=new ge,this.sessionTimeout=e.sessionTimeout??18e5}async initialize(){try{await super.initialize(),this.applyUrlVuid(),this.setupAutoTracking();const e=await this.contextCollector.collect();this.setContext(e),this.webConfig.trackPageViews&&!this.pageViewTracked&&(await this.trackPageView(),this.pageViewTracked=!0)}catch(e){throw console.error("[Vircle] 초기화 실패:",e),e}}applyUrlVuid(){try{const e=new URLSearchParams(window.location.search).get("_vuid");e&&this.setAnonymousId(e)}catch{}}async identify(e,t){return this.contextCache.invalidate(),super.identify(e,t)}async trackPageView(e,t){const i=await this.contextCollector.collectPageContext();return this.track("page_view",{...i,...e},t)}async track(e,t,i){return this.lastActivityTime=Date.now(),new Promise(s=>{this.taskScheduler.enqueue(async()=>{try{const n={...await this.getCachedContext(),...i};await super.track(e,t,n),s()}catch(t){console.warn(`[Vircle] 이벤트 추적 실패 "${e}":`,t),s()}})})}async getCachedContext(){return this.contextCache.getOrCollect(()=>this.contextCollector.collect())}setupAutoTracking(){this.webOptions.flushOnUnload&&(this.unloadHandler=()=>{this.transportService.flushWithKeepalive()},window.addEventListener("beforeunload",this.unloadHandler),this.visibilityChangeHandler=()=>{"hidden"===document.visibilityState?this.transportService.flushWithKeepalive():"visible"===document.visibilityState&&this.checkSessionTimeout()},document.addEventListener("visibilitychange",this.visibilityChangeHandler)),this.webConfig.trackErrors&&this.setupErrorTracking(),this.webConfig.trackClicks&&this.setupClickTracking(),this.webConfig.trackForms&&this.setupFormTracking(),this.webConfig.singlePageApp&&this.setupSPATracking(),this.webConfig.linkDecoration?.enabled&&this.setupLinkDecoration()}setupLinkDecoration(){const e=this.webConfig.linkDecoration;if(!e?.enabled)return;const t=e.allowedDomains??[];0!==t.length?(this.linkDecorator=new xe({allowedDomains:t,paramName:e.paramName,getAnonymousId:()=>this.getAnonymousId()}),this.linkDecorator.start()):console.warn("[Vircle] linkDecoration.enabled=true이지만 allowedDomains가 비어 있어 활성화되지 않습니다. vuid 누출 방지를 위해 도메인 화이트리스트를 명시하세요.")}setupErrorTracking(){this.errorHandler=e=>{this.track("error",{message:e.message,source:e.filename,line:e.lineno,column:e.colno,stack:e.error?.stack}).catch(e=>{console.warn("[Vircle] 에러 추적 실패:",e)})},this.unhandledRejectionHandler=e=>{this.track("unhandled_rejection",{reason:e.reason?.toString(),promise:e.promise?.toString()}).catch(e=>{console.warn("[Vircle] Promise rejection 추적 실패:",e)})},window.addEventListener("error",this.errorHandler),window.addEventListener("unhandledrejection",this.unhandledRejectionHandler)}setupClickTracking(){this.clickHandler=e=>{const t=e.target;if(!this.shouldTrackElement(t))return;const i=this.extractElementProperties(t);this.track("element_clicked",i).catch(e=>{console.warn("[Vircle] 클릭 추적 실패:",e)})},document.addEventListener("click",this.clickHandler,!0)}setupFormTracking(){this.submitHandler=e=>{const t=e.target,i={form_id:t.id,form_name:t.name,form_action:t.action,form_method:t.method};this.track("form_submitted",i).catch(e=>{console.warn("[Vircle] 폼 제출 추적 실패:",e)})},document.addEventListener("submit",this.submitHandler,!0)}setupSPATracking(){this.originalPushState=history.pushState,this.originalReplaceState=history.replaceState;const e=(...e)=>{this.originalPushState.apply(history,e);try{this.handleRouteChange()}catch(e){}};e.__vircle_wrapped=!0,history.pushState=e;const t=(...e)=>{this.originalReplaceState.apply(history,e);try{this.handleRouteChange()}catch(e){}};t.__vircle_wrapped=!0,history.replaceState=t,this.popstateHandler=()=>{this.handleRouteChange()},window.addEventListener("popstate",this.popstateHandler)}handleRouteChange(){this.contextCache.invalidate(),this.webConfig.trackPageViews&&this.trackPageView().catch(e=>{console.warn("[Vircle] 라우트 변경 추적 실패:",e)})}checkSessionTimeout(){const e=Date.now(),t=e-this.lastActivityTime;if(t>=this.sessionTimeout){const i=`sess_${e}_${Math.random().toString(36).substr(2,9)}`;this.setSessionId(i),this.lastActivityTime=e,this.contextCache.invalidate(),this.track("session_start",{reason:"timeout",previous_session_duration:t}).catch(e=>{console.warn("[Vircle] 세션 시작 추적 실패:",e)})}else this.lastActivityTime=e}shouldTrackElement(e){if(e.hasAttribute("data-vircle-ignore"))return!1;let t=e.parentElement;for(;t;){if(t.hasAttribute("data-vircle-ignore"))return!1;t=t.parentElement}return["A","BUTTON","INPUT","SELECT","TEXTAREA"].includes(e.tagName)}extractElementProperties(e){const t={tag_name:e.tagName.toLowerCase(),element_id:e.id||void 0,element_class:e.className||void 0,element_href:e.href||void 0,element_text:e.textContent?.slice(0,100)||void 0};return this.taskScheduler.enqueue(()=>{const i={};Array.from(e.attributes).forEach(e=>{e.name.startsWith("data-")&&!e.name.startsWith("data-vircle-")&&(i[e.name]=e.value)}),Object.keys(i).length>0&&this.track("element_data_collected",{...t,data_attributes:i}).catch(()=>{})}),t}async cleanup(){try{this.unloadHandler&&window.removeEventListener("beforeunload",this.unloadHandler),this.errorHandler&&window.removeEventListener("error",this.errorHandler),this.unhandledRejectionHandler&&window.removeEventListener("unhandledrejection",this.unhandledRejectionHandler),this.clickHandler&&document.removeEventListener("click",this.clickHandler,!0),this.submitHandler&&document.removeEventListener("submit",this.submitHandler,!0),this.visibilityChangeHandler&&document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=void 0),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=void 0),this.linkDecorator&&(this.linkDecorator.stop(),this.linkDecorator=void 0),await this.flush(),await super.cleanup()}catch(e){throw console.error("[Vircle] 정리 중 오류:",e),e}}getCurrentUrl(){return window.location.href}isOnline(){return navigator.onLine}}var Ce="undefined"!=typeof fetch?fetch:()=>{throw new Error("Fetch API is not available")};const Re=window.Headers,ke=window.Request,_e=window.Response;var Pe=Object.freeze({__proto__:null,Headers:Re,Request:ke,Response:_e,default:Ce});export{Se as IndexedDBAdapter,xe as LinkDecorator,be as LocalStorageAdapter,Ee as StorageFactory,we as VircleBrowserCompatibilityError,fe as VircleConfigError,ye as VircleInitializationError,ve as VircleStorageError,Ae as VircleWeb,me as VircleWebError,ge as WebContextCollector,Ie as WebExtendedCryptoAdapter,Ae as default};
|
|
2
2
|
//# sourceMappingURL=vircle-web-sdk.standalone.esm.js.map
|