sitepong 0.1.11 → 0.1.13
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 +21 -17
- package/dist/cdn/sitepong.min.js +1 -1
- package/dist/cdn/sitepong.min.js.map +1 -1
- package/dist/entries/rn.js +23 -89
- package/dist/entries/rn.js.map +1 -1
- package/dist/entries/web.js +8 -5
- package/dist/entries/web.js.map +1 -1
- package/dist/entries/web.mjs +8 -5
- package/dist/entries/web.mjs.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -4
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +7 -4
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +7 -4
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -602,7 +602,7 @@ Native APNs (iOS) and FCM (Android) push notifications, plus iOS Live Activity u
|
|
|
602
602
|
|
|
603
603
|
#### Token lifecycle
|
|
604
604
|
|
|
605
|
-
There are two halves to push: the **client SDK** registers device tokens with the SitePong ingest server, and the **server-side Push API** sends notifications to
|
|
605
|
+
There are two halves to push: the **client SDK** registers device tokens with the SitePong ingest server, and the **server-side Push API** sends notifications and binds tokens to authenticated users.
|
|
606
606
|
|
|
607
607
|
```
|
|
608
608
|
[App launches]
|
|
@@ -611,15 +611,19 @@ There are two halves to push: the **client SDK** registers device tokens with th
|
|
|
611
611
|
↓
|
|
612
612
|
[registerDeviceToken(token, opts)] ← SDK POSTs to /api/push/tokens
|
|
613
613
|
↓ with X-API-Key: sp_live_xxx
|
|
614
|
-
[Token stored in SitePong]
|
|
614
|
+
[Token stored anonymously in SitePong]
|
|
615
615
|
↓
|
|
616
|
-
[
|
|
617
|
-
↓
|
|
618
|
-
[Your backend → POST /api/push/
|
|
616
|
+
[User logs in with your backend]
|
|
617
|
+
↓
|
|
618
|
+
[Your backend → POST /api/push/tokens/associate] ← sp_push_xxx + { token, user_id }
|
|
619
|
+
↓
|
|
620
|
+
[Your backend → POST /api/push/send] ← sp_push_xxx + target user_ids
|
|
619
621
|
↓
|
|
620
622
|
[SitePong → APNs / FCM → Device]
|
|
621
623
|
```
|
|
622
624
|
|
|
625
|
+
> **Why two steps?** Publishable SDK keys (`sp_live_xxx`) are embedded in your app binary and can be extracted by anyone who decompiles the APK/IPA. If the client controlled `user_id`, a leaked SDK key would let an attacker register their own device under your users' IDs and silently receive their push notifications (password resets, OTP codes, order details). User attribution therefore only happens server-to-server with the privileged `sp_push_xxx` key — which stays on your backend.
|
|
626
|
+
|
|
623
627
|
#### 1. Install permission and get the native token
|
|
624
628
|
|
|
625
629
|
```bash
|
|
@@ -649,26 +653,25 @@ import { Platform } from 'react-native';
|
|
|
649
653
|
registerDeviceToken(token, {
|
|
650
654
|
platform: Platform.OS as 'ios' | 'android',
|
|
651
655
|
environment: __DEV__ ? 'sandbox' : 'production',
|
|
652
|
-
userId: 'user-123', // optional — can be set later via identify()
|
|
653
656
|
});
|
|
654
657
|
```
|
|
655
658
|
|
|
656
|
-
This makes a `POST /api/push/tokens` request to the ingest server with `X-API-Key: <your SDK key>`. The body includes the token, `token_type` (`apns`/`fcm`), `device_id`, `
|
|
659
|
+
This makes a `POST /api/push/tokens` request to the ingest server with `X-API-Key: <your SDK key>`. The body includes the token, `token_type` (`apns`/`fcm`), `device_id`, `platform`, app version, device model, and OS version — no `user_id`. The server upserts by `(project_id, token)` so re-registration is idempotent.
|
|
657
660
|
|
|
658
|
-
#### 3.
|
|
661
|
+
#### 3. Associate the token with a user (server-side)
|
|
659
662
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
```typescript
|
|
663
|
-
import { identify } from '@sitepong/sdk/react-native';
|
|
663
|
+
Once your own backend has authenticated the user, have it POST to SitePong's associate endpoint with your `sp_push_xxx` key. Your app should forward the push token to your backend as part of the login flow.
|
|
664
664
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
665
|
+
```bash
|
|
666
|
+
curl -X POST https://api.sitepong.com/api/push/tokens/associate \
|
|
667
|
+
-H "Authorization: Bearer sp_push_xxxxxxxxxxxxxxxx" \
|
|
668
|
+
-H "Content-Type: application/json" \
|
|
669
|
+
-d '{ "token": "<expo_or_native_token>", "user_id": "user-123" }'
|
|
669
670
|
```
|
|
670
671
|
|
|
671
|
-
|
|
672
|
+
On sign-out, POST the same endpoint with `"user_id": null` to clear the association. Because this call is server-authenticated, an attacker who has scraped the SDK key out of your app cannot impersonate a user.
|
|
673
|
+
|
|
674
|
+
> The older pattern of passing `userId` to `registerDeviceToken()` or `pushUserId` to `SitePongRNProvider` still type-checks for backwards compatibility, but the values are silently ignored on both the client and the server. Migrate to the associate endpoint.
|
|
672
675
|
|
|
673
676
|
#### 4. Send notifications from your backend
|
|
674
677
|
|
|
@@ -794,6 +797,7 @@ When APNs or FCM reports a token as invalid (app uninstalled, notifications disa
|
|
|
794
797
|
| POST | `/api/push/live-activity-tokens` | `X-API-Key: sp_live_*` | `registerLiveActivityToken()` |
|
|
795
798
|
| POST | `/api/push/push-to-start-tokens` | `X-API-Key: sp_live_*` | `registerPushToStartToken()` |
|
|
796
799
|
| DELETE | `/api/push/live-activity-tokens` | `X-API-Key: sp_live_*` | `endLiveActivity()` |
|
|
800
|
+
| POST | `/api/push/tokens/associate` | `Authorization: Bearer sp_push_*` | (server-side only) |
|
|
797
801
|
| POST | `/api/push/send` | `Authorization: Bearer sp_push_*` | (server-side only) |
|
|
798
802
|
| POST | `/api/push/live-activity` | `Authorization: Bearer sp_push_*` | (server-side only) |
|
|
799
803
|
|
package/dist/cdn/sitepong.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var SitePong=(function(exports){'use strict';function lt(){try{return typeof localStorage>"u"?null:{getItem:async r=>localStorage.getItem(r),setItem:async(r,e)=>{localStorage.setItem(r,e);},removeItem:async r=>{localStorage.removeItem(r);}}}catch{return null}}function Me(){return {platform:"browser",storage:lt(),getDeviceInfo(){let e={platform:"browser"};return typeof navigator<"u"&&(e.userAgent=navigator.userAgent),typeof window<"u"&&window.screen&&(e.screenWidth=window.screen.width,e.screenHeight=window.screen.height),e},getCurrentUrl(){if(!(typeof window>"u"||!window.location))return window.location.href},getReferrer(){if(!(typeof document>"u"))return document.referrer||void 0},getUserAgent(){if(!(typeof navigator>"u"))return navigator.userAgent},onUncaughtError(e){if(typeof window>"u"||!window.addEventListener)return ()=>{};let t=n=>{e(n.error||n.message);};return window.addEventListener("error",t),()=>window.removeEventListener("error",t)},onUnhandledRejection(e){if(typeof window>"u"||!window.addEventListener)return ()=>{};let t=n=>{e(n.reason);};return window.addEventListener("unhandledrejection",t),()=>window.removeEventListener("unhandledrejection",t)},onBeforeTerminate(e){return typeof window>"u"||!window.addEventListener?()=>{}:(window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e))},onVisibilityHidden(e){if(typeof document>"u"||!document.addEventListener)return ()=>{};let t=()=>{document.visibilityState==="hidden"&&e();};return document.addEventListener("visibilitychange",t),()=>document.removeEventListener("visibilitychange",t)},sendBeacon(e,t){if(typeof navigator>"u"||typeof navigator.sendBeacon!="function")return false;try{let n=new Blob([t],{type:"application/json"});return navigator.sendBeacon(e,n)}catch{return false}}}}var T=null;function A(r){T=r;}function b(){return T}function ae(){if(T)return T.platform;let r=globalThis;return r.navigator&&r.navigator.product==="ReactNative"?"react-native":r.process&&r.process.versions&&r.process.versions.node?"node":r.window&&r.document?"browser":"unknown"}function M(){return ae()==="react-native"}var ut=null;function dt(){return T&&T.platform==="react-native"?T:null}function ce(r){let e=dt();e&&e._setGetCurrentScreen(r);}function X(){return ut}function le(){return T?T.storage:null}var j="sitepong_anonymous_id";function ue(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}var x=null;function R(){if(typeof window<"u"&&typeof localStorage<"u")try{let r=localStorage.getItem(j);return r||(r=ue(),localStorage.setItem(j,r)),r}catch{return x||(x=ue()),x}return x||(x=ue()),x}function Re(){if(typeof window<"u"&&typeof localStorage<"u")try{localStorage.removeItem(j);}catch{}x=null;}function Ie(r){if(typeof window<"u"&&typeof localStorage<"u")try{localStorage.setItem(j,r);}catch{x=r;}else x=r;}function Pe(r){let e=r.toLowerCase();return /ipad/.test(e)||/android/.test(e)&&!/mobile/.test(e)||/tablet/.test(e)?"tablet":/mobile/.test(e)||/iphone/.test(e)||/ipod/.test(e)||/android/.test(e)||/blackberry/.test(e)||/windows phone/.test(e)?"mobile":"desktop"}function Fe(r){let e=r.toLowerCase();return /edg/.test(e)?"edge":/opr|opera/.test(e)?"opera":/samsungbrowser/.test(e)?"samsung":/chrome|chromium|crios/.test(e)?"chrome":/safari/.test(e)&&!/chrome/.test(e)?"safari":/firefox|fxios/.test(e)?"firefox":/msie|trident/.test(e)?"ie":"other"}function De(r){let e=r.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/mac os|macos|macintosh/.test(e)?"macos":/windows/.test(e)?"windows":/linux/.test(e)?"linux":"other"}function de(){let r=b()?.getUserAgent()??"";return {anonymous_id:R(),device_type:r?Pe(r):void 0,browser:r?Fe(r):void 0,os:r?De(r):void 0,user_agent:r||void 0,timestamp:new Date}}function Ae(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e^r.charCodeAt(t);return e>>>0}function ft(r){return Math.random()*100<r.percentage}function pt(r,e,t){let n=`${e.anonymous_id}:${t}`;return Ae(n)%100<r.percentage}function Q(r){let[e,t]=r.split(":").map(Number);return e*60+t}function gt(r,e){let t=e.timestamp||new Date,i=new Intl.DateTimeFormat("en-US",{timeZone:r.timezone,weekday:"short",hour:"2-digit",minute:"2-digit",hour12:false}).formatToParts(t),o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].indexOf(i.find(d=>d.type==="weekday")?.value||""),s=parseInt(i.find(d=>d.type==="hour")?.value||"0",10),c=parseInt(i.find(d=>d.type==="minute")?.value||"0",10),l=s*60+c;if(r.days_of_week&&r.days_of_week.length>0&&!r.days_of_week.includes(o))return false;if(r.start_time&&r.end_time){let d=Q(r.start_time),f=Q(r.end_time);if(d>f){if(l<d&&l>=f)return false}else if(l<d||l>=f)return false}else if(r.start_time){let d=Q(r.start_time);if(l<d)return false}else if(r.end_time){let d=Q(r.end_time);if(l>=d)return false}return true}function ht(r,e){return e.device_type?r.types.includes(e.device_type):false}function mt(r,e){return e.browser?r.browsers.includes(e.browser):false}function vt(r,e){return e.os?r.operating_systems.includes(e.os):false}function yt(r,e,t,n){switch(r){case "percentage_rollout":return ft(e);case "userbase_percentage":return pt(e,t,n);case "time_based":return gt(e,t);case "device_type":return ht(e,t);case "browser":return mt(e,t);case "os":return vt(e,t);default:return false}}function Y(r,e){if(r.override==="force_on")return true;if(r.override==="force_off"||!r.enabled)return false;if(!r.rules||r.rules.length===0)return true;for(let t of r.rules)if(!yt(t.rule_type,t.config,e,r.key))return false;return true}function _e(r,e){if(!Y(r,e)||r.flag_type!=="multivariate"||!r.variants||r.variants.length===0)return null;let t=`${e.anonymous_id}:${r.key}:variant`,n=Ae(t),i=r.variants.reduce((c,l)=>c+l.weight,0),o=n%i,s=0;for(let c of r.variants)if(s+=c.weight,o<s)return c.key;return r.variants[0].key}function Le(r,e){return r.variant_payloads&&r.variant_payloads[e]!==void 0?r.variant_payloads[e]:r.variants?.find(n=>n.key===e)?.payload||null}var bt="https://api.sitepong.com",I=class{constructor(e){this.flags=new Map;this.evaluatedFlags=new Map;this.evaluatedVariants=new Map;this.context=null;this.initialized=false;this.initPromise=null;this.config={endpoint:bt,debug:false,...e};}async init(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.fetchAndEvaluateFlags();try{await this.initPromise,this.initialized=!0;}catch(e){this.log("Failed to initialize flags:",e),this.initialized=true;}finally{this.initPromise=null;}}}async fetchAndEvaluateFlags(){try{let e=await fetch(`${this.config.endpoint}/api/sdk/flags`,{method:"GET",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey}});if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);let t=await e.json();this.log("Fetched flags:",t.flags.length),this.context=de(),this.log("Evaluation context:",this.context),this.flags.clear(),this.evaluatedFlags.clear(),this.evaluatedVariants.clear();for(let n of t.flags){this.flags.set(n.key,n);let i=Y(n,this.context);if(this.evaluatedFlags.set(n.key,i),n.flag_type==="multivariate"&&n.variants){let o=_e(n,this.context);this.evaluatedVariants.set(n.key,o),this.log(`Flag "${n.key}": ${i}, variant: ${o}`);}else this.log(`Flag "${n.key}": ${i}`);}}catch(e){throw this.log("Error fetching flags:",e),e}}getFlag(e,t=false){if(!this.initialized)return this.log(`Flag "${e}" requested before init, returning default:`,t),t;let n=this.evaluatedFlags.get(e);return n===void 0?(this.log(`Flag "${e}" not found, returning default:`,t),t):n}getVariant(e,t=null){if(!this.initialized)return this.log(`Variant "${e}" requested before init, returning default:`,t),t;let n=this.evaluatedVariants.get(e);return n===void 0?(this.log(`Variant "${e}" not found, returning default:`,t),t):n}getVariantPayload(e,t=null){let n=this.getVariant(e);if(!n)return t;let i=this.flags.get(e);return i?Le(i,n)??t:t}getAllFlags(){let e={};for(let[t,n]of this.evaluatedFlags)e[t]=n;return e}hasFlag(e){return this.flags.has(e)}isInitialized(){return this.initialized}async waitForInit(){this.initialized||await this.init();}async refresh(){this.initialized=false,await this.init();}getContext(){return this.context}log(...e){this.config.debug&&console.log("[SitePong Flags]",...e);}};var fe="sitepong_session_id",J="sitepong_session_ts";var _=null,L=null;function Oe(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}function He(r){return Date.now()-r>18e5}function pe(){if(typeof window<"u"&&typeof sessionStorage<"u")try{let r=sessionStorage.getItem(fe),e=sessionStorage.getItem(J);if(r&&e&&!He(parseInt(e,10)))return sessionStorage.setItem(J,String(Date.now())),r;let t=Oe();return sessionStorage.setItem(fe,t),sessionStorage.setItem(J,String(Date.now())),t}catch{return Ne()}return Ne()}function Ne(){return _&&L&&!He(L)?(L=Date.now(),_):(_=Oe(),L=Date.now(),_)}function ge(){if(typeof window<"u"&&typeof sessionStorage<"u")try{sessionStorage.removeItem(fe),sessionStorage.removeItem(J);}catch{}_=null,L=null;}var Be=["[data-sp-no-capture]",".sp-no-capture"];var N=class{constructor(e,t){this.clickHandler=null;this.submitHandler=null;this.active=false;this.config={clicks:true,forms:true,pageviews:true,blockSelectors:Be,maxTextLength:255,debug:false,...e},this.callback=t;}start(){this.active||typeof document>"u"||typeof document.addEventListener!="function"||(this.active=true,this.config.clicks&&this.setupClickCapture(),this.config.forms&&this.setupFormCapture(),this.log("Autocapture started"));}stop(){this.active&&(this.active=false,this.clickHandler&&(document.removeEventListener("click",this.clickHandler,true),this.clickHandler=null),this.submitHandler&&(document.removeEventListener("submit",this.submitHandler,true),this.submitHandler=null),this.log("Autocapture stopped"));}setupClickCapture(){this.clickHandler=e=>{let t=e.target;if(!t||!this.shouldCapture(t))return;let n=this.getElementProperties(t);n.$event_type="click",n.$x=e.clientX,n.$y=e.clientY,this.callback({type:"click",timestamp:new Date().toISOString(),properties:n});},document.addEventListener("click",this.clickHandler,true);}setupFormCapture(){this.submitHandler=e=>{let t=e.target;if(!t||!this.shouldCapture(t))return;let n={$event_type:"form_submit",$form_action:t.action||void 0,$form_method:t.method||"get",$form_name:t.name||t.id||void 0,$field_names:this.getFormFieldNames(t),$field_count:t.elements.length},i=this.getElementProperties(t);Object.assign(n,i),this.callback({type:"form_submit",timestamp:new Date().toISOString(),properties:n});},document.addEventListener("submit",this.submitHandler,true);}shouldCapture(e){let t=this.config.blockSelectors||Be;for(let n of t)if(e.matches(n)||e.closest(n))return false;return !(this.config.allowSelectors&&this.config.allowSelectors.length>0&&!this.config.allowSelectors.some(i=>e.matches(i)||e.closest(i)!==null)||e.offsetParent===null&&e.tagName!=="BODY")}getElementProperties(e){let t={};t.$tag_name=e.tagName.toLowerCase(),t.$el_id=e.id||void 0,e.classList.length>0&&(t.$el_classes=Array.from(e.classList).slice(0,5));let n=this.getElementText(e);n&&(t.$el_text=n),e instanceof HTMLAnchorElement&&(t.$href=e.href||void 0,t.$target=e.target||void 0),(e instanceof HTMLInputElement||e instanceof HTMLButtonElement)&&(t.$el_type=e.type||void 0,t.$el_name=e.name||void 0);let i=e.getAttribute("aria-label");i&&(t.$aria_label=this.truncate(i));let o=e.getAttribute("role");return o&&(t.$el_role=o),t.$selector=this.getSelector(e),t.$current_url=window.location.href,t.$pathname=window.location.pathname,t}getElementText(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)return;let t="";if(e instanceof HTMLButtonElement||e instanceof HTMLAnchorElement)t=e.innerText||e.textContent||"";else for(let n of Array.from(e.childNodes))n.nodeType===Node.TEXT_NODE&&(t+=n.textContent||"");return t=t.trim().replace(/\s+/g," "),t?this.truncate(t):void 0}getFormFieldNames(e){let t=[];for(let n of Array.from(e.elements)){let i=n;i.name&&i.type!=="password"&&i.type!=="hidden"&&t.push(i.name);}return t.slice(0,20)}getSelector(e){let t=[],n=e,i=0;for(;n&&n!==document.body&&i<5;){let o=n.tagName.toLowerCase();if(n.id){o=`#${n.id}`,t.unshift(o);break}n.classList.length>0&&(o+=`.${Array.from(n.classList).slice(0,2).join(".")}`);let s=n.parentElement;if(s){let c=Array.from(s.children).filter(l=>l.tagName===n.tagName);if(c.length>1){let l=c.indexOf(n)+1;o+=`:nth-of-type(${l})`;}}t.unshift(o),n=n.parentElement,i++;}return t.join(" > ")}truncate(e){let t=this.config.maxTextLength||255;return e.length>t?e.slice(0,t)+"...":e}log(...e){this.config.debug&&console.log("[SitePong Autocapture]",...e);}};var wt="https://ingest.sitepong.com",St=20,Tt=1e4,he=3,P=class{constructor(e){this.eventQueue=[];this.flushTimer=null;this.flushFailures=0;this.disabled=false;this.userId=null;this.groupId=null;this.userTraits=null;this.groupTraits=null;this.lastUrl=null;this.popstateHandler=null;this.autocaptureModule=null;this.config={endpoint:wt,enabled:true,autocapturePageviews:false,maxBatchSize:St,flushInterval:Tt,debug:false,...e};}init(){this.config.enabled&&(this.startFlushTimer(),this.setupPageHideListener(),this.config.autocapturePageviews&&this.setupSPATracking(),this.setupAutocapture(),this.log("Analytics initialized"));}initHeadless(){this.config.enabled&&(this.startFlushTimer(),this.log("Analytics initialized (headless)"));}setupAutocapture(){let e=this.config.autocapture,t=this.config.autocaptureClicks,n=this.config.autocaptureForms,i=t||false,o=n||false,s,c;e===true?(i=true,o=true):e&&typeof e=="object"&&(i=e.clicks!==false,o=e.forms!==false,s=e.blockSelectors,c=e.allowSelectors,e.pageviews!==false&&!this.config.autocapturePageviews&&this.setupSPATracking()),!(!i&&!o)&&(this.autocaptureModule=new N({clicks:i,forms:o,pageviews:false,blockSelectors:s,allowSelectors:c,debug:this.config.debug},l=>{let d=l.type==="click"?"$autocapture_click":l.type==="form_submit"?"$autocapture_form_submit":"$autocapture";this.track(d,l.properties);}),this.autocaptureModule.start());}track(e,t){if(!this.config.enabled)return;let n=this.createEvent("track",{name:e,properties:t});this.enqueue(n),this.log("Track:",e,t);}trackPageView(e,t){if(!this.config.enabled)return;let n=e||(typeof window<"u"&&window.location?window.location.href:void 0),i=this.createEvent("page",{properties:{url:n,referrer:typeof document<"u"?document.referrer:void 0,title:typeof document<"u"?document.title:void 0,...t}});this.enqueue(i),this.log("Page view:",n);}identify(e,t){if(!this.config.enabled)return;this.userId=e,t&&(this.userTraits={...this.userTraits,...t});let n=this.createEvent("identify",{traits:this.userTraits||void 0});this.enqueue(n),this.log("Identify:",e,t);}group(e,t){if(!this.config.enabled)return;this.groupId=e,t&&(this.groupTraits={...this.groupTraits,...t});let n=this.createEvent("group",{traits:this.groupTraits||void 0});this.enqueue(n),this.log("Group:",e,t);}reset(){this.userId=null,this.groupId=null,this.userTraits=null,this.groupTraits=null,ge(),this.log("Analytics state reset");}async flush(){if(this.eventQueue.length===0)return;if(this.disabled){this.eventQueue=[];return}let e=[...this.eventQueue];this.eventQueue=[];let t=this.config.eventsEndpoint||`${this.config.endpoint}/api/events`;try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({events:e})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} events`);}catch(n){if(this.flushFailures++,this.flushFailures>=he){this.disabled=true,console.warn(`[SitePong Analytics] Disabled after ${he} consecutive failures. Check that ${t} is accessible and has proper CORS headers.`);return}this.eventQueue.unshift(...e),this.log(`Failed to flush events (attempt ${this.flushFailures}/${he}):`,n);}}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.popstateHandler&&typeof window<"u"&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.autocaptureModule&&(this.autocaptureModule.stop(),this.autocaptureModule=null),this.flushWithBeacon();}createEvent(e,t){return {type:e,name:t.name,properties:t.properties,userId:this.userId||void 0,anonymousId:R(),deviceId:void 0,groupId:this.groupId||void 0,traits:t.traits,sessionId:pe(),timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0,referrer:typeof document<"u"&&typeof document.referrer=="string"?document.referrer:void 0,userAgent:typeof navigator<"u"?navigator.userAgent:void 0}}enqueue(e){this.eventQueue.push(e),this.eventQueue.length>=this.config.maxBatchSize&&this.flush();}startFlushTimer(){this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval);}setupPageHideListener(){typeof window>"u"||M()||typeof window.addEventListener!="function"||window.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flushWithBeacon();});}flushWithBeacon(){if(this.eventQueue.length===0||M()||typeof navigator?.sendBeacon!="function")return;let e=[...this.eventQueue];this.eventQueue=[];let t=this.config.eventsEndpoint||`${this.config.endpoint}/api/events`,n=new Blob([JSON.stringify({events:e,apiKey:this.config.apiKey})],{type:"application/json"});navigator.sendBeacon(t,n),this.log(`Flushed ${e.length} events via beacon`);}setupSPATracking(){if(typeof window>"u"||M()||typeof window.addEventListener!="function")return;this.lastUrl=window.location.href,this.trackPageView(),this.popstateHandler=()=>{let n=window.location.href;n!==this.lastUrl&&(this.lastUrl=n,this.trackPageView(n));},window.addEventListener("popstate",this.popstateHandler);let e=history.pushState.bind(history),t=history.replaceState.bind(history);history.pushState=(...n)=>{e(...n),this.handleUrlChange();},history.replaceState=(...n)=>{t(...n),this.handleUrlChange();};}handleUrlChange(){if(typeof window>"u")return;let e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.trackPageView(e));}log(...e){this.config.debug&&console.log("[SitePong Analytics]",...e);}};var O=class{constructor(e){this.apiKey=e.apiKey,this.endpoint=e.endpoint,this.debug=e.debug||false;}async checkin(e,t={}){try{let n=await fetch(`${this.endpoint}/api/sdk/crons`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify({slug:e,status:t.status||"ok",duration_ms:t.duration_ms,message:t.message,environment:t.environment})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.log(`Check-in sent for "${e}" (${t.status||"ok"})`);}catch(n){this.log("Failed to send check-in:",n);}}start(e,t){let n=Date.now();return this.checkin(e,{status:"in_progress",environment:t}),{ok:async i=>{let o=Date.now()-n;await this.checkin(e,{status:"ok",duration_ms:o,message:i,environment:t});},error:async i=>{let o=Date.now()-n;await this.checkin(e,{status:"error",duration_ms:o,message:i,environment:t});}}}wrap(e,t,n){let i=this.start(e,n);return t().then(async o=>(await i.ok(),o),async o=>{throw await i.error(o?.message||String(o)),o})}log(...e){this.debug&&console.log("[SitePong:Cron]",...e);}};var H=class{constructor(e){this.queue=[];this.flushTimer=null;this.apiKey=e.apiKey,this.endpoint=e.endpoint,this.debug=e.debug||false,this.flushInterval=e.flushInterval||1e4,this.maxBatchSize=e.maxBatchSize||100,this.startFlushTimer();}increment(e,t=1,n){this.enqueue(e,t,"counter",n);}decrement(e,t=1,n){this.enqueue(e,-t,"counter",n);}gauge(e,t,n){this.enqueue(e,t,"gauge",n);}histogram(e,t,n){this.enqueue(e,t,"histogram",n);}distribution(e,t,n){this.enqueue(e,t,"distribution",n);}async time(e,t,n){let i=Date.now();try{let o=await t();return this.distribution(e,Date.now()-i,{...n,unit:n?.unit||"ms"}),o}catch(o){throw this.distribution(e,Date.now()-i,{...n,unit:n?.unit||"ms",tags:{...n?.tags,error:"true"}}),o}}startTimer(e,t){let n=Date.now();return {stop:()=>{this.distribution(e,Date.now()-n,{...t,unit:t?.unit||"ms"});}}}async flush(){if(this.queue.length===0)return;let e=[...this.queue];this.queue=[];try{let t=await fetch(`${this.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify({metrics:e})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} metrics`);}catch(t){this.queue.unshift(...e),this.log("Failed to flush metrics:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}enqueue(e,t,n,i){this.queue.push({name:e,value:t,type:n,unit:i?.unit,tags:i?.tags,timestamp:i?.timestamp||new Date().toISOString()}),this.queue.length>=this.maxBatchSize&&this.flush();}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.flushInterval);let e=b();e&&e.onVisibilityHidden(()=>this.flushWithBeacon());}flushWithBeacon(){if(this.queue.length===0)return;let e=b();if(!e||!e.sendBeacon)return;let t=[...this.queue];this.queue=[];let n=JSON.stringify({metrics:t,apiKey:this.apiKey});e.sendBeacon(`${this.endpoint}/api/sdk/metrics`,n)?this.log(`Flushed ${t.length} metrics via beacon`):this.queue.unshift(...t);}log(...e){this.debug&&console.log("[SitePong:Metrics]",...e);}};var B=class{constructor(e){this.queue=[];this.flushTimer=null;this.queryCounter=0;this.nPlusOneDetector=new Map;this.config={slowQueryThreshold:1e3,maxBatchSize:50,flushInterval:1e4,redactParams:true,...e},this.startFlushTimer();}async track(e,t,n){let i=Date.now();this.queryCounter++;try{let o=await t(),s=Date.now()-i;return this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,is_slow:s>=(this.config.slowQueryThreshold||1e3)}),this.detectNPlusOne(e),o}catch(o){let s=Date.now()-i;throw this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,error:o instanceof Error?o.message:String(o)}),o}}trackSync(e,t,n){let i=Date.now();this.queryCounter++;try{let o=t(),s=Date.now()-i;return this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,is_slow:s>=(this.config.slowQueryThreshold||1e3)}),o}catch(o){let s=Date.now()-i;throw this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,error:o instanceof Error?o.message:String(o)}),o}}getQueryCount(){return this.queryCounter}resetQueryCount(){this.queryCounter=0,this.nPlusOneDetector.clear();}getNPlusOnePatterns(){let e=[];for(let[t,{count:n}]of this.nPlusOneDetector.entries())n>=5&&e.push({query:t,count:n});return e}async flush(){if(this.queue.length===0)return;let e=[...this.queue];this.queue=[];try{let t=await fetch(`${this.config.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e.map(n=>({name:"db.query",value:n.duration_ms,type:"distribution",unit:"ms",tags:{query:n.query.substring(0,200),source:n.source||"unknown",is_slow:String(n.is_slow||!1),...n.error?{error:"true"}:{}},timestamp:n.timestamp}))})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} query events`);}catch(t){this.queue.unshift(...e),this.log("Failed to flush query events:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}recordQuery(e){this.queue.push(e),this.queue.length>=(this.config.maxBatchSize||50)&&this.flush(),e.is_slow&&this.log(`Slow query (${e.duration_ms}ms):`,e.query.substring(0,100));}detectNPlusOne(e){let t=this.normalizeQuery(e),n=Date.now(),i=this.nPlusOneDetector.get(t);if(i?n-i.since<1e3?(i.count++,i.count===5&&this.log(`N+1 query detected! Pattern repeated ${i.count} times:`,t.substring(0,100))):this.nPlusOneDetector.set(t,{count:1,since:n}):this.nPlusOneDetector.set(t,{count:1,since:n}),this.nPlusOneDetector.size>100){let o=[...this.nPlusOneDetector.entries()];o.sort((s,c)=>s[1].since-c[1].since);for(let s=0;s<50;s++)this.nPlusOneDetector.delete(o[s][0]);}}normalizeQuery(e){return e.replace(/\s+/g," ").replace(/'[^']*'/g,"?").replace(/\b\d+\b/g,"?").trim().substring(0,300)}redactQuery(e){return e.replace(/'[^']*'/g,"'***'").replace(/\b\d{4,}\b/g,"***")}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval||1e4);}log(...e){this.config.debug&&console.log("[SitePong:DB]",...e);}};var U=class{constructor(e){this.profiles=[];this.activeProfile=null;this.frameStack=[];this.flushTimer=null;this.config={sampleRate:.1,maxDuration:3e4,flushInterval:3e4,...e},this.startFlushTimer();}async profile(e,t,n){if(Math.random()>(this.config.sampleRate||.1))return t();let i=this.generateId(),o=performance.now();this.activeProfile={id:i,name:e,startTime:o,duration_ms:0,frames:[],metadata:n},this.frameStack=[];let s={name:e,start_ms:0,duration_ms:0,children:[],metadata:n};this.frameStack.push(s);try{let c=await t();return s.duration_ms=performance.now()-o,this.activeProfile.duration_ms=s.duration_ms,this.activeProfile.frames=[s],s.duration_ms<=(this.config.maxDuration||3e4)&&this.profiles.push(this.activeProfile),this.activeProfile=null,this.frameStack=[],c}catch(c){throw s.duration_ms=performance.now()-o,s.metadata={...s.metadata,error:true},this.activeProfile&&(this.activeProfile.duration_ms=s.duration_ms,this.activeProfile.frames=[s],this.profiles.push(this.activeProfile)),this.activeProfile=null,this.frameStack=[],c}}startSpan(e,t){if(!this.activeProfile)return ()=>{};let n=performance.now()-this.activeProfile.startTime,i={name:e,start_ms:n,duration_ms:0,children:[],metadata:t},o=this.frameStack[this.frameStack.length-1];return o&&o.children.push(i),this.frameStack.push(i),()=>{i.duration_ms=performance.now()-this.activeProfile.startTime-i.start_ms,this.frameStack.pop();}}getProfiles(){return [...this.profiles]}getLatestProfile(){return this.profiles.length>0?this.profiles[this.profiles.length-1]:null}async flush(){if(this.profiles.length===0)return;let e=[...this.profiles];this.profiles=[];try{let t=await fetch(`${this.config.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e.map(n=>({name:`profile.${n.name}`,value:n.duration_ms,type:"distribution",unit:"ms",tags:{profile_id:n.id,frame_count:String(Ue(n.frames)),...n.metadata||{}},timestamp:new Date(Date.now()-n.duration_ms).toISOString()}))})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} profiles`);}catch(t){this.profiles.unshift(...e),this.log("Failed to flush profiles:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval||3e4);}generateId(){return `prof_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,8)}`}log(...e){this.config.debug&&console.log("[SitePong:Profiler]",...e);}};function Ue(r){let e=r.length;for(let t of r)e+=Ue(t.children);return e}var me={features:{},sampling:{errors:1,analytics:1,replay:1,performance:1},transport:{flushInterval:1e4,maxBatchSize:20,maxRetries:3},autocapture:{clicks:true,forms:true,pageviews:true,appState:true,screenViews:true},ttl:300};var Ve="sitepong_remote_config",$e="sitepong_remote_config_ts",F=class{constructor(e){this.listeners=[];this.refreshTimer=null;this.initialized=false;this.options=e,this.config={...me};}async init(){await this.loadFromCache(),this.initialized=true,this.fetchAndApply().catch(e=>{this.log("Failed to fetch remote config:",e);});}getConfig(){return this.config}isFeatureEnabled(e,t=true){return this.config.features[e]??t}onChange(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e);}}isInitialized(){return this.initialized}destroy(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.listeners=[];}async loadFromCache(){let e=this.options.storage;if(e)try{let t=await e.getItem(Ve),n=await e.getItem($e);if(t&&n){let i=Date.now()-parseInt(n,10),o=this.config.ttl*1e3;if(i<o){let s=JSON.parse(t);this.config=s,this.log("Loaded config from cache (age:",Math.round(i/1e3),"s)");}}}catch{this.log("Failed to load cached config");}}async fetchAndApply(){try{let e=ae(),t=new URLSearchParams({platform:e,...this.options.sdkVersion?{sdkVersion:this.options.sdkVersion}:{}}),n=await fetch(`${this.options.endpoint}/api/sdk/config?${t}`,{method:"GET",headers:{"X-API-Key":this.options.apiKey}});if(!n.ok)throw new Error(`HTTP ${n.status}`);let i=await n.json();this.config=i.config;for(let o of this.listeners)try{o(this.config);}catch{}await this.saveToCache(),this.scheduleRefresh(),i.config.minSdkVersion&&this.options.sdkVersion&&this.compareVersions(this.options.sdkVersion,i.config.minSdkVersion)<0&&console.warn(`[SitePong] SDK version ${this.options.sdkVersion} is outdated. Minimum recommended: ${i.config.minSdkVersion}. Please update.`),this.log("Remote config fetched successfully");}catch(e){throw this.scheduleRefresh(),e}}async saveToCache(){let e=this.options.storage;if(e)try{await e.setItem(Ve,JSON.stringify(this.config)),await e.setItem($e,String(Date.now()));}catch{this.log("Failed to cache remote config");}}scheduleRefresh(){this.refreshTimer&&clearTimeout(this.refreshTimer);let e=this.config.ttl*1e3;this.refreshTimer=setTimeout(()=>{this.fetchAndApply().catch(t=>{this.log("Refresh failed:",t);});},e);}compareVersions(e,t){let n=e.split(".").map(Number),i=t.split(".").map(Number);for(let o=0;o<3;o++){let s=n[o]||0,c=i[o]||0;if(s>c)return 1;if(s<c)return -1}return 0}log(...e){this.options.debug&&console.log("[SitePong RemoteConfig]",...e);}};var xt="https://ingest.sitepong.com";var V=class{constructor(e){this.metrics=[];this.flushTimer=null;this.flushFailures=0;this.disabled=false;this.vitals={};this.activeTransactions=new Map;this.config={endpoint:xt,enabled:true,webVitals:true,navigationTiming:true,resourceTiming:false,flushInterval:1e4,sampleRate:1,debug:false,...e},this.sampled=Math.random()<=this.config.sampleRate;}init(){!this.config.enabled||!this.sampled||typeof window>"u"||typeof window.addEventListener!="function"||(this.config.webVitals&&this.observeWebVitals(),this.config.navigationTiming&&this.collectNavigationTiming(),this.startFlushTimer(),this.log("Performance monitoring initialized"));}startTransaction(e,t){let n=`txn_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,6)}`,i={id:n,name:e,startTime:performance.now(),status:"running",spans:[],data:t};return this.activeTransactions.set(n,i),this.log("Transaction started:",e,n),n}endTransaction(e,t="ok"){let n=this.activeTransactions.get(e);if(!n){this.log("Transaction not found:",e);return}n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.status=t;for(let i of n.spans)i.status==="running"&&(i.endTime=n.endTime,i.duration=i.endTime-i.startTime,i.status=t);this.activeTransactions.delete(e),this.addMetric({type:"transaction",name:n.name,value:n.duration,unit:"ms",timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0,transaction:n}),this.log("Transaction ended:",n.name,`${n.duration.toFixed(1)}ms`);}startSpan(e,t,n){let i=this.activeTransactions.get(e);if(!i)return this.log("Transaction not found for span:",e),"";let o={id:`span_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,6)}`,name:t,startTime:performance.now(),status:"running",data:n};return i.spans.push(o),o.id}endSpan(e,t,n="ok"){let i=this.activeTransactions.get(e);if(!i)return;let o=i.spans.find(s=>s.id===t);o&&(o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.status=n);}getVitals(){return {...this.vitals}}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush();}observeWebVitals(){if(!(typeof PerformanceObserver>"u")){try{new PerformanceObserver(t=>{let n=t.getEntries(),i=n[n.length-1];i&&(this.vitals.lcp=i.startTime,this.reportVital("LCP",i.startTime));}).observe({type:"largest-contentful-paint",buffered:!0});}catch{}try{new PerformanceObserver(t=>{let n=t.getEntries()[0];if(n){let i=n.processingStart-n.startTime;this.vitals.fid=i,this.reportVital("FID",i);}}).observe({type:"first-input",buffered:!0});}catch{}try{let e=0;new PerformanceObserver(n=>{for(let i of n.getEntries()){let o=i;o.hadRecentInput||(e+=o.value);}this.vitals.cls=e;}).observe({type:"layout-shift",buffered:!0}),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&e>0&&this.reportVital("CLS",e,"score");});}catch{}try{new PerformanceObserver(t=>{let n=t.getEntries().find(i=>i.name==="first-contentful-paint");n&&(this.vitals.fcp=n.startTime,this.reportVital("FCP",n.startTime));}).observe({type:"paint",buffered:!0});}catch{}try{let e=0;new PerformanceObserver(n=>{for(let i of n.getEntries()){let o=i.duration;o>e&&(e=o,this.vitals.inp=e);}}).observe({type:"event",buffered:!0});}catch{}}}collectNavigationTiming(){if(typeof window>"u"||!window.performance)return;let e=()=>{let t=performance.getEntriesByType("navigation")[0];if(!t)return;let n=t.responseStart-t.requestStart;this.vitals.ttfb=n,this.reportVital("TTFB",n),this.addMetric({type:"navigation",name:"page_load",value:t.loadEventEnd-t.startTime,unit:"ms",timestamp:new Date().toISOString(),url:window.location.href,data:{dns:t.domainLookupEnd-t.domainLookupStart,tcp:t.connectEnd-t.connectStart,ttfb:n,domContentLoaded:t.domContentLoadedEventEnd-t.startTime,domComplete:t.domComplete-t.startTime,transferSize:t.transferSize,encodedBodySize:t.encodedBodySize,decodedBodySize:t.decodedBodySize}});};document.readyState==="complete"?setTimeout(e,0):window.addEventListener("load",()=>setTimeout(e,0));}reportVital(e,t,n="ms"){this.addMetric({type:"web_vital",name:e,value:t,unit:n,timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0});}addMetric(e){this.metrics.push(e);}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flush();});}async flush(){if(this.metrics.length===0)return;if(this.disabled){this.metrics=[];return}let e=[...this.metrics];this.metrics=[];let t=this.config.performanceEndpoint||`${this.config.endpoint}/api/performance`;try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} performance metrics`);}catch(n){if(this.flushFailures++,this.flushFailures>=3){this.disabled=true,console.warn(`[SitePong Performance] Disabled after 3 consecutive failures. Check that ${t} is accessible and has proper CORS headers.`);return}this.metrics.unshift(...e),this.log(`Failed to flush metrics (attempt ${this.flushFailures}/3):`,n);}}log(...e){this.config.debug&&console.log("[SitePong Performance]",...e);}};function ze(r){try{if(typeof crypto<"u"&&crypto.getRandomValues){let t=new Uint8Array(r);return crypto.getRandomValues(t),Array.from(t).map(n=>n.toString(16).padStart(2,"0")).join("")}}catch{}let e="";for(let t=0;t<r;t++)e+=Math.floor(Math.random()*256).toString(16).padStart(2,"0");return e}function ve(){return ze(16)}function te(){return ze(8)}function ye(){return {traceId:ve(),spanId:te(),parentSpanId:null,sampled:true}}function Z(r){let e=r.sampled?"01":"00";return {traceparent:`00-${r.traceId}-${r.spanId}-${e}`,tracestate:`sitepong=${r.spanId}`}}function Ke(r){let e=r.traceparent||r.Traceparent;if(!e)return null;let t=e.split("-");if(t.length!==4)return null;let[n,i,o,s]=t;if(n!=="00"||i.length!==32||!/^[0-9a-f]{32}$/.test(i)||o.length!==16||!/^[0-9a-f]{16}$/.test(o)||s.length!==2||!/^[0-9a-f]{2}$/.test(s))return null;let c=(parseInt(s,16)&1)===1;return {traceId:i,spanId:te(),parentSpanId:o,sampled:c}}var ee=class{constructor(e){this.originalFetch=null;this.targets=e;}shouldPropagate(e){return this.targets.some(t=>{if(t.includes("*")){let n=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(e)}return e.startsWith(t)})}injectHeaders(e,t,n){if(!this.shouldPropagate(e))return t;let i=Z(n);return {...t,...i}}start(){if(typeof window>"u"||!window.fetch||this.originalFetch)return;this.originalFetch=window.fetch;let e=this;window.fetch=function(t,n){let i=typeof t=="string"?t:t instanceof URL?t.toString():t.url;if(e.shouldPropagate(i)){let o=ye(),s=Z(o),c={};if(n?.headers)if(n.headers instanceof Headers)n.headers.forEach((f,g)=>{c[g]=f;});else if(Array.isArray(n.headers))for(let[f,g]of n.headers)c[f]=g;else Object.assign(c,n.headers);let l={...c,...s},d={...n,headers:l};return e.originalFetch.call(window,t,d)}return e.originalFetch.call(window,t,n)};}stop(){typeof window>"u"||this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null);}};function kt(){if(b())return;let r=globalThis,e=typeof r.window<"u"&&typeof r.document<"u",t=!e&&!!r.process?.versions?.node,n=e?"browser":"node";A({platform:n,storage:null,getDeviceInfo(){let o={platform:n};return r.navigator?.userAgent&&(o.userAgent=r.navigator.userAgent),e&&r.window?.screen&&(o.screenWidth=r.window.screen.width,o.screenHeight=r.window.screen.height),t&&r.process&&(o.osName=r.process.platform,o.osVersion=r.process.versions?.node),o},getCurrentUrl(){return r.window?.location?.href??void 0},getReferrer(){return r.document?.referrer||void 0},getUserAgent(){if(r.navigator?.userAgent)return r.navigator.userAgent;if(t&&r.process)return `SitePong-Node/${r.process.versions?.node} (${r.process.platform})`},onUncaughtError(o){if(e&&r.window?.addEventListener){let s=c=>o(c.error||c.message);return r.window.addEventListener("error",s),()=>r.window?.removeEventListener?.("error",s)}if(t&&r.process?.on&&r.process.off){let s=c=>o(c);return r.process.on("uncaughtException",s),()=>r.process?.off?.("uncaughtException",s)}return ()=>{}},onUnhandledRejection(o){if(e&&r.window?.addEventListener){let s=c=>o(c.reason);return r.window.addEventListener("unhandledrejection",s),()=>r.window?.removeEventListener?.("unhandledrejection",s)}if(t&&r.process?.on&&r.process.off){let s=c=>o(c);return r.process.on("unhandledRejection",s),()=>r.process?.off?.("unhandledRejection",s)}return ()=>{}},onBeforeTerminate(o){return e&&r.window?.addEventListener?(r.window.addEventListener("beforeunload",o),()=>r.window?.removeEventListener?.("beforeunload",o)):t&&r.process?.on&&r.process.off?(r.process.on("beforeExit",o),r.process.on("SIGINT",o),r.process.on("SIGTERM",o),()=>{r.process?.off?.("beforeExit",o),r.process?.off?.("SIGINT",o),r.process?.off?.("SIGTERM",o);}):()=>{}},onVisibilityHidden(o){if(r.document?.addEventListener){let s=()=>{r.document?.visibilityState==="hidden"&&o();};return r.document.addEventListener("visibilitychange",s),()=>r.document?.removeEventListener?.("visibilitychange",s)}return ()=>{}},sendBeacon(o,s){if(typeof r.navigator?.sendBeacon!="function")return false;try{return r.navigator.sendBeacon(o,new Blob([s],{type:"application/json"}))}catch{return false}}});}kt();var k={};function qe(r){k={...k,...r};}var m="https://ingest.sitepong.com",Et=10,Ct=5e3,be=3,we=class{constructor(){this.errorQueue=[];this.flushTimer=null;this.context={};this.initialized=false;this.flushFailures=0;this.disabled=false;this.flagManager=null;this.analyticsManager=null;this.fingerprintManager=null;this.replayManager=null;this.performanceManager=null;this.cronManager=null;this.metricsManager=null;this.databaseTracker=null;this.profiler=null;this.remoteConfigManager=null;this.envUnsubs=[];this.identifyHooks=[];this.config={apiKey:"",endpoint:m,environment:"production",release:"",autoCapture:true,maxBatchSize:Et,flushInterval:Ct,debug:false};}init(e){if(!e.apiKey){console.error("[SitePong] API key is required");return}if(this.config={...this.config,...e},this.initialized=true,this.config.autoCapture&&this.setupAutoCapture(),this.startFlushTimer(),this.log("Initialized with endpoint:",this.config.endpoint),e.enableFlags&&(this.flagManager=new I({apiKey:e.apiKey,endpoint:e.flagsEndpoint||e.endpoint||m,debug:e.debug}),this.flagManager.init().catch(t=>{this.log("Failed to initialize flags:",t);})),e.analytics?.enabled&&(this.analyticsManager&&this.analyticsManager.destroy(),this.analyticsManager=new P({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,autocapturePageviews:e.analytics.autocapturePageviews,autocaptureClicks:e.analytics.autocaptureClicks,autocaptureForms:e.analytics.autocaptureForms,autocapture:e.analytics.autocapture,maxBatchSize:e.analytics.maxBatchSize,flushInterval:e.analytics.flushInterval,eventsEndpoint:e.analytics.eventsEndpoint,debug:e.debug}),this.analyticsManager.init()),e.fingerprint?.enabled&&k.createFingerprint?this.fingerprintManager=k.createFingerprint({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,extendedSignals:e.fingerprint.extendedSignals,visitorEndpoint:e.fingerprint.visitorEndpoint,debug:e.debug}):e.fingerprint?.enabled&&this.log("Fingerprint requested but not available on this platform (web only)."),e.performance?.enabled&&k.createPerformance?(this.performanceManager&&this.performanceManager.destroy(),this.performanceManager=k.createPerformance({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,webVitals:e.performance.webVitals,navigationTiming:e.performance.navigationTiming,resourceTiming:e.performance.resourceTiming,sampleRate:e.performance.sampleRate,flushInterval:e.performance.flushInterval,performanceEndpoint:e.performance.performanceEndpoint,debug:e.debug}),this.performanceManager.init()):e.performance?.enabled&&this.log("Performance requested but not available on this platform (web only)."),e.replay?.enabled&&k.createReplay?(this.replayManager&&this.replayManager.stop(),this.replayManager=k.createReplay({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,maskInputs:e.replay.maskInputs,blockSelector:e.replay.blockSelector,maskSelector:e.replay.maskSelector,sampleRate:e.replay.sampleRate,maxSessionDuration:e.replay.maxSessionDuration,flushInterval:e.replay.flushInterval,replayEndpoint:e.replay.replayEndpoint,recordNetwork:e.replay.recordNetwork,captureNetworkHeaders:e.replay.captureNetworkHeaders,recordConsole:e.replay.recordConsole,consoleLevels:e.replay.consoleLevels,bufferDuration:e.replay.bufferDuration,debug:e.debug}),this.replayManager.start()):e.replay?.enabled&&this.log("Replay requested but not available on this platform (web only)."),e.crons?.enabled&&(this.cronManager=new O({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug})),e.database?.enabled&&(this.databaseTracker=new B({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,slowQueryThreshold:e.database.slowQueryThreshold,redactParams:e.database.redactParams})),e.metrics?.enabled&&(this.metricsManager=new H({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,flushInterval:e.metrics.flushInterval,maxBatchSize:e.metrics.maxBatchSize})),e.profiling?.enabled&&(this.profiler=new U({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,sampleRate:e.profiling.sampleRate,maxDuration:e.profiling.maxDuration,flushInterval:e.profiling.flushInterval})),e.remoteConfig?.enabled!==false){let t=e._storageAdapter||le();this.remoteConfigManager=new F({apiKey:e.apiKey,endpoint:e.endpoint||m,storage:t,debug:e.debug}),this.remoteConfigManager.init().catch(n=>{this.log("Failed to initialize remote config:",n);});}}initRN(e){if(!e.apiKey){console.error("[SitePong] API key is required");return}if(this.config={...this.config,...e},this.initialized=true,this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval),this.log("Initialized (React Native) with endpoint:",this.config.endpoint),e.enableFlags&&(this.flagManager=new I({apiKey:e.apiKey,endpoint:e.flagsEndpoint||e.endpoint||m,debug:e.debug}),this.flagManager.init().catch(t=>{this.log("Failed to initialize flags:",t);})),e.analytics?.enabled&&(this.analyticsManager&&this.analyticsManager.destroy(),this.analyticsManager=new P({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,maxBatchSize:e.analytics.maxBatchSize,flushInterval:e.analytics.flushInterval,eventsEndpoint:e.analytics.eventsEndpoint,debug:e.debug}),this.analyticsManager.initHeadless()),e.crons?.enabled&&(this.cronManager=new O({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug})),e.metrics?.enabled&&(this.metricsManager=new H({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,flushInterval:e.metrics.flushInterval,maxBatchSize:e.metrics.maxBatchSize})),e.database?.enabled&&(this.databaseTracker=new B({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,slowQueryThreshold:e.database.slowQueryThreshold,redactParams:e.database.redactParams})),e.profiling?.enabled&&(this.profiler=new U({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,sampleRate:e.profiling.sampleRate,maxDuration:e.profiling.maxDuration,flushInterval:e.profiling.flushInterval})),e.remoteConfig?.enabled!==false){let t=e._storageAdapter||le();this.remoteConfigManager=new F({apiKey:e.apiKey,endpoint:e.endpoint||m,storage:t,debug:e.debug}),this.remoteConfigManager.init().catch(n=>{this.log("Failed to initialize remote config:",n);});}}isInitialized(){return this.initialized}getFlag(e,t=false){return this.flagManager?this.flagManager.getFlag(e,t):(this.log("Flags not enabled. Set enableFlags: true in init()"),t)}getAllFlags(){return this.flagManager?this.flagManager.getAllFlags():{}}async waitForFlags(){this.flagManager&&await this.flagManager.waitForInit();}areFlagsReady(){return this.flagManager?.isInitialized()??false}getVariant(e,t=null){return this.flagManager?this.flagManager.getVariant(e,t):(this.log("Flags not enabled. Set enableFlags: true in init()"),t)}getVariantPayload(e,t=null){return this.flagManager?this.flagManager.getVariantPayload(e,t):t}async refreshFlags(){this.flagManager&&await this.flagManager.refresh();}track(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.track(e,t);}trackPageView(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.trackPageView(e,t);}identify(e,t){this.replayManager&&this.replayManager.setUser({id:e});for(let n of this.identifyHooks)try{n(e);}catch(i){this.log("identify hook failed:",i);}if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.identify(e,t);}registerIdentifyHook(e){return this.identifyHooks.push(e),()=>{let t=this.identifyHooks.indexOf(e);t>=0&&this.identifyHooks.splice(t,1);}}group(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.group(e,t);}resetAnalytics(){this.analyticsManager&&this.analyticsManager.reset();}async getVisitorId(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getVisitorId()}async getDeviceSignals(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getDeviceSignals()}async getFraudCheck(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getFraudCheck()}startReplay(){return this.replayManager?this.replayManager.start():(this.log("Replay not enabled. Set replay.enabled: true in init()"),false)}stopReplay(){this.replayManager&&this.replayManager.stop();}isReplayRecording(){return this.replayManager?.isRecording()??false}getReplaySessionId(){return this.replayManager?.getSessionId()??null}startTransaction(e,t){return this.performanceManager?this.performanceManager.startTransaction(e,t):(this.log("Performance not enabled. Set performance.enabled: true in init()"),"")}endTransaction(e,t="ok"){this.performanceManager&&this.performanceManager.endTransaction(e,t);}startSpan(e,t,n){return this.performanceManager?this.performanceManager.startSpan(e,t,n):""}endSpan(e,t,n="ok"){this.performanceManager&&this.performanceManager.endSpan(e,t,n);}getWebVitals(){return this.performanceManager?this.performanceManager.getVitals():{}}cronCheckin(e,t){return this.cronManager?this.cronManager.checkin(e,t):(this.log("Cron monitoring not enabled. Set crons.enabled: true in init()"),Promise.resolve())}cronStart(e,t){return this.cronManager?this.cronManager.start(e,t):(this.log("Cron monitoring not enabled. Set crons.enabled: true in init()"),{ok:()=>Promise.resolve(),error:()=>Promise.resolve()})}cronWrap(e,t,n){return this.cronManager?this.cronManager.wrap(e,t,n):t()}metricIncrement(e,t,n){if(!this.metricsManager){this.log("Metrics not enabled. Set metrics.enabled: true in init()");return}this.metricsManager.increment(e,t,n);}metricGauge(e,t,n){this.metricsManager&&this.metricsManager.gauge(e,t,n);}metricHistogram(e,t,n){this.metricsManager&&this.metricsManager.histogram(e,t,n);}metricDistribution(e,t,n){this.metricsManager&&this.metricsManager.distribution(e,t,n);}async metricTime(e,t,n){return this.metricsManager?this.metricsManager.time(e,t,n):t()}metricStartTimer(e,t){return this.metricsManager?this.metricsManager.startTimer(e,t):{stop:()=>{}}}async flushMetrics(){if(this.metricsManager)return this.metricsManager.flush()}async dbTrack(e,t,n){return this.databaseTracker?this.databaseTracker.track(e,t,n):t()}dbTrackSync(e,t,n){return this.databaseTracker?this.databaseTracker.trackSync(e,t,n):t()}getDbQueryCount(){return this.databaseTracker?this.databaseTracker.getQueryCount():0}resetDbQueryCount(){this.databaseTracker&&this.databaseTracker.resetQueryCount();}getDbNPlusOnePatterns(){return this.databaseTracker?this.databaseTracker.getNPlusOnePatterns():[]}async profile(e,t,n){return this.profiler?this.profiler.profile(e,t,n):t()}startProfileSpan(e,t){return this.profiler?this.profiler.startSpan(e,t):()=>{}}getProfiles(){return this.profiler?this.profiler.getProfiles():[]}getLatestProfile(){return this.profiler?this.profiler.getLatestProfile():null}async flushProfiles(){if(this.profiler)return this.profiler.flush()}getRemoteConfig(){return this.remoteConfigManager?.getConfig()??null}isRemoteConfigFeatureEnabled(e,t=true){return this.remoteConfigManager?.isFeatureEnabled(e,t)??t}onRemoteConfigChange(e){return this.remoteConfigManager?this.remoteConfigManager.onChange(e):()=>{}}setContext(e){this.context={...this.context,...e};}setUser(e){this.context.user=e,this.replayManager&&this.replayManager.setUser(e?{id:e.id}:null);}setTags(e){this.context.tags={...this.context.tags,...e};}clearUser(){this.context.user=void 0,this.replayManager&&this.replayManager.setUser(null);}addBreadcrumb(e){this.log("Breadcrumb added:",e);}captureError(e,t){if(!this.initialized){console.warn("[SitePong] SDK not initialized. Call init() first.");return}let n=this.formatError(e,t);this.errorQueue.push(n),this.log("Captured error:",n.message),this.replayManager?.isRecording()&&this.replayManager.flushOnError().catch(i=>{this.log("Failed to flush replay on error:",i);}),this.errorQueue.length>=this.config.maxBatchSize&&this.flush();}captureMessage(e,t="info",n){if(!this.initialized){console.warn("[SitePong] SDK not initialized. Call init() first.");return}let i={message:e,type:t,timestamp:new Date().toISOString(),url:this.getUrl(),userAgent:this.getUserAgent(),environment:this.config.environment,release:this.config.release,context:{...this.context,...n},replaySessionId:this.replayManager?.isRecording()&&this.replayManager.getSessionId()||void 0};this.errorQueue.push(i),this.log("Captured message:",e),this.errorQueue.length>=this.config.maxBatchSize&&this.flush();}async flush(){if(this.errorQueue.length===0)return;if(this.disabled){this.errorQueue=[];return}let e=[...this.errorQueue];this.errorQueue=[];try{let t=await fetch(`${this.config.endpoint}/api/errors/batch`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({errors:e})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} errors`);}catch(t){if(this.flushFailures++,this.flushFailures>=be){this.disabled=true,console.warn(`[SitePong] SDK disabled after ${be} consecutive failures. Events will no longer be sent. This may be due to CORS issues or network problems. Check that ${this.config.endpoint} is accessible and has proper CORS headers.`);return}this.errorQueue.unshift(...e),this.log(`Failed to flush errors (attempt ${this.flushFailures}/${be}):`,t);}}formatError(e,t){let n=e instanceof Error,i=n?e.message:String(e),o=n?e.stack:new Error(i).stack,s=n?e.name:"Error";return {message:i,stack:o,type:s,timestamp:new Date().toISOString(),url:this.getUrl(),userAgent:this.getUserAgent(),environment:this.config.environment,release:this.config.release,context:{...this.context,...t},fingerprint:this.generateFingerprint(i,o,s),replaySessionId:this.replayManager?.isRecording()&&this.replayManager.getSessionId()||void 0}}generateFingerprint(e,t,n){let i=n||"Error",o=this.normalizeMessage(e),s=t?this.extractTopFrame(t):"",c=[i,o,s].join(`
|
|
1
|
+
var SitePong=(function(exports){'use strict';function lt(){try{return typeof localStorage>"u"?null:{getItem:async r=>localStorage.getItem(r),setItem:async(r,e)=>{localStorage.setItem(r,e);},removeItem:async r=>{localStorage.removeItem(r);}}}catch{return null}}function Me(){return {platform:"browser",storage:lt(),getDeviceInfo(){let e={platform:"browser"};return typeof navigator<"u"&&(e.userAgent=navigator.userAgent),typeof window<"u"&&window.screen&&(e.screenWidth=window.screen.width,e.screenHeight=window.screen.height),e},getCurrentUrl(){if(!(typeof window>"u"||!window.location))return window.location.href},getReferrer(){if(!(typeof document>"u"))return document.referrer||void 0},getUserAgent(){if(!(typeof navigator>"u"))return navigator.userAgent},onUncaughtError(e){if(typeof window>"u"||!window.addEventListener)return ()=>{};let t=n=>{e(n.error||n.message);};return window.addEventListener("error",t),()=>window.removeEventListener("error",t)},onUnhandledRejection(e){if(typeof window>"u"||!window.addEventListener)return ()=>{};let t=n=>{e(n.reason);};return window.addEventListener("unhandledrejection",t),()=>window.removeEventListener("unhandledrejection",t)},onBeforeTerminate(e){return typeof window>"u"||!window.addEventListener?()=>{}:(window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e))},onVisibilityHidden(e){if(typeof document>"u"||!document.addEventListener)return ()=>{};let t=()=>{document.visibilityState==="hidden"&&e();};return document.addEventListener("visibilitychange",t),()=>document.removeEventListener("visibilitychange",t)},sendBeacon(e,t){if(typeof navigator>"u"||typeof navigator.sendBeacon!="function")return false;try{let n=new Blob([t],{type:"application/json"});return navigator.sendBeacon(e,n)}catch{return false}}}}var T=null;function A(r){T=r;}function b(){return T}function ae(){if(T)return T.platform;let r=globalThis;return r.navigator&&r.navigator.product==="ReactNative"?"react-native":r.process&&r.process.versions&&r.process.versions.node?"node":r.window&&r.document?"browser":"unknown"}function M(){return ae()==="react-native"}var ut=null;function dt(){return T&&T.platform==="react-native"?T:null}function ce(r){let e=dt();e&&e._setGetCurrentScreen(r);}function X(){return ut}function le(){return T?T.storage:null}var j="sitepong_anonymous_id";function ue(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}var x=null;function R(){if(typeof window<"u"&&typeof localStorage<"u")try{let r=localStorage.getItem(j);return r||(r=ue(),localStorage.setItem(j,r)),r}catch{return x||(x=ue()),x}return x||(x=ue()),x}function Re(){if(typeof window<"u"&&typeof localStorage<"u")try{localStorage.removeItem(j);}catch{}x=null;}function Ie(r){if(typeof window<"u"&&typeof localStorage<"u")try{localStorage.setItem(j,r);}catch{x=r;}else x=r;}function Pe(r){let e=r.toLowerCase();return /ipad/.test(e)||/android/.test(e)&&!/mobile/.test(e)||/tablet/.test(e)?"tablet":/mobile/.test(e)||/iphone/.test(e)||/ipod/.test(e)||/android/.test(e)||/blackberry/.test(e)||/windows phone/.test(e)?"mobile":"desktop"}function Fe(r){let e=r.toLowerCase();return /edg/.test(e)?"edge":/opr|opera/.test(e)?"opera":/samsungbrowser/.test(e)?"samsung":/chrome|chromium|crios/.test(e)?"chrome":/safari/.test(e)&&!/chrome/.test(e)?"safari":/firefox|fxios/.test(e)?"firefox":/msie|trident/.test(e)?"ie":"other"}function De(r){let e=r.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/mac os|macos|macintosh/.test(e)?"macos":/windows/.test(e)?"windows":/linux/.test(e)?"linux":"other"}function de(){let r=b()?.getUserAgent()??"";return {anonymous_id:R(),device_type:r?Pe(r):void 0,browser:r?Fe(r):void 0,os:r?De(r):void 0,user_agent:r||void 0,timestamp:new Date}}function Ae(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e^r.charCodeAt(t);return e>>>0}function ft(r){return Math.random()*100<r.percentage}function pt(r,e,t){let n=`${e.anonymous_id}:${t}`;return Ae(n)%100<r.percentage}function Q(r){let[e,t]=r.split(":").map(Number);return e*60+t}function gt(r,e){let t=e.timestamp||new Date,i=new Intl.DateTimeFormat("en-US",{timeZone:r.timezone,weekday:"short",hour:"2-digit",minute:"2-digit",hour12:false}).formatToParts(t),o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].indexOf(i.find(d=>d.type==="weekday")?.value||""),s=parseInt(i.find(d=>d.type==="hour")?.value||"0",10),c=parseInt(i.find(d=>d.type==="minute")?.value||"0",10),l=s*60+c;if(r.days_of_week&&r.days_of_week.length>0&&!r.days_of_week.includes(o))return false;if(r.start_time&&r.end_time){let d=Q(r.start_time),f=Q(r.end_time);if(d>f){if(l<d&&l>=f)return false}else if(l<d||l>=f)return false}else if(r.start_time){let d=Q(r.start_time);if(l<d)return false}else if(r.end_time){let d=Q(r.end_time);if(l>=d)return false}return true}function ht(r,e){return e.device_type?r.types.includes(e.device_type):false}function mt(r,e){return e.browser?r.browsers.includes(e.browser):false}function vt(r,e){return e.os?r.operating_systems.includes(e.os):false}function yt(r,e,t,n){switch(r){case "percentage_rollout":return ft(e);case "userbase_percentage":return pt(e,t,n);case "time_based":return gt(e,t);case "device_type":return ht(e,t);case "browser":return mt(e,t);case "os":return vt(e,t);default:return false}}function Y(r,e){if(r.override==="force_on")return true;if(r.override==="force_off"||!r.enabled)return false;if(!r.rules||r.rules.length===0)return true;for(let t of r.rules)if(!yt(t.rule_type,t.config,e,r.key))return false;return true}function _e(r,e){if(!Y(r,e)||r.flag_type!=="multivariate"||!r.variants||r.variants.length===0)return null;let t=`${e.anonymous_id}:${r.key}:variant`,n=Ae(t),i=r.variants.reduce((c,l)=>c+l.weight,0),o=n%i,s=0;for(let c of r.variants)if(s+=c.weight,o<s)return c.key;return r.variants[0].key}function Le(r,e){return r.variant_payloads&&r.variant_payloads[e]!==void 0?r.variant_payloads[e]:r.variants?.find(n=>n.key===e)?.payload||null}var bt="https://api.sitepong.com",I=class{constructor(e){this.flags=new Map;this.evaluatedFlags=new Map;this.evaluatedVariants=new Map;this.context=null;this.initialized=false;this.initPromise=null;this.config={endpoint:bt,debug:false,...e};}async init(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.fetchAndEvaluateFlags();try{await this.initPromise,this.initialized=!0;}catch(e){this.log("Failed to initialize flags:",e),this.initialized=true;}finally{this.initPromise=null;}}}async fetchAndEvaluateFlags(){try{let e=await fetch(`${this.config.endpoint}/api/sdk/flags`,{method:"GET",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey}});if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);let t=await e.json();this.log("Fetched flags:",t.flags.length),this.context=de(),this.log("Evaluation context:",this.context),this.flags.clear(),this.evaluatedFlags.clear(),this.evaluatedVariants.clear();for(let n of t.flags){this.flags.set(n.key,n);let i=Y(n,this.context);if(this.evaluatedFlags.set(n.key,i),n.flag_type==="multivariate"&&n.variants){let o=_e(n,this.context);this.evaluatedVariants.set(n.key,o),this.log(`Flag "${n.key}": ${i}, variant: ${o}`);}else this.log(`Flag "${n.key}": ${i}`);}}catch(e){throw this.log("Error fetching flags:",e),e}}getFlag(e,t=false){if(!this.initialized)return this.log(`Flag "${e}" requested before init, returning default:`,t),t;let n=this.evaluatedFlags.get(e);return n===void 0?(this.log(`Flag "${e}" not found, returning default:`,t),t):n}getVariant(e,t=null){if(!this.initialized)return this.log(`Variant "${e}" requested before init, returning default:`,t),t;let n=this.evaluatedVariants.get(e);return n===void 0?(this.log(`Variant "${e}" not found, returning default:`,t),t):n}getVariantPayload(e,t=null){let n=this.getVariant(e);if(!n)return t;let i=this.flags.get(e);return i?Le(i,n)??t:t}getAllFlags(){let e={};for(let[t,n]of this.evaluatedFlags)e[t]=n;return e}hasFlag(e){return this.flags.has(e)}isInitialized(){return this.initialized}async waitForInit(){this.initialized||await this.init();}async refresh(){this.initialized=false,await this.init();}getContext(){return this.context}log(...e){this.config.debug&&console.log("[SitePong Flags]",...e);}};var fe="sitepong_session_id",J="sitepong_session_ts";var _=null,L=null;function Oe(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}function He(r){return Date.now()-r>18e5}function pe(){if(typeof window<"u"&&typeof sessionStorage<"u")try{let r=sessionStorage.getItem(fe),e=sessionStorage.getItem(J);if(r&&e&&!He(parseInt(e,10)))return sessionStorage.setItem(J,String(Date.now())),r;let t=Oe();return sessionStorage.setItem(fe,t),sessionStorage.setItem(J,String(Date.now())),t}catch{return Ne()}return Ne()}function Ne(){return _&&L&&!He(L)?(L=Date.now(),_):(_=Oe(),L=Date.now(),_)}function ge(){if(typeof window<"u"&&typeof sessionStorage<"u")try{sessionStorage.removeItem(fe),sessionStorage.removeItem(J);}catch{}_=null,L=null;}var Be=["[data-sp-no-capture]",".sp-no-capture"];var N=class{constructor(e,t){this.clickHandler=null;this.submitHandler=null;this.active=false;this.config={clicks:true,forms:true,pageviews:true,blockSelectors:Be,maxTextLength:255,debug:false,...e},this.callback=t;}start(){this.active||typeof document>"u"||typeof document.addEventListener!="function"||(this.active=true,this.config.clicks&&this.setupClickCapture(),this.config.forms&&this.setupFormCapture(),this.log("Autocapture started"));}stop(){this.active&&(this.active=false,this.clickHandler&&(document.removeEventListener("click",this.clickHandler,true),this.clickHandler=null),this.submitHandler&&(document.removeEventListener("submit",this.submitHandler,true),this.submitHandler=null),this.log("Autocapture stopped"));}setupClickCapture(){this.clickHandler=e=>{let t=e.target;if(!t||!this.shouldCapture(t))return;let n=this.getElementProperties(t);n.$event_type="click",n.$x=e.clientX,n.$y=e.clientY,this.callback({type:"click",timestamp:new Date().toISOString(),properties:n});},document.addEventListener("click",this.clickHandler,true);}setupFormCapture(){this.submitHandler=e=>{let t=e.target;if(!t||!this.shouldCapture(t))return;let n={$event_type:"form_submit",$form_action:t.action||void 0,$form_method:t.method||"get",$form_name:t.name||t.id||void 0,$field_names:this.getFormFieldNames(t),$field_count:t.elements.length},i=this.getElementProperties(t);Object.assign(n,i),this.callback({type:"form_submit",timestamp:new Date().toISOString(),properties:n});},document.addEventListener("submit",this.submitHandler,true);}shouldCapture(e){let t=this.config.blockSelectors||Be;for(let n of t)if(e.matches(n)||e.closest(n))return false;return !(this.config.allowSelectors&&this.config.allowSelectors.length>0&&!this.config.allowSelectors.some(i=>e.matches(i)||e.closest(i)!==null)||e.offsetParent===null&&e.tagName!=="BODY")}getElementProperties(e){let t={};t.$tag_name=e.tagName.toLowerCase(),t.$el_id=e.id||void 0,e.classList.length>0&&(t.$el_classes=Array.from(e.classList).slice(0,5));let n=this.getElementText(e);n&&(t.$el_text=n),e instanceof HTMLAnchorElement&&(t.$href=e.href||void 0,t.$target=e.target||void 0),(e instanceof HTMLInputElement||e instanceof HTMLButtonElement)&&(t.$el_type=e.type||void 0,t.$el_name=e.name||void 0);let i=e.getAttribute("aria-label");i&&(t.$aria_label=this.truncate(i));let o=e.getAttribute("role");return o&&(t.$el_role=o),t.$selector=this.getSelector(e),typeof window<"u"&&window.location&&(t.$current_url=window.location.href,t.$pathname=window.location.pathname),t}getElementText(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)return;let t="";if(e instanceof HTMLButtonElement||e instanceof HTMLAnchorElement)t=e.innerText||e.textContent||"";else for(let n of Array.from(e.childNodes))n.nodeType===Node.TEXT_NODE&&(t+=n.textContent||"");return t=t.trim().replace(/\s+/g," "),t?this.truncate(t):void 0}getFormFieldNames(e){let t=[];for(let n of Array.from(e.elements)){let i=n;i.name&&i.type!=="password"&&i.type!=="hidden"&&t.push(i.name);}return t.slice(0,20)}getSelector(e){let t=[],n=e,i=0;for(;n&&n!==document.body&&i<5;){let o=n.tagName.toLowerCase();if(n.id){o=`#${n.id}`,t.unshift(o);break}n.classList.length>0&&(o+=`.${Array.from(n.classList).slice(0,2).join(".")}`);let s=n.parentElement;if(s){let c=Array.from(s.children).filter(l=>l.tagName===n.tagName);if(c.length>1){let l=c.indexOf(n)+1;o+=`:nth-of-type(${l})`;}}t.unshift(o),n=n.parentElement,i++;}return t.join(" > ")}truncate(e){let t=this.config.maxTextLength||255;return e.length>t?e.slice(0,t)+"...":e}log(...e){this.config.debug&&console.log("[SitePong Autocapture]",...e);}};var wt="https://ingest.sitepong.com",St=20,Tt=1e4,he=3,P=class{constructor(e){this.eventQueue=[];this.flushTimer=null;this.flushFailures=0;this.disabled=false;this.userId=null;this.groupId=null;this.userTraits=null;this.groupTraits=null;this.lastUrl=null;this.popstateHandler=null;this.autocaptureModule=null;this.config={endpoint:wt,enabled:true,autocapturePageviews:false,maxBatchSize:St,flushInterval:Tt,debug:false,...e};}init(){this.config.enabled&&(this.startFlushTimer(),this.setupPageHideListener(),this.config.autocapturePageviews&&this.setupSPATracking(),this.setupAutocapture(),this.log("Analytics initialized"));}initHeadless(){this.config.enabled&&(this.startFlushTimer(),this.log("Analytics initialized (headless)"));}setupAutocapture(){let e=this.config.autocapture,t=this.config.autocaptureClicks,n=this.config.autocaptureForms,i=t||false,o=n||false,s,c;e===true?(i=true,o=true):e&&typeof e=="object"&&(i=e.clicks!==false,o=e.forms!==false,s=e.blockSelectors,c=e.allowSelectors,e.pageviews!==false&&!this.config.autocapturePageviews&&this.setupSPATracking()),!(!i&&!o)&&(this.autocaptureModule=new N({clicks:i,forms:o,pageviews:false,blockSelectors:s,allowSelectors:c,debug:this.config.debug},l=>{let d=l.type==="click"?"$autocapture_click":l.type==="form_submit"?"$autocapture_form_submit":"$autocapture";this.track(d,l.properties);}),this.autocaptureModule.start());}track(e,t){if(!this.config.enabled)return;let n=this.createEvent("track",{name:e,properties:t});this.enqueue(n),this.log("Track:",e,t);}trackPageView(e,t){if(!this.config.enabled)return;let n=e||(typeof window<"u"&&window.location?window.location.href:void 0),i=this.createEvent("page",{properties:{url:n,referrer:typeof document<"u"?document.referrer:void 0,title:typeof document<"u"?document.title:void 0,...t}});this.enqueue(i),this.log("Page view:",n);}identify(e,t){if(!this.config.enabled)return;this.userId=e,t&&(this.userTraits={...this.userTraits,...t});let n=this.createEvent("identify",{traits:this.userTraits||void 0});this.enqueue(n),this.log("Identify:",e,t);}group(e,t){if(!this.config.enabled)return;this.groupId=e,t&&(this.groupTraits={...this.groupTraits,...t});let n=this.createEvent("group",{traits:this.groupTraits||void 0});this.enqueue(n),this.log("Group:",e,t);}reset(){this.userId=null,this.groupId=null,this.userTraits=null,this.groupTraits=null,ge(),this.log("Analytics state reset");}async flush(){if(this.eventQueue.length===0)return;if(this.disabled){this.eventQueue=[];return}let e=[...this.eventQueue];this.eventQueue=[];let t=this.config.eventsEndpoint||`${this.config.endpoint}/api/events`;try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({events:e})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} events`);}catch(n){if(this.flushFailures++,this.flushFailures>=he){this.disabled=true,console.warn(`[SitePong Analytics] Disabled after ${he} consecutive failures. Check that ${t} is accessible and has proper CORS headers.`);return}this.eventQueue.unshift(...e),this.log(`Failed to flush events (attempt ${this.flushFailures}/${he}):`,n);}}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.popstateHandler&&typeof window<"u"&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.autocaptureModule&&(this.autocaptureModule.stop(),this.autocaptureModule=null),this.flushWithBeacon();}createEvent(e,t){return {type:e,name:t.name,properties:t.properties,userId:this.userId||void 0,anonymousId:R(),deviceId:void 0,groupId:this.groupId||void 0,traits:t.traits,sessionId:pe(),timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0,referrer:typeof document<"u"&&typeof document.referrer=="string"?document.referrer:void 0,userAgent:typeof navigator<"u"?navigator.userAgent:void 0}}enqueue(e){this.eventQueue.push(e),this.eventQueue.length>=this.config.maxBatchSize&&this.flush();}startFlushTimer(){this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval);}setupPageHideListener(){typeof window>"u"||M()||typeof window.addEventListener!="function"||window.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flushWithBeacon();});}flushWithBeacon(){if(this.eventQueue.length===0||M()||typeof navigator?.sendBeacon!="function")return;let e=[...this.eventQueue];this.eventQueue=[];let t=this.config.eventsEndpoint||`${this.config.endpoint}/api/events`,n=new Blob([JSON.stringify({events:e,apiKey:this.config.apiKey})],{type:"application/json"});navigator.sendBeacon(t,n),this.log(`Flushed ${e.length} events via beacon`);}setupSPATracking(){if(typeof window>"u"||M()||!window.location||typeof window.addEventListener!="function")return;this.lastUrl=window.location.href,this.trackPageView(),this.popstateHandler=()=>{if(!window.location)return;let n=window.location.href;n!==this.lastUrl&&(this.lastUrl=n,this.trackPageView(n));},window.addEventListener("popstate",this.popstateHandler);let e=history.pushState.bind(history),t=history.replaceState.bind(history);history.pushState=(...n)=>{e(...n),this.handleUrlChange();},history.replaceState=(...n)=>{t(...n),this.handleUrlChange();};}handleUrlChange(){if(typeof window>"u"||!window.location)return;let e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.trackPageView(e));}log(...e){this.config.debug&&console.log("[SitePong Analytics]",...e);}};var O=class{constructor(e){this.apiKey=e.apiKey,this.endpoint=e.endpoint,this.debug=e.debug||false;}async checkin(e,t={}){try{let n=await fetch(`${this.endpoint}/api/sdk/crons`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify({slug:e,status:t.status||"ok",duration_ms:t.duration_ms,message:t.message,environment:t.environment})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.log(`Check-in sent for "${e}" (${t.status||"ok"})`);}catch(n){this.log("Failed to send check-in:",n);}}start(e,t){let n=Date.now();return this.checkin(e,{status:"in_progress",environment:t}),{ok:async i=>{let o=Date.now()-n;await this.checkin(e,{status:"ok",duration_ms:o,message:i,environment:t});},error:async i=>{let o=Date.now()-n;await this.checkin(e,{status:"error",duration_ms:o,message:i,environment:t});}}}wrap(e,t,n){let i=this.start(e,n);return t().then(async o=>(await i.ok(),o),async o=>{throw await i.error(o?.message||String(o)),o})}log(...e){this.debug&&console.log("[SitePong:Cron]",...e);}};var H=class{constructor(e){this.queue=[];this.flushTimer=null;this.apiKey=e.apiKey,this.endpoint=e.endpoint,this.debug=e.debug||false,this.flushInterval=e.flushInterval||1e4,this.maxBatchSize=e.maxBatchSize||100,this.startFlushTimer();}increment(e,t=1,n){this.enqueue(e,t,"counter",n);}decrement(e,t=1,n){this.enqueue(e,-t,"counter",n);}gauge(e,t,n){this.enqueue(e,t,"gauge",n);}histogram(e,t,n){this.enqueue(e,t,"histogram",n);}distribution(e,t,n){this.enqueue(e,t,"distribution",n);}async time(e,t,n){let i=Date.now();try{let o=await t();return this.distribution(e,Date.now()-i,{...n,unit:n?.unit||"ms"}),o}catch(o){throw this.distribution(e,Date.now()-i,{...n,unit:n?.unit||"ms",tags:{...n?.tags,error:"true"}}),o}}startTimer(e,t){let n=Date.now();return {stop:()=>{this.distribution(e,Date.now()-n,{...t,unit:t?.unit||"ms"});}}}async flush(){if(this.queue.length===0)return;let e=[...this.queue];this.queue=[];try{let t=await fetch(`${this.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify({metrics:e})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} metrics`);}catch(t){this.queue.unshift(...e),this.log("Failed to flush metrics:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}enqueue(e,t,n,i){this.queue.push({name:e,value:t,type:n,unit:i?.unit,tags:i?.tags,timestamp:i?.timestamp||new Date().toISOString()}),this.queue.length>=this.maxBatchSize&&this.flush();}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.flushInterval);let e=b();e&&e.onVisibilityHidden(()=>this.flushWithBeacon());}flushWithBeacon(){if(this.queue.length===0)return;let e=b();if(!e||!e.sendBeacon)return;let t=[...this.queue];this.queue=[];let n=JSON.stringify({metrics:t,apiKey:this.apiKey});e.sendBeacon(`${this.endpoint}/api/sdk/metrics`,n)?this.log(`Flushed ${t.length} metrics via beacon`):this.queue.unshift(...t);}log(...e){this.debug&&console.log("[SitePong:Metrics]",...e);}};var B=class{constructor(e){this.queue=[];this.flushTimer=null;this.queryCounter=0;this.nPlusOneDetector=new Map;this.config={slowQueryThreshold:1e3,maxBatchSize:50,flushInterval:1e4,redactParams:true,...e},this.startFlushTimer();}async track(e,t,n){let i=Date.now();this.queryCounter++;try{let o=await t(),s=Date.now()-i;return this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,is_slow:s>=(this.config.slowQueryThreshold||1e3)}),this.detectNPlusOne(e),o}catch(o){let s=Date.now()-i;throw this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,error:o instanceof Error?o.message:String(o)}),o}}trackSync(e,t,n){let i=Date.now();this.queryCounter++;try{let o=t(),s=Date.now()-i;return this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,is_slow:s>=(this.config.slowQueryThreshold||1e3)}),o}catch(o){let s=Date.now()-i;throw this.recordQuery({query:this.config.redactParams?this.redactQuery(e):e,duration_ms:s,timestamp:new Date().toISOString(),source:n,error:o instanceof Error?o.message:String(o)}),o}}getQueryCount(){return this.queryCounter}resetQueryCount(){this.queryCounter=0,this.nPlusOneDetector.clear();}getNPlusOnePatterns(){let e=[];for(let[t,{count:n}]of this.nPlusOneDetector.entries())n>=5&&e.push({query:t,count:n});return e}async flush(){if(this.queue.length===0)return;let e=[...this.queue];this.queue=[];try{let t=await fetch(`${this.config.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e.map(n=>({name:"db.query",value:n.duration_ms,type:"distribution",unit:"ms",tags:{query:n.query.substring(0,200),source:n.source||"unknown",is_slow:String(n.is_slow||!1),...n.error?{error:"true"}:{}},timestamp:n.timestamp}))})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} query events`);}catch(t){this.queue.unshift(...e),this.log("Failed to flush query events:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}recordQuery(e){this.queue.push(e),this.queue.length>=(this.config.maxBatchSize||50)&&this.flush(),e.is_slow&&this.log(`Slow query (${e.duration_ms}ms):`,e.query.substring(0,100));}detectNPlusOne(e){let t=this.normalizeQuery(e),n=Date.now(),i=this.nPlusOneDetector.get(t);if(i?n-i.since<1e3?(i.count++,i.count===5&&this.log(`N+1 query detected! Pattern repeated ${i.count} times:`,t.substring(0,100))):this.nPlusOneDetector.set(t,{count:1,since:n}):this.nPlusOneDetector.set(t,{count:1,since:n}),this.nPlusOneDetector.size>100){let o=[...this.nPlusOneDetector.entries()];o.sort((s,c)=>s[1].since-c[1].since);for(let s=0;s<50;s++)this.nPlusOneDetector.delete(o[s][0]);}}normalizeQuery(e){return e.replace(/\s+/g," ").replace(/'[^']*'/g,"?").replace(/\b\d+\b/g,"?").trim().substring(0,300)}redactQuery(e){return e.replace(/'[^']*'/g,"'***'").replace(/\b\d{4,}\b/g,"***")}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval||1e4);}log(...e){this.config.debug&&console.log("[SitePong:DB]",...e);}};var U=class{constructor(e){this.profiles=[];this.activeProfile=null;this.frameStack=[];this.flushTimer=null;this.config={sampleRate:.1,maxDuration:3e4,flushInterval:3e4,...e},this.startFlushTimer();}async profile(e,t,n){if(Math.random()>(this.config.sampleRate||.1))return t();let i=this.generateId(),o=performance.now();this.activeProfile={id:i,name:e,startTime:o,duration_ms:0,frames:[],metadata:n},this.frameStack=[];let s={name:e,start_ms:0,duration_ms:0,children:[],metadata:n};this.frameStack.push(s);try{let c=await t();return s.duration_ms=performance.now()-o,this.activeProfile.duration_ms=s.duration_ms,this.activeProfile.frames=[s],s.duration_ms<=(this.config.maxDuration||3e4)&&this.profiles.push(this.activeProfile),this.activeProfile=null,this.frameStack=[],c}catch(c){throw s.duration_ms=performance.now()-o,s.metadata={...s.metadata,error:true},this.activeProfile&&(this.activeProfile.duration_ms=s.duration_ms,this.activeProfile.frames=[s],this.profiles.push(this.activeProfile)),this.activeProfile=null,this.frameStack=[],c}}startSpan(e,t){if(!this.activeProfile)return ()=>{};let n=performance.now()-this.activeProfile.startTime,i={name:e,start_ms:n,duration_ms:0,children:[],metadata:t},o=this.frameStack[this.frameStack.length-1];return o&&o.children.push(i),this.frameStack.push(i),()=>{i.duration_ms=performance.now()-this.activeProfile.startTime-i.start_ms,this.frameStack.pop();}}getProfiles(){return [...this.profiles]}getLatestProfile(){return this.profiles.length>0?this.profiles[this.profiles.length-1]:null}async flush(){if(this.profiles.length===0)return;let e=[...this.profiles];this.profiles=[];try{let t=await fetch(`${this.config.endpoint}/api/sdk/metrics`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e.map(n=>({name:`profile.${n.name}`,value:n.duration_ms,type:"distribution",unit:"ms",tags:{profile_id:n.id,frame_count:String(Ue(n.frames)),...n.metadata||{}},timestamp:new Date(Date.now()-n.duration_ms).toISOString()}))})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.log(`Flushed ${e.length} profiles`);}catch(t){this.profiles.unshift(...e),this.log("Failed to flush profiles:",t);}}async destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush();}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval||3e4);}generateId(){return `prof_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,8)}`}log(...e){this.config.debug&&console.log("[SitePong:Profiler]",...e);}};function Ue(r){let e=r.length;for(let t of r)e+=Ue(t.children);return e}var me={features:{},sampling:{errors:1,analytics:1,replay:1,performance:1},transport:{flushInterval:1e4,maxBatchSize:20,maxRetries:3},autocapture:{clicks:true,forms:true,pageviews:true,appState:true,screenViews:true},ttl:300};var Ve="sitepong_remote_config",$e="sitepong_remote_config_ts",F=class{constructor(e){this.listeners=[];this.refreshTimer=null;this.initialized=false;this.options=e,this.config={...me};}async init(){await this.loadFromCache(),this.initialized=true,this.fetchAndApply().catch(e=>{this.log("Failed to fetch remote config:",e);});}getConfig(){return this.config}isFeatureEnabled(e,t=true){return this.config.features[e]??t}onChange(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e);}}isInitialized(){return this.initialized}destroy(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.listeners=[];}async loadFromCache(){let e=this.options.storage;if(e)try{let t=await e.getItem(Ve),n=await e.getItem($e);if(t&&n){let i=Date.now()-parseInt(n,10),o=this.config.ttl*1e3;if(i<o){let s=JSON.parse(t);this.config=s,this.log("Loaded config from cache (age:",Math.round(i/1e3),"s)");}}}catch{this.log("Failed to load cached config");}}async fetchAndApply(){try{let e=ae(),t=new URLSearchParams({platform:e,...this.options.sdkVersion?{sdkVersion:this.options.sdkVersion}:{}}),n=await fetch(`${this.options.endpoint}/api/sdk/config?${t}`,{method:"GET",headers:{"X-API-Key":this.options.apiKey}});if(!n.ok)throw new Error(`HTTP ${n.status}`);let i=await n.json();this.config=i.config;for(let o of this.listeners)try{o(this.config);}catch{}await this.saveToCache(),this.scheduleRefresh(),i.config.minSdkVersion&&this.options.sdkVersion&&this.compareVersions(this.options.sdkVersion,i.config.minSdkVersion)<0&&console.warn(`[SitePong] SDK version ${this.options.sdkVersion} is outdated. Minimum recommended: ${i.config.minSdkVersion}. Please update.`),this.log("Remote config fetched successfully");}catch(e){throw this.scheduleRefresh(),e}}async saveToCache(){let e=this.options.storage;if(e)try{await e.setItem(Ve,JSON.stringify(this.config)),await e.setItem($e,String(Date.now()));}catch{this.log("Failed to cache remote config");}}scheduleRefresh(){this.refreshTimer&&clearTimeout(this.refreshTimer);let e=this.config.ttl*1e3;this.refreshTimer=setTimeout(()=>{this.fetchAndApply().catch(t=>{this.log("Refresh failed:",t);});},e);}compareVersions(e,t){let n=e.split(".").map(Number),i=t.split(".").map(Number);for(let o=0;o<3;o++){let s=n[o]||0,c=i[o]||0;if(s>c)return 1;if(s<c)return -1}return 0}log(...e){this.options.debug&&console.log("[SitePong RemoteConfig]",...e);}};var xt="https://ingest.sitepong.com";var V=class{constructor(e){this.metrics=[];this.flushTimer=null;this.flushFailures=0;this.disabled=false;this.vitals={};this.activeTransactions=new Map;this.config={endpoint:xt,enabled:true,webVitals:true,navigationTiming:true,resourceTiming:false,flushInterval:1e4,sampleRate:1,debug:false,...e},this.sampled=Math.random()<=this.config.sampleRate;}init(){!this.config.enabled||!this.sampled||typeof window>"u"||typeof window.addEventListener!="function"||(this.config.webVitals&&this.observeWebVitals(),this.config.navigationTiming&&this.collectNavigationTiming(),this.startFlushTimer(),this.log("Performance monitoring initialized"));}startTransaction(e,t){let n=`txn_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,6)}`,i={id:n,name:e,startTime:performance.now(),status:"running",spans:[],data:t};return this.activeTransactions.set(n,i),this.log("Transaction started:",e,n),n}endTransaction(e,t="ok"){let n=this.activeTransactions.get(e);if(!n){this.log("Transaction not found:",e);return}n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.status=t;for(let i of n.spans)i.status==="running"&&(i.endTime=n.endTime,i.duration=i.endTime-i.startTime,i.status=t);this.activeTransactions.delete(e),this.addMetric({type:"transaction",name:n.name,value:n.duration,unit:"ms",timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0,transaction:n}),this.log("Transaction ended:",n.name,`${n.duration.toFixed(1)}ms`);}startSpan(e,t,n){let i=this.activeTransactions.get(e);if(!i)return this.log("Transaction not found for span:",e),"";let o={id:`span_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,6)}`,name:t,startTime:performance.now(),status:"running",data:n};return i.spans.push(o),o.id}endSpan(e,t,n="ok"){let i=this.activeTransactions.get(e);if(!i)return;let o=i.spans.find(s=>s.id===t);o&&(o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.status=n);}getVitals(){return {...this.vitals}}destroy(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush();}observeWebVitals(){if(!(typeof PerformanceObserver>"u")){try{new PerformanceObserver(t=>{let n=t.getEntries(),i=n[n.length-1];i&&(this.vitals.lcp=i.startTime,this.reportVital("LCP",i.startTime));}).observe({type:"largest-contentful-paint",buffered:!0});}catch{}try{new PerformanceObserver(t=>{let n=t.getEntries()[0];if(n){let i=n.processingStart-n.startTime;this.vitals.fid=i,this.reportVital("FID",i);}}).observe({type:"first-input",buffered:!0});}catch{}try{let e=0;new PerformanceObserver(n=>{for(let i of n.getEntries()){let o=i;o.hadRecentInput||(e+=o.value);}this.vitals.cls=e;}).observe({type:"layout-shift",buffered:!0}),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&e>0&&this.reportVital("CLS",e,"score");});}catch{}try{new PerformanceObserver(t=>{let n=t.getEntries().find(i=>i.name==="first-contentful-paint");n&&(this.vitals.fcp=n.startTime,this.reportVital("FCP",n.startTime));}).observe({type:"paint",buffered:!0});}catch{}try{let e=0;new PerformanceObserver(n=>{for(let i of n.getEntries()){let o=i.duration;o>e&&(e=o,this.vitals.inp=e);}}).observe({type:"event",buffered:!0});}catch{}}}collectNavigationTiming(){if(typeof window>"u"||!window.performance||!window.location)return;let e=()=>{let t=performance.getEntriesByType("navigation")[0];if(!t)return;let n=t.responseStart-t.requestStart;this.vitals.ttfb=n,this.reportVital("TTFB",n),this.addMetric({type:"navigation",name:"page_load",value:t.loadEventEnd-t.startTime,unit:"ms",timestamp:new Date().toISOString(),url:window.location.href,data:{dns:t.domainLookupEnd-t.domainLookupStart,tcp:t.connectEnd-t.connectStart,ttfb:n,domContentLoaded:t.domContentLoadedEventEnd-t.startTime,domComplete:t.domComplete-t.startTime,transferSize:t.transferSize,encodedBodySize:t.encodedBodySize,decodedBodySize:t.decodedBodySize}});};document.readyState==="complete"?setTimeout(e,0):window.addEventListener("load",()=>setTimeout(e,0));}reportVital(e,t,n="ms"){this.addMetric({type:"web_vital",name:e,value:t,unit:n,timestamp:new Date().toISOString(),url:typeof window<"u"&&window.location?window.location.href:void 0});}addMetric(e){this.metrics.push(e);}startFlushTimer(){this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flush();});}async flush(){if(this.metrics.length===0)return;if(this.disabled){this.metrics=[];return}let e=[...this.metrics];this.metrics=[];let t=this.config.performanceEndpoint||`${this.config.endpoint}/api/performance`;try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({metrics:e})});if(!n.ok)throw new Error(`HTTP ${n.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} performance metrics`);}catch(n){if(this.flushFailures++,this.flushFailures>=3){this.disabled=true,console.warn(`[SitePong Performance] Disabled after 3 consecutive failures. Check that ${t} is accessible and has proper CORS headers.`);return}this.metrics.unshift(...e),this.log(`Failed to flush metrics (attempt ${this.flushFailures}/3):`,n);}}log(...e){this.config.debug&&console.log("[SitePong Performance]",...e);}};function ze(r){try{if(typeof crypto<"u"&&crypto.getRandomValues){let t=new Uint8Array(r);return crypto.getRandomValues(t),Array.from(t).map(n=>n.toString(16).padStart(2,"0")).join("")}}catch{}let e="";for(let t=0;t<r;t++)e+=Math.floor(Math.random()*256).toString(16).padStart(2,"0");return e}function ve(){return ze(16)}function te(){return ze(8)}function ye(){return {traceId:ve(),spanId:te(),parentSpanId:null,sampled:true}}function Z(r){let e=r.sampled?"01":"00";return {traceparent:`00-${r.traceId}-${r.spanId}-${e}`,tracestate:`sitepong=${r.spanId}`}}function Ke(r){let e=r.traceparent||r.Traceparent;if(!e)return null;let t=e.split("-");if(t.length!==4)return null;let[n,i,o,s]=t;if(n!=="00"||i.length!==32||!/^[0-9a-f]{32}$/.test(i)||o.length!==16||!/^[0-9a-f]{16}$/.test(o)||s.length!==2||!/^[0-9a-f]{2}$/.test(s))return null;let c=(parseInt(s,16)&1)===1;return {traceId:i,spanId:te(),parentSpanId:o,sampled:c}}var ee=class{constructor(e){this.originalFetch=null;this.targets=e;}shouldPropagate(e){return this.targets.some(t=>{if(t.includes("*")){let n=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(e)}return e.startsWith(t)})}injectHeaders(e,t,n){if(!this.shouldPropagate(e))return t;let i=Z(n);return {...t,...i}}start(){if(typeof window>"u"||!window.fetch||this.originalFetch)return;this.originalFetch=window.fetch;let e=this;window.fetch=function(t,n){let i=typeof t=="string"?t:t instanceof URL?t.toString():t.url;if(e.shouldPropagate(i)){let o=ye(),s=Z(o),c={};if(n?.headers)if(n.headers instanceof Headers)n.headers.forEach((f,g)=>{c[g]=f;});else if(Array.isArray(n.headers))for(let[f,g]of n.headers)c[f]=g;else Object.assign(c,n.headers);let l={...c,...s},d={...n,headers:l};return e.originalFetch.call(window,t,d)}return e.originalFetch.call(window,t,n)};}stop(){typeof window>"u"||this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null);}};function kt(){if(b())return;let r=globalThis,e=typeof r.window<"u"&&typeof r.document<"u",t=!e&&!!r.process?.versions?.node,n=e?"browser":"node";A({platform:n,storage:null,getDeviceInfo(){let o={platform:n};return r.navigator?.userAgent&&(o.userAgent=r.navigator.userAgent),e&&r.window?.screen&&(o.screenWidth=r.window.screen.width,o.screenHeight=r.window.screen.height),t&&r.process&&(o.osName=r.process.platform,o.osVersion=r.process.versions?.node),o},getCurrentUrl(){return r.window?.location?.href??void 0},getReferrer(){return r.document?.referrer||void 0},getUserAgent(){if(r.navigator?.userAgent)return r.navigator.userAgent;if(t&&r.process)return `SitePong-Node/${r.process.versions?.node} (${r.process.platform})`},onUncaughtError(o){if(e&&r.window?.addEventListener){let s=c=>o(c.error||c.message);return r.window.addEventListener("error",s),()=>r.window?.removeEventListener?.("error",s)}if(t&&r.process?.on&&r.process.off){let s=c=>o(c);return r.process.on("uncaughtException",s),()=>r.process?.off?.("uncaughtException",s)}return ()=>{}},onUnhandledRejection(o){if(e&&r.window?.addEventListener){let s=c=>o(c.reason);return r.window.addEventListener("unhandledrejection",s),()=>r.window?.removeEventListener?.("unhandledrejection",s)}if(t&&r.process?.on&&r.process.off){let s=c=>o(c);return r.process.on("unhandledRejection",s),()=>r.process?.off?.("unhandledRejection",s)}return ()=>{}},onBeforeTerminate(o){return e&&r.window?.addEventListener?(r.window.addEventListener("beforeunload",o),()=>r.window?.removeEventListener?.("beforeunload",o)):t&&r.process?.on&&r.process.off?(r.process.on("beforeExit",o),r.process.on("SIGINT",o),r.process.on("SIGTERM",o),()=>{r.process?.off?.("beforeExit",o),r.process?.off?.("SIGINT",o),r.process?.off?.("SIGTERM",o);}):()=>{}},onVisibilityHidden(o){if(r.document?.addEventListener){let s=()=>{r.document?.visibilityState==="hidden"&&o();};return r.document.addEventListener("visibilitychange",s),()=>r.document?.removeEventListener?.("visibilitychange",s)}return ()=>{}},sendBeacon(o,s){if(typeof r.navigator?.sendBeacon!="function")return false;try{return r.navigator.sendBeacon(o,new Blob([s],{type:"application/json"}))}catch{return false}}});}kt();var k={};function qe(r){k={...k,...r};}var m="https://ingest.sitepong.com",Et=10,Ct=5e3,be=3,we=class{constructor(){this.errorQueue=[];this.flushTimer=null;this.context={};this.initialized=false;this.flushFailures=0;this.disabled=false;this.flagManager=null;this.analyticsManager=null;this.fingerprintManager=null;this.replayManager=null;this.performanceManager=null;this.cronManager=null;this.metricsManager=null;this.databaseTracker=null;this.profiler=null;this.remoteConfigManager=null;this.envUnsubs=[];this.identifyHooks=[];this.config={apiKey:"",endpoint:m,environment:"production",release:"",autoCapture:true,maxBatchSize:Et,flushInterval:Ct,debug:false};}init(e){if(!e.apiKey){console.error("[SitePong] API key is required");return}if(this.config={...this.config,...e},this.initialized=true,this.config.autoCapture&&this.setupAutoCapture(),this.startFlushTimer(),this.log("Initialized with endpoint:",this.config.endpoint),e.enableFlags&&(this.flagManager=new I({apiKey:e.apiKey,endpoint:e.flagsEndpoint||e.endpoint||m,debug:e.debug}),this.flagManager.init().catch(t=>{this.log("Failed to initialize flags:",t);})),e.analytics?.enabled&&(this.analyticsManager&&this.analyticsManager.destroy(),this.analyticsManager=new P({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,autocapturePageviews:e.analytics.autocapturePageviews,autocaptureClicks:e.analytics.autocaptureClicks,autocaptureForms:e.analytics.autocaptureForms,autocapture:e.analytics.autocapture,maxBatchSize:e.analytics.maxBatchSize,flushInterval:e.analytics.flushInterval,eventsEndpoint:e.analytics.eventsEndpoint,debug:e.debug}),this.analyticsManager.init()),e.fingerprint?.enabled&&k.createFingerprint?this.fingerprintManager=k.createFingerprint({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,extendedSignals:e.fingerprint.extendedSignals,visitorEndpoint:e.fingerprint.visitorEndpoint,debug:e.debug}):e.fingerprint?.enabled&&this.log("Fingerprint requested but not available on this platform (web only)."),e.performance?.enabled&&k.createPerformance?(this.performanceManager&&this.performanceManager.destroy(),this.performanceManager=k.createPerformance({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,webVitals:e.performance.webVitals,navigationTiming:e.performance.navigationTiming,resourceTiming:e.performance.resourceTiming,sampleRate:e.performance.sampleRate,flushInterval:e.performance.flushInterval,performanceEndpoint:e.performance.performanceEndpoint,debug:e.debug}),this.performanceManager.init()):e.performance?.enabled&&this.log("Performance requested but not available on this platform (web only)."),e.replay?.enabled&&k.createReplay?(this.replayManager&&this.replayManager.stop(),this.replayManager=k.createReplay({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,maskInputs:e.replay.maskInputs,blockSelector:e.replay.blockSelector,maskSelector:e.replay.maskSelector,sampleRate:e.replay.sampleRate,maxSessionDuration:e.replay.maxSessionDuration,flushInterval:e.replay.flushInterval,replayEndpoint:e.replay.replayEndpoint,recordNetwork:e.replay.recordNetwork,captureNetworkHeaders:e.replay.captureNetworkHeaders,recordConsole:e.replay.recordConsole,consoleLevels:e.replay.consoleLevels,bufferDuration:e.replay.bufferDuration,debug:e.debug}),this.replayManager.start()):e.replay?.enabled&&this.log("Replay requested but not available on this platform (web only)."),e.crons?.enabled&&(this.cronManager=new O({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug})),e.database?.enabled&&(this.databaseTracker=new B({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,slowQueryThreshold:e.database.slowQueryThreshold,redactParams:e.database.redactParams})),e.metrics?.enabled&&(this.metricsManager=new H({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,flushInterval:e.metrics.flushInterval,maxBatchSize:e.metrics.maxBatchSize})),e.profiling?.enabled&&(this.profiler=new U({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,sampleRate:e.profiling.sampleRate,maxDuration:e.profiling.maxDuration,flushInterval:e.profiling.flushInterval})),e.remoteConfig?.enabled!==false){let t=e._storageAdapter||le();this.remoteConfigManager=new F({apiKey:e.apiKey,endpoint:e.endpoint||m,storage:t,debug:e.debug}),this.remoteConfigManager.init().catch(n=>{this.log("Failed to initialize remote config:",n);});}}initRN(e){if(!e.apiKey){console.error("[SitePong] API key is required");return}if(this.config={...this.config,...e},this.initialized=true,this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval),this.log("Initialized (React Native) with endpoint:",this.config.endpoint),e.enableFlags&&(this.flagManager=new I({apiKey:e.apiKey,endpoint:e.flagsEndpoint||e.endpoint||m,debug:e.debug}),this.flagManager.init().catch(t=>{this.log("Failed to initialize flags:",t);})),e.analytics?.enabled&&(this.analyticsManager&&this.analyticsManager.destroy(),this.analyticsManager=new P({apiKey:e.apiKey,endpoint:e.endpoint||m,enabled:true,maxBatchSize:e.analytics.maxBatchSize,flushInterval:e.analytics.flushInterval,eventsEndpoint:e.analytics.eventsEndpoint,debug:e.debug}),this.analyticsManager.initHeadless()),e.crons?.enabled&&(this.cronManager=new O({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug})),e.metrics?.enabled&&(this.metricsManager=new H({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,flushInterval:e.metrics.flushInterval,maxBatchSize:e.metrics.maxBatchSize})),e.database?.enabled&&(this.databaseTracker=new B({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,slowQueryThreshold:e.database.slowQueryThreshold,redactParams:e.database.redactParams})),e.profiling?.enabled&&(this.profiler=new U({apiKey:e.apiKey,endpoint:e.endpoint||m,debug:e.debug,sampleRate:e.profiling.sampleRate,maxDuration:e.profiling.maxDuration,flushInterval:e.profiling.flushInterval})),e.remoteConfig?.enabled!==false){let t=e._storageAdapter||le();this.remoteConfigManager=new F({apiKey:e.apiKey,endpoint:e.endpoint||m,storage:t,debug:e.debug}),this.remoteConfigManager.init().catch(n=>{this.log("Failed to initialize remote config:",n);});}}isInitialized(){return this.initialized}getFlag(e,t=false){return this.flagManager?this.flagManager.getFlag(e,t):(this.log("Flags not enabled. Set enableFlags: true in init()"),t)}getAllFlags(){return this.flagManager?this.flagManager.getAllFlags():{}}async waitForFlags(){this.flagManager&&await this.flagManager.waitForInit();}areFlagsReady(){return this.flagManager?.isInitialized()??false}getVariant(e,t=null){return this.flagManager?this.flagManager.getVariant(e,t):(this.log("Flags not enabled. Set enableFlags: true in init()"),t)}getVariantPayload(e,t=null){return this.flagManager?this.flagManager.getVariantPayload(e,t):t}async refreshFlags(){this.flagManager&&await this.flagManager.refresh();}track(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.track(e,t);}trackPageView(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.trackPageView(e,t);}identify(e,t){this.replayManager&&this.replayManager.setUser({id:e});for(let n of this.identifyHooks)try{n(e);}catch(i){this.log("identify hook failed:",i);}if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.identify(e,t);}registerIdentifyHook(e){return this.identifyHooks.push(e),()=>{let t=this.identifyHooks.indexOf(e);t>=0&&this.identifyHooks.splice(t,1);}}group(e,t){if(!this.analyticsManager){this.log("Analytics not enabled. Set analytics.enabled: true in init()");return}this.analyticsManager.group(e,t);}resetAnalytics(){this.analyticsManager&&this.analyticsManager.reset();}async getVisitorId(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getVisitorId()}async getDeviceSignals(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getDeviceSignals()}async getFraudCheck(){if(!this.fingerprintManager)throw new Error("Fingerprint not enabled. Set fingerprint.enabled: true in init()");return this.fingerprintManager.getFraudCheck()}startReplay(){return this.replayManager?this.replayManager.start():(this.log("Replay not enabled. Set replay.enabled: true in init()"),false)}stopReplay(){this.replayManager&&this.replayManager.stop();}isReplayRecording(){return this.replayManager?.isRecording()??false}getReplaySessionId(){return this.replayManager?.getSessionId()??null}startTransaction(e,t){return this.performanceManager?this.performanceManager.startTransaction(e,t):(this.log("Performance not enabled. Set performance.enabled: true in init()"),"")}endTransaction(e,t="ok"){this.performanceManager&&this.performanceManager.endTransaction(e,t);}startSpan(e,t,n){return this.performanceManager?this.performanceManager.startSpan(e,t,n):""}endSpan(e,t,n="ok"){this.performanceManager&&this.performanceManager.endSpan(e,t,n);}getWebVitals(){return this.performanceManager?this.performanceManager.getVitals():{}}cronCheckin(e,t){return this.cronManager?this.cronManager.checkin(e,t):(this.log("Cron monitoring not enabled. Set crons.enabled: true in init()"),Promise.resolve())}cronStart(e,t){return this.cronManager?this.cronManager.start(e,t):(this.log("Cron monitoring not enabled. Set crons.enabled: true in init()"),{ok:()=>Promise.resolve(),error:()=>Promise.resolve()})}cronWrap(e,t,n){return this.cronManager?this.cronManager.wrap(e,t,n):t()}metricIncrement(e,t,n){if(!this.metricsManager){this.log("Metrics not enabled. Set metrics.enabled: true in init()");return}this.metricsManager.increment(e,t,n);}metricGauge(e,t,n){this.metricsManager&&this.metricsManager.gauge(e,t,n);}metricHistogram(e,t,n){this.metricsManager&&this.metricsManager.histogram(e,t,n);}metricDistribution(e,t,n){this.metricsManager&&this.metricsManager.distribution(e,t,n);}async metricTime(e,t,n){return this.metricsManager?this.metricsManager.time(e,t,n):t()}metricStartTimer(e,t){return this.metricsManager?this.metricsManager.startTimer(e,t):{stop:()=>{}}}async flushMetrics(){if(this.metricsManager)return this.metricsManager.flush()}async dbTrack(e,t,n){return this.databaseTracker?this.databaseTracker.track(e,t,n):t()}dbTrackSync(e,t,n){return this.databaseTracker?this.databaseTracker.trackSync(e,t,n):t()}getDbQueryCount(){return this.databaseTracker?this.databaseTracker.getQueryCount():0}resetDbQueryCount(){this.databaseTracker&&this.databaseTracker.resetQueryCount();}getDbNPlusOnePatterns(){return this.databaseTracker?this.databaseTracker.getNPlusOnePatterns():[]}async profile(e,t,n){return this.profiler?this.profiler.profile(e,t,n):t()}startProfileSpan(e,t){return this.profiler?this.profiler.startSpan(e,t):()=>{}}getProfiles(){return this.profiler?this.profiler.getProfiles():[]}getLatestProfile(){return this.profiler?this.profiler.getLatestProfile():null}async flushProfiles(){if(this.profiler)return this.profiler.flush()}getRemoteConfig(){return this.remoteConfigManager?.getConfig()??null}isRemoteConfigFeatureEnabled(e,t=true){return this.remoteConfigManager?.isFeatureEnabled(e,t)??t}onRemoteConfigChange(e){return this.remoteConfigManager?this.remoteConfigManager.onChange(e):()=>{}}setContext(e){this.context={...this.context,...e};}setUser(e){this.context.user=e,this.replayManager&&this.replayManager.setUser(e?{id:e.id}:null);}setTags(e){this.context.tags={...this.context.tags,...e};}clearUser(){this.context.user=void 0,this.replayManager&&this.replayManager.setUser(null);}addBreadcrumb(e){this.log("Breadcrumb added:",e);}captureError(e,t){if(!this.initialized){console.warn("[SitePong] SDK not initialized. Call init() first.");return}let n=this.formatError(e,t);this.errorQueue.push(n),this.log("Captured error:",n.message),this.replayManager?.isRecording()&&this.replayManager.flushOnError().catch(i=>{this.log("Failed to flush replay on error:",i);}),this.errorQueue.length>=this.config.maxBatchSize&&this.flush();}captureMessage(e,t="info",n){if(!this.initialized){console.warn("[SitePong] SDK not initialized. Call init() first.");return}let i={message:e,type:t,timestamp:new Date().toISOString(),url:this.getUrl(),userAgent:this.getUserAgent(),environment:this.config.environment,release:this.config.release,context:{...this.context,...n},replaySessionId:this.replayManager?.isRecording()&&this.replayManager.getSessionId()||void 0};this.errorQueue.push(i),this.log("Captured message:",e),this.errorQueue.length>=this.config.maxBatchSize&&this.flush();}async flush(){if(this.errorQueue.length===0)return;if(this.disabled){this.errorQueue=[];return}let e=[...this.errorQueue];this.errorQueue=[];try{let t=await fetch(`${this.config.endpoint}/api/errors/batch`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.config.apiKey},body:JSON.stringify({errors:e})});if(!t.ok)throw new Error(`HTTP ${t.status}`);this.flushFailures=0,this.log(`Flushed ${e.length} errors`);}catch(t){if(this.flushFailures++,this.flushFailures>=be){this.disabled=true,console.warn(`[SitePong] SDK disabled after ${be} consecutive failures. Events will no longer be sent. This may be due to CORS issues or network problems. Check that ${this.config.endpoint} is accessible and has proper CORS headers.`);return}this.errorQueue.unshift(...e),this.log(`Failed to flush errors (attempt ${this.flushFailures}/${be}):`,t);}}formatError(e,t){let n=e instanceof Error,i=n?e.message:String(e),o=n?e.stack:new Error(i).stack,s=n?e.name:"Error";return {message:i,stack:o,type:s,timestamp:new Date().toISOString(),url:this.getUrl(),userAgent:this.getUserAgent(),environment:this.config.environment,release:this.config.release,context:{...this.context,...t},fingerprint:this.generateFingerprint(i,o,s),replaySessionId:this.replayManager?.isRecording()&&this.replayManager.getSessionId()||void 0}}generateFingerprint(e,t,n){let i=n||"Error",o=this.normalizeMessage(e),s=t?this.extractTopFrame(t):"",c=[i,o,s].join(`
|
|
2
2
|
`),l=2166136261;for(let d=0;d<c.length;d++)l^=c.charCodeAt(d),l=Math.imul(l,16777619);return (l>>>0).toString(16).padStart(8,"0")}normalizeMessage(e){return e.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,"<uuid>").replace(/\b0x[0-9a-f]{4,}\b/gi,"<hex>").replace(/\b[0-9a-f]{8,}\b/gi,"<hex>").replace(/https?:\/\/[^\s)"']+/g,"<url>").replace(/\b\d+(\.\d+)?\b/g,"<n>").replace(/\s+/g," ").trim()}extractTopFrame(e){let t=e.split(`
|
|
3
3
|
`);for(let n=1;n<t.length;n++){let i=t[n].trim();if(i&&(i.startsWith("at ")||/^\w+@/.test(i)))return i.replace(/:\d+\)?\s*$/,")")}return ""}setupAutoCapture(){let e=b();e&&(this.envUnsubs.push(e.onUncaughtError(t=>{let n=t instanceof Error?t:new Error(String(t));this.captureError(n);})),this.envUnsubs.push(e.onUnhandledRejection(t=>{let n=t instanceof Error?t:new Error(String(t));this.captureError(n);})),this.log("Auto-capture enabled for",e.platform));}startFlushTimer(){this.flushTimer&&clearInterval(this.flushTimer),this.flushTimer=setInterval(()=>{this.flush();},this.config.flushInterval);let e=b();e&&(this.envUnsubs.push(e.onBeforeTerminate(()=>this.flush())),this.envUnsubs.push(e.onVisibilityHidden(()=>this.flushWithBeacon())));}flushWithBeacon(){if(this.errorQueue.length===0)return;let e=b();if(!e||!e.sendBeacon)return;let t=[...this.errorQueue];this.errorQueue=[];let n=JSON.stringify({errors:t,apiKey:this.config.apiKey});e.sendBeacon(`${this.config.endpoint}/api/errors/batch`,n)?this.log(`Flushed ${t.length} errors via beacon`):this.errorQueue.unshift(...t);}setCurrentScreen(e){this.currentScreen=e,ce(()=>this.currentScreen);}getUrl(){let e=b();return e?e.getCurrentUrl()??this.currentScreen??void 0:this.currentScreen??void 0}getUserAgent(){let e=b();if(e)return e.getUserAgent()}log(...e){this.config.debug&&console.log("[SitePong]",...e);}},a=new we,mr=a.init.bind(a),vr=a.initRN.bind(a),yr=a.captureError.bind(a),br=a.captureMessage.bind(a),wr=a.setContext.bind(a),Sr=a.setUser.bind(a),Tr=a.setTags.bind(a),xr=a.flush.bind(a),kr=a.isInitialized.bind(a),Er=a.clearUser.bind(a),Cr=a.addBreadcrumb.bind(a),Mr=a.setCurrentScreen.bind(a);var Rr=a.getFlag.bind(a),Ir=a.getAllFlags.bind(a),Pr=a.getVariant.bind(a),Fr=a.getVariantPayload.bind(a),Dr=a.waitForFlags.bind(a),Ar=a.areFlagsReady.bind(a),_r=a.refreshFlags.bind(a),Lr=a.track.bind(a),Nr=a.trackPageView.bind(a),Or=a.identify.bind(a),Hr=a.group.bind(a),Br=a.resetAnalytics.bind(a),Ur=a.getVisitorId.bind(a),Vr=a.getDeviceSignals.bind(a),$r=a.getFraudCheck.bind(a),zr=a.startReplay.bind(a),Kr=a.stopReplay.bind(a),qr=a.isReplayRecording.bind(a),Wr=a.getReplaySessionId.bind(a),Gr=a.startTransaction.bind(a),Xr=a.endTransaction.bind(a),jr=a.startSpan.bind(a),Qr=a.endSpan.bind(a),Yr=a.getWebVitals.bind(a),Jr=a.dbTrack.bind(a),Zr=a.dbTrackSync.bind(a),ei=a.getDbQueryCount.bind(a),ti=a.resetDbQueryCount.bind(a),ni=a.getDbNPlusOnePatterns.bind(a),ri=a.cronCheckin.bind(a),ii=a.cronStart.bind(a),oi=a.cronWrap.bind(a),si=a.metricIncrement.bind(a),ai=a.metricGauge.bind(a),ci=a.metricHistogram.bind(a),li=a.metricDistribution.bind(a),ui=a.metricTime.bind(a),di=a.metricStartTimer.bind(a),fi=a.flushMetrics.bind(a),pi=a.profile.bind(a),gi=a.startProfileSpan.bind(a),hi=a.getProfiles.bind(a),mi=a.getLatestProfile.bind(a),vi=a.flushProfiles.bind(a),yi=a.getRemoteConfig.bind(a),bi=a.isRemoteConfigFeatureEnabled.bind(a),wi=a.onRemoteConfigChange.bind(a),Si=a.registerIdentifyHook.bind(a),Mt=a;var Xe=0,We=new WeakMap;function Rt(){Xe=0;}function y(r){let e=We.get(r);return e===void 0&&(e=++Xe,We.set(r,e)),e}var je=new Set(["script","noscript"]),It=new Set(["src","href","action","poster"]),Qe=["display","visibility","opacity","position","top","right","bottom","left","z-index","float","clear","width","height","min-width","min-height","max-width","max-height","margin-top","margin-right","margin-bottom","margin-left","padding-top","padding-right","padding-bottom","padding-left","border-top-width","border-right-width","border-bottom-width","border-left-width","border-top-style","border-right-style","border-bottom-style","border-left-style","border-top-color","border-right-color","border-bottom-color","border-left-color","border-radius","background-color","background-image","background-size","background-position","color","font-family","font-size","font-weight","font-style","line-height","letter-spacing","text-align","text-decoration","text-transform","overflow","overflow-x","overflow-y","flex-direction","flex-wrap","justify-content","align-items","align-self","flex-grow","flex-shrink","flex-basis","gap","grid-template-columns","grid-template-rows","transform","box-shadow","text-shadow","cursor","white-space","word-break","box-sizing"],$=null,S=null;function Pt(r){if(typeof document>"u")return {};$||($=new Map);let e=$.get(r);if(e)return e;try{S||(S=document.createElement("iframe"),S.style.cssText="position:fixed;top:-9999px;left:-9999px;width:0;height:0;border:none;visibility:hidden;",document.body.appendChild(S));let t=S.contentDocument;if(!t)return {};let n=t.createElement(r);t.body.appendChild(n);let i=t.defaultView.getComputedStyle(n),o={};for(let s of Qe)o[s]=i.getPropertyValue(s);return t.body.removeChild(n),$.set(r,o),o}catch{return {}}}function Se(r){if(typeof window>"u")return null;try{let e=r.tagName.toLowerCase();if(je.has(e)||e==="head"||e==="html"||e==="meta"||e==="link"||e==="title")return null;let t=window.getComputedStyle(r),n=Pt(e),i=[];for(let o of Qe){let s=t.getPropertyValue(o);s&&s!==n[o]&&i.push(`${o}:${s}`);}return i.length>0?i.join(";"):null}catch{return null}}var C=new Map;async function Ye(r){if(C.has(r))return C.get(r)??null;try{let e=await fetch(r,{mode:"cors"});if(!e.ok)return C.set(r,null),null;let t=await e.text(),n=ne(t,r);return C.set(r,n),n}catch{return C.set(r,null),null}}function Ft(r){return C.get(r)??null}function Je(){S&&S.parentNode&&S.parentNode.removeChild(S),S=null,$=null,C.clear();}function Ze(r,e){if(!r||r.startsWith("data:")||r.startsWith("blob:")||r.startsWith("#"))return r;try{return new URL(r,e).href}catch{return r}}function ne(r,e){return r.replace(/url\(\s*(['"]?)([^'")]+)\1\s*\)/g,(t,n,i)=>{let o=i.trim();if(o.startsWith("data:")||o.startsWith("blob:")||o.startsWith("http://")||o.startsWith("https://")||o.startsWith("//"))return `url(${n}${o}${n})`;try{let s=new URL(o,e).href;return `url(${n}${s}${n})`}catch{return `url(${n}${o}${n})`}})}function Ge(r){try{let e=r.cssRules,t="";for(let n=0;n<e.length;n++)t+=e[n].cssText+`
|
|
4
4
|
`;return t}catch{return null}}function re(r){let e=r.tagName.toLowerCase(),t=location.href;if(e==="style"){let n=r;if(n.sheet){let o=Ge(n.sheet);if(o!==null)return ne(o,t)}let i=r.textContent||"";return i?ne(i,t):null}if(e==="link"){let n=r;if(n.rel!=="stylesheet")return null;let i=n.href||t;if(n.sheet){let o=Ge(n.sheet);if(o!==null)return ne(o,i)}if(n.href){let o=Ft(n.href);if(o)return o}return null}return null}function Dt(r,e){return r.split(",").map(t=>{let n=t.trim().split(/\s+/);return n[0]&&(n[0]=Ze(n[0],e)),n.join(" ")}).join(", ")}function ie(r,e,t=false){let n=y(r);if(r.nodeType===Node.TEXT_NODE){let i=r.parentElement,o=r.textContent||"";return i&&e.maskSelector&&i.matches(e.maskSelector)&&(o=o.replace(/\S/g,"*")),{id:n,type:"text",textContent:o}}if(r.nodeType===Node.COMMENT_NODE)return {id:n,type:"comment",textContent:""};if(r.nodeType===Node.ELEMENT_NODE){let i=r,o=i;if(e.blockSelector&&i.matches(e.blockSelector))return {id:n,type:"element",tagName:"div",attributes:{"data-blocked":"true",style:`width:${o.offsetWidth}px;height:${o.offsetHeight}px;background:#f0f0f0;`}};let s=i.tagName.toLowerCase();if(je.has(s))return null;let c=t||s==="svg"||i instanceof SVGElement,l={},d=location.href;for(let u=0;u<i.attributes.length;u++){let p=i.attributes[u],h=p.name,v=p.value;h.startsWith("on")||v&&v.toLowerCase().startsWith("javascript:")||(It.has(h)&&(v=Ze(v,d)),h==="srcset"&&(v=Dt(v,d)),l[h]=v);}if(s==="style"||s==="link"&&i.getAttribute("rel")==="stylesheet"){let u=re(i);u&&(l._cssText=u);}if(!c&&s!=="style"&&s!=="link"){let u=Se(i);u&&(l._computedStyle=u);}if(s==="input"){let u=i,p=(u.type||"").toLowerCase();if(p==="checkbox"||p==="radio")l._checked=String(u.checked);else {let h=e.maskInputs?"***":u.value;h&&(l._value=h);}}else if(s==="textarea"){let u=i,p=e.maskInputs?"***":u.value;p&&(l._value=p);}else if(s==="select"){let u=i;l._selectedIndex=String(u.selectedIndex);}if(s==="canvas")try{let p=i.toDataURL("image/webp",.4);p&&p!=="data:,"&&(l._canvasDataUrl=p);}catch{}e.maskSelector&&i.matches(e.maskSelector);let f=[];for(let u of Array.from(i.childNodes)){let p=ie(u,e,c);p&&f.push(p);}let g={id:n,type:"element",tagName:s,attributes:Object.keys(l).length>0?l:void 0,children:f.length>0?f:void 0};return c&&(g.isSVG=true),g}return null}function oe(r){if(typeof document>"u")return null;Rt();let e=ie(document.documentElement,r);return e?{_version:2,doctype:document.doctype?`<!DOCTYPE ${document.doctype.name}>`:void 0,html:e,width:window.innerWidth,height:window.innerHeight}:null}var se=["authorization","cookie","set-cookie","x-api-key","x-auth-token"],z=class{constructor(e,t){this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null;this.active=false;this.callback=e,this.captureHeaders=t?.captureHeaders??false,this.urlFilter=t?.urlFilter;}start(){this.active||typeof window>"u"||(this.active=true,this.interceptFetch(),this.interceptXHR());}stop(){this.active&&(this.active=false,this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null));}interceptFetch(){if(typeof window.fetch!="function")return;this.originalFetch=window.fetch;let e=this;window.fetch=async function(t,n){let i=typeof t=="string"?t:t instanceof URL?t.toString():t.url;if(e.urlFilter&&!e.urlFilter(i))return e.originalFetch.call(window,t,n);let o=Date.now(),s=n?.method||(t instanceof Request?t.method:"GET"),c;n?.body&&(typeof n.body=="string"?c=n.body.length:n.body instanceof Blob&&(c=n.body.size));try{let l=await e.originalFetch.call(window,t,n),d=Date.now()-o,f={method:s.toUpperCase(),url:e.truncateUrl(i),status:l.status,statusText:l.statusText,duration:d,requestSize:c,initiator:"fetch"};return e.captureHeaders&&(f.requestHeaders=e.safeHeaders(n?.headers),f.responseHeaders=e.headersToObject(l.headers)),e.emit(f),l}catch(l){let d=Date.now()-o;throw e.emit({method:s.toUpperCase(),url:e.truncateUrl(i),duration:d,requestSize:c,error:l instanceof Error?l.message:"Network error",initiator:"fetch"}),l}};}interceptXHR(){if(typeof XMLHttpRequest>"u")return;this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this;XMLHttpRequest.prototype.open=function(t,n,...i){return this._spMethod=t,this._spUrl=typeof n=="string"?n:n.toString(),e.originalXhrOpen.apply(this,[t,n,...i])},XMLHttpRequest.prototype.send=function(t){let n=this,i=n._spUrl;if(e.urlFilter&&!e.urlFilter(i))return e.originalXhrSend.call(this,t);let o=Date.now(),s;typeof t=="string"&&(s=t.length);let c=()=>{let l=Date.now()-o,d;try{n.responseType===""||n.responseType==="text"?d=n.responseText?.length:n.responseType==="json"&&n.response!=null?d=JSON.stringify(n.response).length:n.responseType==="arraybuffer"&&n.response?d=n.response.byteLength:n.responseType==="blob"&&n.response&&(d=n.response.size);}catch{}let f={method:(n._spMethod||"GET").toUpperCase(),url:e.truncateUrl(i),status:n.status,statusText:n.statusText,duration:l,requestSize:s,responseSize:d,initiator:"xhr"};n.status===0&&(f.error="Network error"),e.emit(f),n.removeEventListener("loadend",c);};return n.addEventListener("loadend",c),e.originalXhrSend.call(this,t)};}emit(e){this.active&&this.callback({type:"network",timestamp:Date.now(),data:e});}truncateUrl(e){try{let t=new URL(e,window.location.origin),n=t.pathname+t.search;return n.length>500?n.slice(0,500)+"...":t.origin+n}catch{return e.length>500?e.slice(0,500)+"...":e}}safeHeaders(e){if(!e)return;let t={};if(e instanceof Headers)e.forEach((n,i)=>{t[i]=se.includes(i.toLowerCase())?"[REDACTED]":n;});else if(Array.isArray(e))for(let[n,i]of e)t[n]=se.includes(n.toLowerCase())?"[REDACTED]":i;else for(let[n,i]of Object.entries(e))t[n]=se.includes(n.toLowerCase())?"[REDACTED]":i;return t}headersToObject(e){let t={};return e.forEach((n,i)=>{t[i]=se.includes(i.toLowerCase())?"[REDACTED]":n;}),t}};var K=class{constructor(e,t){this.originals={};this.active=false;this.callback=e,this.levels=t?.levels||["log","info","warn","error","debug"];}start(){if(!(this.active||typeof console>"u")){this.active=true;for(let e of this.levels)this.originals[e]=console[e].bind(console),console[e]=(...t)=>{this.originals[e](...t),this.record(e,t);};}}stop(){if(this.active){this.active=false;for(let e of this.levels)this.originals[e]&&(console[e]=this.originals[e]);this.originals={};}}record(e,t){if(!this.active||t.length>0&&typeof t[0]=="string"&&t[0].startsWith("[SitePong"))return;let n=t.slice(0,10).map(o=>this.serialize(o)),i={level:e,args:n};if(e==="error"){let o=this.getStackTrace();o&&(i.trace=o.slice(0,2e3));}this.callback({type:"console",timestamp:Date.now(),data:i});}serialize(e){if(e===null)return "null";if(e===void 0)return "undefined";if(e instanceof Error)return `Error: ${e.message}${e.stack?`
|