@wetusco/wts-web-sdk 0.1.0-alpha.2 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and Semantic Versioning.
4
4
 
5
+ ## 0.2.0-alpha.1
6
+
7
+ - Added consent-gated `identify`, `updateUser`, `setReportedAttribution`, and `resetIdentity`.
8
+ - Added a durable identity mutation queue that flushes before product events.
9
+ - Added Web Protocol V3 collector support while retaining V2 server compatibility.
10
+ - Preserved opaque external user IDs and added native `Date` attribute support.
11
+ - Fixed IndexedDB queue eviction and retryable identity rejection scheduling.
12
+
5
13
  ## [0.1.0-alpha.2] - 2026-07-16
6
14
 
7
15
  ### Changed
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Consent-first browser measurement and deterministic wts.is link attribution. The SDK is dependency-free, safe to import during server rendering, and never collects DOM content, form values, URL queries, fragments, advertising identifiers, or fingerprints.
4
4
 
5
- > `0.1.0-alpha.2` is an early integration release using wts.is Web Protocol V2.
5
+ > `0.2.0-alpha.1` adds consent-gated identity through Web Protocol V3 while retaining the existing page, event, and deterministic attribution behavior.
6
6
 
7
7
  ## Requirements
8
8
 
@@ -45,8 +45,8 @@ Use a versioned artifact and the SRI value shipped next to it. Do not use an unv
45
45
 
46
46
  ```html
47
47
  <script
48
- src="https://cdn.jsdelivr.net/npm/@wetusco/wts-web-sdk@0.1.0-alpha.2/dist/wts-web.iife.min.js"
49
- integrity="sha384-yd6nOlkavObZDFnbLq8jTn6bMrD8gIU+Er4oOqzNTa2Mo2VnD6wPG8VFZqVMIKyC"
48
+ src="https://cdn.jsdelivr.net/npm/@wetusco/wts-web-sdk@0.2.0-alpha.1/dist/wts-web.iife.min.js"
49
+ integrity="sha384-ahc9V9IOmrRpKErCHoXwXF8o78RvGqtJgDgHO2UEPjxqsj8RzvVuQugsK5IO4brh"
50
50
  crossorigin="anonymous"
51
51
  ></script>
52
52
  <script>
@@ -68,6 +68,34 @@ The IIFE exports `window.WtsWeb`. The release workflow records the exact SHA-384
68
68
 
69
69
  Calls to `page` and `track` while pending or denied return an explicit no-op result. They are never retained in memory for later delivery.
70
70
 
71
+ ## User identity and reported attribution
72
+
73
+ Identity operations use the same consent decision and are persisted ahead of product events. Use a stable, opaque internal customer ID rather than an email address. The ID is case-sensitive and is never trimmed or normalized by the SDK.
74
+
75
+ ```ts
76
+ await wts.identify("customer_1842", {
77
+ email: "user@example.com",
78
+ plan: "enterprise",
79
+ created_at: new Date("2026-07-16T10:00:00.000Z"),
80
+ });
81
+
82
+ await wts.updateUser({
83
+ set: { plan: "business" },
84
+ setOnce: { signup_channel: "partner" },
85
+ increment: { lifetime_orders: 1 },
86
+ });
87
+
88
+ await wts.setReportedAttribution({
89
+ source: "newsletter",
90
+ medium: "email",
91
+ campaign: "summer_2026",
92
+ });
93
+
94
+ await wts.resetIdentity(); // call on logout
95
+ ```
96
+
97
+ `resetIdentity()` closes the current profile binding and rotates the anonymous and session identities. Setting consent to `denied` clears all browser SDK storage and stops collection.
98
+
71
99
  The anonymous identity is first-party and persistent. The session identity and bootstrap idempotency key live in `sessionStorage`, so full-page navigations in the same browser session do not inflate session counts.
72
100
 
73
101
  ## Page tracking
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var y="0.1.0-alpha.2";var S="_wts";function c(){let n=globalThis.crypto;if(!n)throw new Error("A secure random number generator is required.");if(typeof n.randomUUID=="function")return n.randomUUID();let t=n.getRandomValues(new Uint8Array(16));t[6]=t[6]&15|64,t[8]=t[8]&63|128;let e=Array.from(t,i=>i.toString(16).padStart(2,"0"));return `${e.slice(0,4).join("")}-${e.slice(4,6).join("")}-${e.slice(6,8).join("")}-${e.slice(8,10).join("")}-${e.slice(10).join("")}`}function m(n){return new TextEncoder().encode(JSON.stringify(n)).byteLength}function g(){return typeof navigator>"u"?"en":navigator.language||"en"}function k(){if(!(typeof document>"u"||!document.referrer))try{return new URL(document.referrer).hostname.toLowerCase()||void 0}catch{return}}function v(n,t){n&&typeof console<"u"&&console.warn(`[wts.is] ${t}`);}function R(n){if(!(typeof sessionStorage>"u"))try{let t=JSON.parse(sessionStorage.getItem(I(n))??"null");return t&&A(t.sessionId)&&A(t.bootstrapClientEventId)?{sessionId:t.sessionId,bootstrapClientEventId:t.bootstrapClientEventId}:void 0}catch{return}}function O(n,t){if(!(typeof sessionStorage>"u"))try{sessionStorage.setItem(I(n),JSON.stringify(t));}catch{}}function T(n){if(!(typeof sessionStorage>"u"))try{sessionStorage.removeItem(I(n));}catch{}}function I(n){return `wts-session-${n}`}function A(n){return typeof n=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(n)}var j=1e4,b=class{constructor(t){this.name=t;}async run(t){if(typeof navigator<"u"&&navigator.locks)return navigator.locks.request(this.name,t);this.current&&await this.current;let e=this.acquireLease();if(!e)return;let i=t();this.current=i;try{return await i}finally{this.current===i&&(this.current=void 0),e.release();}}acquireLease(){if(typeof localStorage>"u")return {release(){}};let t=`wts-lock-${this.name}`,e=c(),i=Date.now();try{let r=C(localStorage.getItem(t));return r&&r.expiresAt>i||(localStorage.setItem(t,JSON.stringify({token:e,expiresAt:i+j})),C(localStorage.getItem(t))?.token!==e)?void 0:{release(){C(localStorage.getItem(t))?.token===e&&localStorage.removeItem(t);}}}catch{return {release(){}}}}};function C(n){if(n)try{let t=JSON.parse(n);return typeof t.token=="string"&&typeof t.expiresAt=="number"?{token:t.token,expiresAt:t.expiresAt}:void 0}catch{return}}function q(n){if(typeof window>"u")return ()=>{};let t=window.history,e=t.pushState,i=t.replaceState,r=false,s=()=>{r||(r=true,queueMicrotask(()=>{r=false,n();}));};return t.pushState=function(...o){e.apply(this,o),s();},t.replaceState=function(...o){i.apply(this,o),s();},window.addEventListener("popstate",s),()=>{t.pushState=e,t.replaceState=i,window.removeEventListener("popstate",s);}}var d="meta",u="events";async function _(n){if(typeof indexedDB>"u")throw new Error("IndexedDB is unavailable.");return P.open(n)}async function D(n){if(typeof indexedDB>"u")return;let t=indexedDB.deleteDatabase(N(n));await new Promise((e,i)=>{t.onsuccess=()=>e(),t.onerror=()=>i(t.error??new Error("IndexedDB deletion failed.")),t.onblocked=()=>i(new Error("IndexedDB deletion was blocked by another tab."));});}var w=class{constructor(){this.state={queue:[]};}async load(){return B(this.state)}async saveIdentity(t){this.state.identity={...t};}async saveAttributionContext(t,e){t&&e?(this.state.attributionContextId=t,this.state.attributionContextExpiresAt=e):(delete this.state.attributionContextId,delete this.state.attributionContextExpiresAt);}async enqueue(t){this.state.queue.push(B(t)),W(this.state.queue);}async remove(t){this.state.queue=this.state.queue.filter(e=>!t.has(e.clientEventId));}async clear(){this.state={queue:[]};}close(){}},P=class n{constructor(t){this.database=t;}static async open(t){let e=indexedDB.open(N(t),1);return e.onupgradeneeded=()=>{let i=e.result;i.objectStoreNames.contains(d)||i.createObjectStore(d),i.objectStoreNames.contains(u)||i.createObjectStore(u,{keyPath:"clientEventId"});},new n(await p(e))}async load(){let t=this.database.transaction([d,u],"readonly"),e=t.objectStore(d),i=t.objectStore(u),[r,s,o,a]=await Promise.all([p(e.get("identity")),p(e.get("attributionContextId")),p(e.get("attributionContextExpiresAt")),p(i.getAll())]);return await l(t),a.sort((f,U)=>f.occurredAt.localeCompare(U.occurredAt)),{...r?{identity:r}:{},...s&&o?{attributionContextId:s,attributionContextExpiresAt:o}:{},queue:a}}async saveIdentity(t){await this.writeMeta("identity",t);}async saveAttributionContext(t,e){let i=this.database.transaction(d,"readwrite"),r=i.objectStore(d);t&&e?(r.put(t,"attributionContextId"),r.put(e,"attributionContextExpiresAt")):(r.delete("attributionContextId"),r.delete("attributionContextExpiresAt")),await l(i);}async enqueue(t){let e=await this.load(),i=[...e.queue,t];W(i);let r=new Set(i.map(a=>a.clientEventId)),s=this.database.transaction(u,"readwrite"),o=s.objectStore(u);o.put(t);for(let a of e.queue)r.has(a.clientEventId)||o.delete(a.clientEventId);await l(s);}async remove(t){if(t.size===0)return;let e=this.database.transaction(u,"readwrite"),i=e.objectStore(u);for(let r of t)i.delete(r);await l(e);}async clear(){let t=this.database.transaction([d,u],"readwrite");t.objectStore(d).clear(),t.objectStore(u).clear(),await l(t);}close(){this.database.close();}async writeMeta(t,e){let i=this.database.transaction(d,"readwrite");i.objectStore(d).put(e,t),await l(i);}};function W(n){for(;n.length>100||m(n)>1048576;)n.shift();}function p(n){return new Promise((t,e)=>{n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("IndexedDB request failed."));})}function l(n){return new Promise((t,e)=>{n.oncomplete=()=>t(),n.onerror=()=>e(n.error??new Error("IndexedDB transaction failed.")),n.onabort=()=>e(n.error??new Error("IndexedDB transaction aborted."));})}function B(n){return JSON.parse(JSON.stringify(n))}function N(n){return `wts-web-${n}`}var E=class{constructor(t,e){this.collectorOrigin=t;this.timeoutMs=e;}async bootstrap(t){return await(await this.post("/v2/bootstrap",t.sourceKey,{schemaVersion:2,clientEventId:t.clientEventId,...t.identity,occurredAt:new Date().toISOString(),metadata:{platform:"web",sdkVersion:y,locale:g()},...t.attributionToken?{attributionToken:t.attributionToken}:{}},false)).json()}async send(t,e,i){return await(await this.post("/v2/events/batch",t,{schemaVersion:2,events:e},i)).json()}async post(t,e,i,r){let s=new AbortController,o=setTimeout(()=>s.abort(),this.timeoutMs);try{let a=await fetch(`${this.collectorOrigin}${t}`,{method:"POST",headers:{"Content-Type":"application/json","X-WTS-Source-Key":e},body:JSON.stringify(i),credentials:"omit",mode:"cors",cache:"no-store",keepalive:r,signal:s.signal});if(!a.ok)throw await h.fromResponse(a);return a}finally{clearTimeout(o);}}},h=class n extends Error{constructor(e,i,r,s){super(e);this.status=i;this.retryable=r;this.code=s;this.name="WtsTransportError";}static async fromResponse(e){let i={};try{i=await e.json();}catch{}return new n(i.message??`Collector request failed with status ${e.status}.`,e.status,e.status===429||e.status>=500,i.code)}};var V=/^[a-z][a-z0-9_]{1,63}$/,z=/^[A-Za-z0-9_-]{8,128}$/,H=/^[A-Z]{3}$/,X=/^-?\d{1,12}(?:\.\d{1,6})?$/;function L(n){if(!z.test(n.sourceKey))throw new TypeError("sourceKey must be a valid wts.is Web App source key.");let t=new URL(n.collectorOrigin??"https://collect.wts.is");if(t.protocol!=="https:"&&!F(t.hostname))throw new TypeError("collectorOrigin must use HTTPS outside localhost.");if(t.pathname!=="/"||t.search||t.hash)throw new TypeError("collectorOrigin must not include a path, query, or fragment.");let e=n.requestTimeoutMs??2e3;if(!Number.isInteger(e)||e<250||e>3e4)throw new TypeError("requestTimeoutMs must be an integer between 250 and 30000.");return {sourceKey:n.sourceKey,consent:n.consent??"pending",autoTrackPageViews:n.autoTrackPageViews??false,collectorOrigin:t.origin,requestTimeoutMs:e,debug:n.debug??false}}function M(n,t,e){if(!V.test(n))throw new TypeError("eventKey must match ^[a-z][a-z0-9_]{1,63}$.");let i=Object.entries(t);if(i.length>20)throw new TypeError("Events can contain at most 20 properties.");for(let[r,s]of i){if(!/^[a-z][a-z0-9_]{0,63}$/.test(r))throw new TypeError(`Invalid property key: ${r}`);if(!["string","number","boolean"].includes(typeof s))throw new TypeError(`Property ${r} must be a string, number, or boolean.`);if(typeof s=="string"&&s.length>512)throw new TypeError(`Property ${r} cannot exceed 512 characters.`);if(typeof s=="number"&&!Number.isFinite(s))throw new TypeError(`Property ${r} must be finite.`)}if(e&&(!X.test(e.amount)||!H.test(e.currency)))throw new TypeError("Revenue requires a decimal amount and uppercase ISO-4217 currency.")}function $(n){let t=n.startsWith("/")?n:`/${n}`;if(t.includes("?")||t.includes("#"))throw new TypeError("Page pathname cannot include a query or fragment.");if(t.length>2048)throw new TypeError("Page pathname cannot exceed 2048 characters.");return t}function F(n){return n==="localhost"||n==="127.0.0.1"||n==="[::1]"}var Q=10080*6e4,x=class{constructor(t,e){this.bootstrapClientEventId=c();this.bootstrapped=false;this.destroyed=false;this.retryAttempt=0;this.onPageHide=()=>{this.consent==="granted"&&this.lock.run(()=>this.flushExclusive(true));};this.onVisibilityChange=()=>{document.visibilityState==="hidden"&&this.consent==="granted"&&this.lock.run(()=>this.flushExclusive(true));};this.options=L(t),this.consent=this.options.consent,this.transport=e??new E(this.options.collectorOrigin,this.options.requestTimeoutMs),this.lock=new b(`flush-${this.options.sourceKey}`),this.attributionToken=G(),this.installLifecycleListeners(),this.consent==="granted"&&this.startEnable(),this.consent==="denied"&&(this.attributionToken=void 0);}async setConsent(t){if(this.destroyed)return;if(t==="denied"){this.consent="denied",this.cancelRetry();let i=this.storage;i&&await this.lock.run(async()=>{await i.clear(),i.close();});try{await D(this.options.sourceKey);}catch{v(this.options.debug,"Stored SDK data could not be deleted because it is in use.");}this.storage=void 0,this.identity=void 0,this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.attributionToken=void 0,this.bootstrapped=false,T(this.options.sourceKey),this.removeSpaTracking();return}let e=this.consent==="granted";this.consent="granted",(!e||!this.storage)&&await this.startEnable();}async page(t){let e=this.unavailableResult();if(e||(await this.ensureReady(),e=this.unavailableResult(),e))return e;let i=K(),r=k(),s={...this.eventBase("page_view"),pathname:i,...t?.trim()?{pageName:t.trim().slice(0,120)}:{},...r?{referrerHost:r}:{},properties:{}};return await this.enqueue(s),this.lastPagePath=i,{accepted:true,clientEventId:s.clientEventId}}async track(t,e={},i){let r=this.unavailableResult();if(r||(await this.ensureReady(),r=this.unavailableResult(),r))return r;M(t,e,i);let s={...this.eventBase("custom"),eventKey:t,properties:{...e},...i?{revenue:{...i}}:{}};return await this.enqueue(s),{accepted:true,clientEventId:s.clientEventId}}async flush(){return this.consent!=="granted"||this.destroyed||!this.storage?{sent:0,pending:0}:await this.lock.run(async()=>this.flushExclusive(false))??{sent:0,pending:(await this.storage.load()).queue.length}}async reset(){this.cancelRetry(),await this.storage?.clear(),this.identity=void 0,this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.attributionToken=void 0,T(this.options.sourceKey),this.bootstrapClientEventId=c(),this.bootstrapped=false,this.lastPagePath=void 0,this.consent==="granted"&&!this.destroyed&&await this.initializeIdentity();}destroy(){if(this.destroyed)return;this.destroyed=true,this.cancelRetry(),this.removeSpaTracking(),this.removeLifecycleListeners();let t=this.storage;t&&this.lock.run(async()=>t.close());}async enable(){if(!(this.destroyed||this.consent!=="granted")){if(!this.storage)try{this.storage=await _(this.options.sourceKey),await this.storage.load();}catch{this.storage?.close(),this.storage=new w,v(this.options.debug,"IndexedDB unavailable; using a memory-only event queue.");}await this.initializeIdentity();try{await this.ensureBootstrapped();}catch(t){this.handleRetryableError(t);}this.options.autoTrackPageViews&&!this.removeSpaTracker&&(this.removeSpaTracker=q(()=>{this.trackAutomaticPage();}),await this.trackAutomaticPage()),this.flush();}}startEnable(){if(this.enablePromise)return this.enablePromise;let t=this.enable();return this.enablePromise=t,t.finally(()=>{this.enablePromise===t&&(this.enablePromise=void 0);}),t}async ensureReady(){this.consent==="granted"&&(!this.storage||!this.identity)&&await this.startEnable();}async initializeIdentity(){if(!this.storage)return;let t=await this.storage.load(),e=R(this.options.sourceKey);this.identity={anonymousId:t.identity?.anonymousId??c(),sessionId:e?.sessionId??c()},this.bootstrapClientEventId=e?.bootstrapClientEventId??c(),O(this.options.sourceKey,{sessionId:this.identity.sessionId,bootstrapClientEventId:this.bootstrapClientEventId});let i=t.attributionContextExpiresAt?Date.parse(t.attributionContextExpiresAt):Number.NaN;t.attributionContextId&&Number.isFinite(i)&&i>Date.now()?(this.attributionContextId=t.attributionContextId,this.attributionContextExpiresAt=i):(t.attributionContextId||t.attributionContextExpiresAt)&&await this.storage.saveAttributionContext(),(!t.identity||t.identity.anonymousId!==this.identity.anonymousId||t.identity.sessionId!==this.identity.sessionId)&&await this.storage.saveIdentity(this.identity);}async ensureBootstrapped(){if(this.bootstrapped||!this.identity||!this.storage)return;let t=await this.transport.bootstrap({sourceKey:this.options.sourceKey,identity:this.identity,clientEventId:this.bootstrapClientEventId,...this.attributionToken?{attributionToken:this.attributionToken}:{}});if(this.bootstrapped=true,this.attributionToken=void 0,t.attributionContextId){this.attributionContextId=t.attributionContextId;let e=Date.parse(t.serverTime);this.attributionContextExpiresAt=(Number.isFinite(e)?e:Date.now())+Q,await this.storage.saveAttributionContext(t.attributionContextId,new Date(this.attributionContextExpiresAt).toISOString());}this.retryAttempt=0;}async enqueue(t){this.storage&&(await this.storage.enqueue(t),queueMicrotask(()=>{this.flush();}));}async flushExclusive(t){if(!this.storage)return {sent:0,pending:0};if(this.retryTimer&&!t)return {sent:0,pending:(await this.storage.load()).queue.length};try{await this.ensureBootstrapped();let e=await this.storage.load(),i=Z(e.queue,this.activeAttributionContextId());if(i.length===0)return {sent:0,pending:e.queue.length};let r=await this.transport.send(this.options.sourceKey,i,t),s=new Set([...r.accepted,...r.duplicates]),o=!1;for(let f of r.rejected)f.retryable?o=!0:s.add(f.clientEventId);await this.storage.remove(s);let a=(await this.storage.load()).queue.length;return o?this.scheduleRetry():(this.retryAttempt=0,a>0&&queueMicrotask(()=>{this.flush();})),{sent:s.size,pending:a}}catch(e){return this.handleRetryableError(e),{sent:0,pending:(await this.storage.load()).queue.length}}}handleRetryableError(t){if(t instanceof h&&!t.retryable){v(this.options.debug,`Collector rejected the request (${t.code??t.status}).`);return}this.scheduleRetry();}scheduleRetry(){if(this.consent!=="granted"||this.destroyed||this.retryTimer)return;let t=Math.min(6e4,1e3*2**Math.min(this.retryAttempt,6)),e=Math.floor(Math.random()*Math.max(1,t*.25));this.retryAttempt+=1,this.retryTimer=setTimeout(()=>{this.retryTimer=void 0,this.flush();},t+e);}async trackAutomaticPage(){K()!==this.lastPagePath&&await this.page();}eventBase(t){if(!this.identity)throw new Error("Web SDK identity is unavailable.");let e=this.activeAttributionContextId();return {schemaVersion:2,clientEventId:c(),...this.identity,type:t,occurredAt:new Date().toISOString(),metadata:{platform:"web",sdkVersion:y,locale:g()},...e?{attributionContextId:e}:{}}}unavailableResult(){if(this.destroyed)return {accepted:false,reason:"destroyed"};if(this.consent==="pending")return {accepted:false,reason:"consent_pending"};if(this.consent==="denied")return {accepted:false,reason:"consent_denied"}}activeAttributionContextId(){if(this.attributionContextId&&this.attributionContextExpiresAt&&this.attributionContextExpiresAt>Date.now())return this.attributionContextId;(this.attributionContextId||this.attributionContextExpiresAt)&&(this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.storage?.saveAttributionContext());}installLifecycleListeners(){typeof window>"u"||typeof document>"u"||(window.addEventListener("pagehide",this.onPageHide),document.addEventListener("visibilitychange",this.onVisibilityChange));}removeLifecycleListeners(){typeof window>"u"||typeof document>"u"||(window.removeEventListener("pagehide",this.onPageHide),document.removeEventListener("visibilitychange",this.onVisibilityChange));}removeSpaTracking(){this.removeSpaTracker?.(),this.removeSpaTracker=void 0;}cancelRetry(){this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=void 0;}};function K(){return $(typeof location>"u"?"/":location.pathname)}function G(){if(typeof location>"u"||typeof history>"u")return;let n=new URL(location.href),t=n.searchParams.get(S)??void 0;if(t)return n.searchParams.delete(S),history.replaceState(history.state,"",`${n.pathname}${n.search}${n.hash}`),t}function Z(n,t){let e=[];for(let i of n.slice(0,50)){let r=t?{...i,attributionContextId:t}:i;if(m({schemaVersion:2,events:[...e,r]})>65536)break;e.push(r);}return e}function xt(n){return new x(n)}
2
- exports.createWtsClient=xt;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var S="0.2.0-alpha.1";var q="_wts";function c(){let n=globalThis.crypto;if(!n)throw new Error("A secure random number generator is required.");if(typeof n.randomUUID=="function")return n.randomUUID();let t=n.getRandomValues(new Uint8Array(16));t[6]=t[6]&15|64,t[8]=t[8]&63|128;let e=Array.from(t,i=>i.toString(16).padStart(2,"0"));return `${e.slice(0,4).join("")}-${e.slice(4,6).join("")}-${e.slice(6,8).join("")}-${e.slice(8,10).join("")}-${e.slice(10).join("")}`}function v(n){return new TextEncoder().encode(JSON.stringify(n)).byteLength}function x(){return typeof navigator>"u"?"en":navigator.language||"en"}function $(){if(!(typeof document>"u"||!document.referrer))try{return new URL(document.referrer).hostname.toLowerCase()||void 0}catch{return}}function w(n,t){n&&typeof console<"u"&&console.warn(`[wts.is] ${t}`);}function W(n){if(!(typeof sessionStorage>"u"))try{let t=JSON.parse(sessionStorage.getItem(U(n))??"null");return t&&N(t.sessionId)&&N(t.bootstrapClientEventId)?{sessionId:t.sessionId,bootstrapClientEventId:t.bootstrapClientEventId}:void 0}catch{return}}function M(n,t){if(!(typeof sessionStorage>"u"))try{sessionStorage.setItem(U(n),JSON.stringify(t));}catch{}}function A(n){if(!(typeof sessionStorage>"u"))try{sessionStorage.removeItem(U(n));}catch{}}function U(n){return `wts-session-${n}`}function N(n){return typeof n=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(n)}var it=1e4,C=class{constructor(t){this.name=t;}async run(t){if(typeof navigator<"u"&&navigator.locks)return navigator.locks.request(this.name,t);this.current&&await this.current;let e=this.acquireLease();if(!e)return;let i=t();this.current=i;try{return await i}finally{this.current===i&&(this.current=void 0),e.release();}}acquireLease(){if(typeof localStorage>"u")return {release(){}};let t=`wts-lock-${this.name}`,e=c(),i=Date.now();try{let r=B(localStorage.getItem(t));return r&&r.expiresAt>i||(localStorage.setItem(t,JSON.stringify({token:e,expiresAt:i+it})),B(localStorage.getItem(t))?.token!==e)?void 0:{release(){B(localStorage.getItem(t))?.token===e&&localStorage.removeItem(t);}}}catch{return {release(){}}}}};function B(n){if(n)try{let t=JSON.parse(n);return typeof t.token=="string"&&typeof t.expiresAt=="number"?{token:t.token,expiresAt:t.expiresAt}:void 0}catch{return}}function K(n){if(typeof window>"u")return ()=>{};let t=window.history,e=t.pushState,i=t.replaceState,r=false,s=()=>{r||(r=true,queueMicrotask(()=>{r=false,n();}));};return t.pushState=function(...a){e.apply(this,a),s();},t.replaceState=function(...a){i.apply(this,a),s();},window.addEventListener("popstate",s),()=>{t.pushState=e,t.replaceState=i,window.removeEventListener("popstate",s);}}var y="meta",l="events",p="identity_mutations";async function L(n){if(typeof indexedDB>"u")throw new Error("IndexedDB is unavailable.");return _.open(n)}async function Q(n){if(typeof indexedDB>"u")return;let t=indexedDB.deleteDatabase(V(n));await new Promise((e,i)=>{t.onsuccess=()=>e(),t.onerror=()=>i(t.error??new Error("IndexedDB deletion failed.")),t.onblocked=()=>i(new Error("IndexedDB deletion was blocked by another tab."));});}var P=class{constructor(){this.state={queue:[],identityQueue:[]};}async load(){return T(this.state)}async saveIdentity(t){this.state.identity={...t};}async saveAttributionContext(t,e){t&&e?(this.state.attributionContextId=t,this.state.attributionContextExpiresAt=e):(delete this.state.attributionContextId,delete this.state.attributionContextExpiresAt);}async enqueue(t){this.state.queue.push(T(t)),R(this.state);}async enqueueIdentity(t){this.state.identityQueue.push(T(t)),R(this.state);}async remove(t){this.state.queue=this.state.queue.filter(e=>!t.has(e.clientEventId));}async removeIdentity(t){this.state.identityQueue=this.state.identityQueue.filter(e=>!t.has(e.clientMutationId));}async clear(){this.state={queue:[],identityQueue:[]};}close(){}},_=class n{constructor(t){this.database=t;}static async open(t){let e=indexedDB.open(V(t),2);return e.onupgradeneeded=()=>{let i=e.result;i.objectStoreNames.contains(y)||i.createObjectStore(y),i.objectStoreNames.contains(l)||i.createObjectStore(l,{keyPath:"clientEventId"}),i.objectStoreNames.contains(p)||i.createObjectStore(p,{keyPath:"clientMutationId"});},new n(await I(e))}async load(){let t=this.database.transaction([y,l,p],"readonly"),e=t.objectStore(y),i=t.objectStore(l),r=t.objectStore(p),[s,a,d,h,o]=await Promise.all([I(e.get("identity")),I(e.get("attributionContextId")),I(e.get("attributionContextExpiresAt")),I(i.getAll()),I(r.getAll())]);return await m(t),h.sort((b,u)=>b.occurredAt.localeCompare(u.occurredAt)),o.sort((b,u)=>b.occurredAt.localeCompare(u.occurredAt)),{...s?{identity:s}:{},...a&&d?{attributionContextId:a,attributionContextExpiresAt:d}:{},queue:h,identityQueue:o}}async saveIdentity(t){await this.writeMeta("identity",t);}async saveAttributionContext(t,e){let i=this.database.transaction(y,"readwrite"),r=i.objectStore(y);t&&e?(r.put(t,"attributionContextId"),r.put(e,"attributionContextExpiresAt")):(r.delete("attributionContextId"),r.delete("attributionContextExpiresAt")),await m(i);}async enqueue(t){let e=await this.load(),i=T(e);i.queue.push(t),R(i);let r=new Set(i.queue.map(o=>o.clientEventId)),s=new Set(i.identityQueue.map(o=>o.clientMutationId)),a=this.database.transaction([l,p],"readwrite"),d=a.objectStore(l),h=a.objectStore(p);d.put(t);for(let o of e.queue)r.has(o.clientEventId)||d.delete(o.clientEventId);for(let o of i.identityQueue)h.put(o);for(let o of e.identityQueue)s.has(o.clientMutationId)||h.delete(o.clientMutationId);await m(a);}async enqueueIdentity(t){let e=await this.load(),i=T(e);i.identityQueue.push(t),R(i);let r=new Set(i.queue.map(o=>o.clientEventId)),s=new Set(i.identityQueue.map(o=>o.clientMutationId)),a=this.database.transaction([l,p],"readwrite"),d=a.objectStore(l),h=a.objectStore(p);h.put(t);for(let o of e.queue)r.has(o.clientEventId)||d.delete(o.clientEventId);for(let o of e.identityQueue)s.has(o.clientMutationId)||h.delete(o.clientMutationId);await m(a);}async remove(t){if(t.size===0)return;let e=this.database.transaction(l,"readwrite"),i=e.objectStore(l);for(let r of t)i.delete(r);await m(e);}async removeIdentity(t){if(t.size===0)return;let e=this.database.transaction(p,"readwrite"),i=e.objectStore(p);for(let r of t)i.delete(r);await m(e);}async clear(){let t=this.database.transaction([y,l,p],"readwrite");t.objectStore(y).clear(),t.objectStore(l).clear(),t.objectStore(p).clear(),await m(t);}close(){this.database.close();}async writeMeta(t,e){let i=this.database.transaction(y,"readwrite");i.objectStore(y).put(e,t),await m(i);}};function R(n){for(;n.queue.length+n.identityQueue.length>100||v({events:n.queue,mutations:n.identityQueue})>1048576;)n.queue.length>0?n.queue.shift():n.identityQueue.shift();}function I(n){return new Promise((t,e)=>{n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("IndexedDB request failed."));})}function m(n){return new Promise((t,e)=>{n.oncomplete=()=>t(),n.onerror=()=>e(n.error??new Error("IndexedDB transaction failed.")),n.onabort=()=>e(n.error??new Error("IndexedDB transaction aborted."));})}function T(n){return JSON.parse(JSON.stringify(n))}function V(n){return `wts-web-${n}`}var k=class{constructor(t,e){this.collectorOrigin=t;this.timeoutMs=e;}async bootstrap(t){return await(await this.post("/v3/bootstrap",t.sourceKey,{schemaVersion:3,clientEventId:t.clientEventId,...t.identity,occurredAt:new Date().toISOString(),metadata:{platform:"web",sdkVersion:S,locale:x()},...t.attributionToken?{attributionToken:t.attributionToken}:{}},false)).json()}async send(t,e,i){return await(await this.post("/v3/events/batch",t,{schemaVersion:3,events:e},i)).json()}async sendIdentity(t,e){return await(await this.post("/v3/identity/mutations",t,{schemaVersion:1,mutations:e},false)).json()}async post(t,e,i,r){let s=new AbortController,a=setTimeout(()=>s.abort(),this.timeoutMs);try{let d=await fetch(`${this.collectorOrigin}${t}`,{method:"POST",headers:{"Content-Type":"application/json","X-WTS-Source-Key":e},body:JSON.stringify(i),credentials:"omit",mode:"cors",cache:"no-store",keepalive:r,signal:s.signal});if(!d.ok)throw await E.fromResponse(d);return d}finally{clearTimeout(a);}}},E=class n extends Error{constructor(e,i,r,s){super(e);this.status=i;this.retryable=r;this.code=s;this.name="WtsTransportError";}static async fromResponse(e){let i={};try{i=await e.json();}catch{}return new n(i.message??`Collector request failed with status ${e.status}.`,e.status,e.status===429||e.status>=500,i.code)}};var rt=/^[a-z][a-z0-9_]{1,63}$/,st=/^[A-Za-z0-9_-]{8,128}$/,ot=/^[A-Z]{3}$/,at=/^-?\d{1,12}(?:\.\d{1,6})?$/,ut=/^[a-z][a-z0-9_]{0,63}$/;function z(n){if(!st.test(n.sourceKey))throw new TypeError("sourceKey must be a valid wts.is Web App source key.");let t=new URL(n.collectorOrigin??"https://collect.wts.is");if(t.protocol!=="https:"&&!dt(t.hostname))throw new TypeError("collectorOrigin must use HTTPS outside localhost.");if(t.pathname!=="/"||t.search||t.hash)throw new TypeError("collectorOrigin must not include a path, query, or fragment.");let e=n.requestTimeoutMs??2e3;if(!Number.isInteger(e)||e<250||e>3e4)throw new TypeError("requestTimeoutMs must be an integer between 250 and 30000.");return {sourceKey:n.sourceKey,consent:n.consent??"pending",autoTrackPageViews:n.autoTrackPageViews??false,collectorOrigin:t.origin,requestTimeoutMs:e,debug:n.debug??false}}function F(n,t,e){if(!rt.test(n))throw new TypeError("eventKey must match ^[a-z][a-z0-9_]{1,63}$.");let i=Object.entries(t);if(i.length>20)throw new TypeError("Events can contain at most 20 properties.");for(let[r,s]of i){if(!/^[a-z][a-z0-9_]{0,63}$/.test(r))throw new TypeError(`Invalid property key: ${r}`);if(!["string","number","boolean"].includes(typeof s))throw new TypeError(`Property ${r} must be a string, number, or boolean.`);if(typeof s=="string"&&s.length>512)throw new TypeError(`Property ${r} cannot exceed 512 characters.`);if(typeof s=="number"&&!Number.isFinite(s))throw new TypeError(`Property ${r} must be finite.`)}if(e&&(!at.test(e.amount)||!ot.test(e.currency)))throw new TypeError("Revenue requires a decimal amount and uppercase ISO-4217 currency.")}function H(n){if(typeof n!="string"||n.length<1||n.length>128)throw new TypeError("externalUserId must contain 1\u2013128 characters.")}function J(n){Z(Object.entries(n));}function X(n){let t=[...Object.keys(n.set??{}),...Object.keys(n.setOnce??{}),...n.unset??[],...Object.keys(n.increment??{})];if(t.length===0)throw new TypeError("At least one user update operation is required.");if(t.length>50)throw new TypeError("A user update can contain at most 50 operations.");if(new Set(t).size!==t.length)throw new TypeError("An attribute can be changed only once within a user update.");Z([...Object.entries(n.set??{}),...Object.entries(n.setOnce??{})]);for(let e of n.unset??[])j(e);for(let[e,i]of Object.entries(n.increment??{}))if(j(e),!Number.isFinite(i))throw new TypeError(`Increment ${e} must be finite.`)}function Y(n){for(let[t,e,i]of [["source",n.source,120],["medium",n.medium,120],["campaign",n.campaign,160],["externalRef",n.externalRef,256]])if(e!==void 0&&(!e.trim()||e.length>i))throw new TypeError(`${t} must contain 1\u2013${i} characters.`)}function G(n){let t=n.startsWith("/")?n:`/${n}`;if(t.includes("?")||t.includes("#"))throw new TypeError("Page pathname cannot include a query or fragment.");if(t.length>2048)throw new TypeError("Page pathname cannot exceed 2048 characters.");return t}function dt(n){return n==="localhost"||n==="127.0.0.1"||n==="[::1]"}function Z(n){if(n.length>50)throw new TypeError("A mutation can contain at most 50 attributes.");for(let[t,e]of n){if(j(t),e instanceof Date){if(Number.isNaN(e.getTime()))throw new TypeError(`Attribute ${t} must contain a valid Date.`);continue}if(Array.isArray(e)){if(e.length>50||e.some(i=>typeof i!="string"||i.length>512))throw new TypeError(`Attribute ${t} must be an array of at most 50 short strings.`);continue}if(!["string","number","boolean"].includes(typeof e))throw new TypeError(`Attribute ${t} has an unsupported value type.`);if(typeof e=="string"&&e.length>2048)throw new TypeError(`Attribute ${t} cannot exceed 2048 characters.`);if(typeof e=="number"&&!Number.isFinite(e))throw new TypeError(`Attribute ${t} must be finite.`)}}function j(n){if(!ut.test(n))throw new TypeError(`Invalid attribute key: ${n}`)}var ct=10080*6e4,O=class{constructor(t,e){this.bootstrapClientEventId=c();this.bootstrapped=false;this.destroyed=false;this.retryAttempt=0;this.onPageHide=()=>{this.consent==="granted"&&this.lock.run(()=>this.flushExclusive(true));};this.onVisibilityChange=()=>{document.visibilityState==="hidden"&&this.consent==="granted"&&this.lock.run(()=>this.flushExclusive(true));};this.options=z(t),this.consent=this.options.consent,this.transport=e??new k(this.options.collectorOrigin,this.options.requestTimeoutMs),this.lock=new C(`flush-${this.options.sourceKey}`),this.attributionToken=lt(),this.installLifecycleListeners(),this.consent==="granted"&&this.startEnable(),this.consent==="denied"&&(this.attributionToken=void 0);}async setConsent(t){if(this.destroyed)return;if(t==="denied"){this.consent="denied",this.cancelRetry();let i=this.storage;i&&await this.lock.run(async()=>{await i.clear(),i.close();});try{await Q(this.options.sourceKey);}catch{w(this.options.debug,"Stored SDK data could not be deleted because it is in use.");}this.storage=void 0,this.identity=void 0,this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.attributionToken=void 0,this.bootstrapped=false,A(this.options.sourceKey),this.removeSpaTracking();return}let e=this.consent==="granted";this.consent="granted",(!e||!this.storage)&&await this.startEnable();}async page(t){let e=this.unavailableResult();if(e||(await this.ensureReady(),e=this.unavailableResult(),e))return e;let i=tt(),r=$(),s={...this.eventBase("page_view"),pathname:i,...t?.trim()?{pageName:t.trim().slice(0,120)}:{},...r?{referrerHost:r}:{},properties:{}};return await this.enqueue(s),this.lastPagePath=i,{accepted:true,clientEventId:s.clientEventId}}async track(t,e={},i){let r=this.unavailableResult();if(r||(await this.ensureReady(),r=this.unavailableResult(),r))return r;F(t,e,i);let s={...this.eventBase("custom"),eventKey:t,properties:{...e},...i?{revenue:{...i}}:{}};return await this.enqueue(s),{accepted:true,clientEventId:s.clientEventId}}async identify(t,e={}){let i=await this.prepareIdentityOperation();return i||(H(t),J(e),this.enqueueIdentityMutation({type:"identify",externalUserId:t,...Object.keys(e).length?{attributes:ft(e)}:{}}))}async updateUser(t){let e=await this.prepareIdentityOperation();return e||(X(t),this.enqueueIdentityMutation({type:"update_user",operations:yt(t)}))}async setReportedAttribution(t){let e=await this.prepareIdentityOperation();return e||(Y(t),this.enqueueIdentityMutation({type:"reported_attribution",attribution:{...t}}))}async resetIdentity(){let t=await this.prepareIdentityOperation();if(t)return t;let e=await this.enqueueIdentityMutation({type:"reset_identity"});return this.storage&&(this.identity={anonymousId:c(),sessionId:c()},this.bootstrapClientEventId=c(),this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.attributionToken=void 0,this.bootstrapped=false,this.lastPagePath=void 0,A(this.options.sourceKey),M(this.options.sourceKey,{sessionId:this.identity.sessionId,bootstrapClientEventId:this.bootstrapClientEventId}),await this.storage.saveIdentity(this.identity),await this.storage.saveAttributionContext()),e}async flush(){if(this.consent!=="granted"||this.destroyed||!this.storage)return {sent:0,pending:0};let t=await this.lock.run(async()=>this.flushExclusive(false));if(t)return t;let e=await this.storage.load();return {sent:0,pending:e.queue.length+e.identityQueue.length}}async reset(){this.cancelRetry(),await this.storage?.clear(),this.identity=void 0,this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.attributionToken=void 0,A(this.options.sourceKey),this.bootstrapClientEventId=c(),this.bootstrapped=false,this.lastPagePath=void 0,this.consent==="granted"&&!this.destroyed&&await this.initializeIdentity();}destroy(){if(this.destroyed)return;this.destroyed=true,this.cancelRetry(),this.removeSpaTracking(),this.removeLifecycleListeners();let t=this.storage;t&&this.lock.run(async()=>t.close());}async enable(){if(!(this.destroyed||this.consent!=="granted")){if(!this.storage)try{this.storage=await L(this.options.sourceKey),await this.storage.load();}catch{this.storage?.close(),this.storage=new P,w(this.options.debug,"IndexedDB unavailable; using a memory-only event queue.");}await this.initializeIdentity();try{await this.ensureBootstrapped();}catch(t){this.handleRetryableError(t);}this.options.autoTrackPageViews&&!this.removeSpaTracker&&(this.removeSpaTracker=K(()=>{this.trackAutomaticPage();}),await this.trackAutomaticPage()),this.flush();}}startEnable(){if(this.enablePromise)return this.enablePromise;let t=this.enable();return this.enablePromise=t,t.finally(()=>{this.enablePromise===t&&(this.enablePromise=void 0);}),t}async ensureReady(){this.consent==="granted"&&(!this.storage||!this.identity)&&await this.startEnable();}async initializeIdentity(){if(!this.storage)return;let t=await this.storage.load(),e=W(this.options.sourceKey);this.identity={anonymousId:t.identity?.anonymousId??c(),sessionId:e?.sessionId??c()},this.bootstrapClientEventId=e?.bootstrapClientEventId??c(),M(this.options.sourceKey,{sessionId:this.identity.sessionId,bootstrapClientEventId:this.bootstrapClientEventId});let i=t.attributionContextExpiresAt?Date.parse(t.attributionContextExpiresAt):Number.NaN;t.attributionContextId&&Number.isFinite(i)&&i>Date.now()?(this.attributionContextId=t.attributionContextId,this.attributionContextExpiresAt=i):(t.attributionContextId||t.attributionContextExpiresAt)&&await this.storage.saveAttributionContext(),(!t.identity||t.identity.anonymousId!==this.identity.anonymousId||t.identity.sessionId!==this.identity.sessionId)&&await this.storage.saveIdentity(this.identity);}async ensureBootstrapped(){if(this.bootstrapped||!this.identity||!this.storage)return;let t=await this.transport.bootstrap({sourceKey:this.options.sourceKey,identity:this.identity,clientEventId:this.bootstrapClientEventId,...this.attributionToken?{attributionToken:this.attributionToken}:{}});if(this.bootstrapped=true,this.attributionToken=void 0,t.attributionContextId){this.attributionContextId=t.attributionContextId;let e=Date.parse(t.serverTime);this.attributionContextExpiresAt=(Number.isFinite(e)?e:Date.now())+ct,await this.storage.saveAttributionContext(t.attributionContextId,new Date(this.attributionContextExpiresAt).toISOString());}this.retryAttempt=0;}async enqueue(t){this.storage&&(await this.storage.enqueue(t),queueMicrotask(()=>{this.flush();}));}async flushExclusive(t){if(!this.storage)return {sent:0,pending:0};if(this.retryTimer&&!t){let e=await this.storage.load();return {sent:0,pending:e.queue.length+e.identityQueue.length}}try{await this.ensureBootstrapped();let e=await this.storage.load(),i=ht(e.identityQueue);if(i.length>0)try{let u=await this.transport.sendIdentity(this.options.sourceKey,i),g=(u.rejected??[]).filter(f=>!f.retryable).map(f=>f.clientMutationId),nt=(u.rejected??[]).some(f=>f.retryable);if(await this.storage.removeIdentity(new Set([...u.accepted,...u.duplicates,...g])),g.length>0&&w(this.options.debug,`Collector permanently rejected ${g.length} identity mutation(s).`),nt){this.scheduleRetry();let f=await this.storage.load();return {sent:u.accepted.length+u.duplicates.length+g.length,pending:f.queue.length+f.identityQueue.length}}}catch(u){if(u instanceof E&&!u.retryable)await this.storage.removeIdentity(new Set(i.map(g=>g.clientMutationId))),w(this.options.debug,`Collector rejected an identity mutation (${u.code??u.status}).`);else return this.handleRetryableError(u),{sent:0,pending:e.queue.length+e.identityQueue.length}}let r=await this.storage.load(),s=pt(r.queue,this.activeAttributionContextId());if(s.length===0)return {sent:i.length,pending:r.queue.length+r.identityQueue.length};let a=await this.transport.send(this.options.sourceKey,s,t),d=new Set([...a.accepted,...a.duplicates]),h=!1;for(let u of a.rejected)u.retryable?h=!0:d.add(u.clientEventId);await this.storage.remove(d);let o=await this.storage.load(),b=o.queue.length+o.identityQueue.length;return h?this.scheduleRetry():(this.retryAttempt=0,b>0&&queueMicrotask(()=>{this.flush();})),{sent:d.size+i.length,pending:b}}catch(e){this.handleRetryableError(e);let i=await this.storage.load();return {sent:0,pending:i.queue.length+i.identityQueue.length}}}handleRetryableError(t){if(t instanceof E&&!t.retryable){w(this.options.debug,`Collector rejected the request (${t.code??t.status}).`);return}this.scheduleRetry();}scheduleRetry(){if(this.consent!=="granted"||this.destroyed||this.retryTimer)return;let t=Math.min(6e4,1e3*2**Math.min(this.retryAttempt,6)),e=Math.floor(Math.random()*Math.max(1,t*.25));this.retryAttempt+=1,this.retryTimer=setTimeout(()=>{this.retryTimer=void 0,this.flush();},t+e);}async trackAutomaticPage(){tt()!==this.lastPagePath&&await this.page();}eventBase(t){if(!this.identity)throw new Error("Web SDK identity is unavailable.");let e=this.activeAttributionContextId();return {schemaVersion:3,clientEventId:c(),...this.identity,type:t,occurredAt:new Date().toISOString(),metadata:{platform:"web",sdkVersion:S,locale:x()},...e?{attributionContextId:e}:{}}}async prepareIdentityOperation(){let t=this.unavailableResult();return t||(await this.ensureReady(),t=this.unavailableResult(),t)}async enqueueIdentityMutation(t){if(!this.storage||!this.identity)throw new Error("Web SDK identity is unavailable.");let e={schemaVersion:1,clientMutationId:c(),occurredAt:new Date().toISOString(),identity:{...this.identity},metadata:{platform:"web",sdkVersion:S,locale:x()},...t};if(v({schemaVersion:1,mutations:[e]})>65536)throw new TypeError("Identity mutation cannot exceed 64 KiB.");return await this.storage.enqueueIdentity(e),queueMicrotask(()=>{this.flush();}),{accepted:true,clientEventId:e.clientMutationId}}unavailableResult(){if(this.destroyed)return {accepted:false,reason:"destroyed"};if(this.consent==="pending")return {accepted:false,reason:"consent_pending"};if(this.consent==="denied")return {accepted:false,reason:"consent_denied"}}activeAttributionContextId(){if(this.attributionContextId&&this.attributionContextExpiresAt&&this.attributionContextExpiresAt>Date.now())return this.attributionContextId;(this.attributionContextId||this.attributionContextExpiresAt)&&(this.attributionContextId=void 0,this.attributionContextExpiresAt=void 0,this.storage?.saveAttributionContext());}installLifecycleListeners(){typeof window>"u"||typeof document>"u"||(window.addEventListener("pagehide",this.onPageHide),document.addEventListener("visibilitychange",this.onVisibilityChange));}removeLifecycleListeners(){typeof window>"u"||typeof document>"u"||(window.removeEventListener("pagehide",this.onPageHide),document.removeEventListener("visibilitychange",this.onVisibilityChange));}removeSpaTracking(){this.removeSpaTracker?.(),this.removeSpaTracker=void 0;}cancelRetry(){this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=void 0;}};function tt(){return G(typeof location>"u"?"/":location.pathname)}function lt(){if(typeof location>"u"||typeof history>"u")return;let n=new URL(location.href),t=n.searchParams.get(q)??void 0;if(t)return n.searchParams.delete(q),history.replaceState(history.state,"",`${n.pathname}${n.search}${n.hash}`),t}function pt(n,t){let e=[];for(let i of n.slice(0,50)){let r=t?{...i,attributionContextId:t}:i;if(v({schemaVersion:3,events:[...e,r]})>65536)break;e.push(r);}return e}function ht(n){let t=[];for(let e of n.slice(0,50)){if(v({schemaVersion:1,mutations:[...t,e]})>65536){t.length===0&&t.push(e);break}t.push(e);}return t}function yt(n){return JSON.parse(JSON.stringify(n))}function ft(n){return Object.fromEntries(Object.entries(n).map(([t,e])=>[t,e instanceof Date?e.toISOString():e]))}function Dt(n){return new O(n)}
2
+ exports.createWtsClient=Dt;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/runtime.ts","../src/multitab-lock.ts","../src/spa-tracker.ts","../src/storage.ts","../src/transport.ts","../src/validation.ts","../src/client.ts","../src/index.ts"],"names":["SDK_VERSION","ATTRIBUTION_QUERY_KEY","createUuid","cryptoApi","bytes","hex","value","byteLength","locale","referrerHost","safeWarn","enabled","message","loadBrowserSession","sourceKey","parsed","sessionKey","isUuid","saveBrowserSession","state","clearBrowserSession","LEASE_MS","MultiTabLock","name","operation","lease","current","key","token","now","parseLease","installSpaTracker","onNavigate","historyApi","originalPush","originalReplace","scheduled","notify","args","META_STORE","EVENT_STORE","createStorage","IndexedDbStorage","deleteStorage","request","databaseName","resolve","reject","MemoryStorage","clone","identity","expiresAt","event","trimQueue","clientEventIds","_IndexedDbStorage","database","requestResult","transaction","meta","events","attributionContextId","attributionContextExpiresAt","queue","transactionDone","left","right","store","retainedIds","item","queued","id","HttpTransport","collectorOrigin","timeoutMs","input","keepalive","path","body","controller","timeout","response","TransportError","_TransportError","status","retryable","code","payload","eventKeyPattern","sourceKeyPattern","currencyPattern","amountPattern","validateOptions","options","collector","isLocalhost","validateEvent","eventKey","properties","revenue","entries","normalizePathname","pathname","normalized","hostname","ATTRIBUTION_CONTEXT_TTL_MS","WtsClientImpl","transport","captureAttributionToken","consent","storage","wasGranted","unavailable","currentPathname","referrer","error","pending","browserSession","contextExpiry","result","serverTime","batch","takeBatch","remove","hasRetryableRejection","rejection","base","jitter","type","url","createWtsClient"],"mappings":"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","file":"index.cjs","sourcesContent":["export const SDK_VERSION = \"0.1.0-alpha.2\";\nexport const DEFAULT_COLLECTOR_ORIGIN = \"https://collect.wts.is\";\nexport const MAX_QUEUE_EVENTS = 100;\nexport const MAX_QUEUE_BYTES = 1024 * 1024;\nexport const MAX_BATCH_EVENTS = 50;\nexport const MAX_BATCH_BYTES = 64 * 1024;\nexport const DEFAULT_TIMEOUT_MS = 2_000;\nexport const ATTRIBUTION_QUERY_KEY = \"_wts\";\n","export function createUuid(): string {\n const cryptoApi = globalThis.crypto;\n if (!cryptoApi) throw new Error(\"A secure random number generator is required.\");\n if (typeof cryptoApi.randomUUID === \"function\") return cryptoApi.randomUUID();\n const bytes = cryptoApi.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\"));\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10).join(\"\")}`;\n}\n\nexport function byteLength(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nexport function locale(): string {\n return typeof navigator === \"undefined\" ? \"en\" : navigator.language || \"en\";\n}\n\nexport function referrerHost(): string | undefined {\n if (typeof document === \"undefined\" || !document.referrer) return undefined;\n try {\n return new URL(document.referrer).hostname.toLowerCase() || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function safeWarn(enabled: boolean, message: string): void {\n if (enabled && typeof console !== \"undefined\") console.warn(`[wts.is] ${message}`);\n}\n\nexport type BrowserSessionState = {\n sessionId: string;\n bootstrapClientEventId: string;\n};\n\nexport function loadBrowserSession(sourceKey: string): BrowserSessionState | undefined {\n if (typeof sessionStorage === \"undefined\") return undefined;\n try {\n const parsed = JSON.parse(sessionStorage.getItem(sessionKey(sourceKey)) ?? \"null\") as {\n sessionId?: unknown;\n bootstrapClientEventId?: unknown;\n } | null;\n return parsed && isUuid(parsed.sessionId) && isUuid(parsed.bootstrapClientEventId)\n ? {\n sessionId: parsed.sessionId,\n bootstrapClientEventId: parsed.bootstrapClientEventId,\n }\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function saveBrowserSession(sourceKey: string, state: BrowserSessionState): void {\n if (typeof sessionStorage === \"undefined\") return;\n try {\n sessionStorage.setItem(sessionKey(sourceKey), JSON.stringify(state));\n } catch {\n // Storage restrictions are handled by the SDK's memory-only fallback.\n }\n}\n\nexport function clearBrowserSession(sourceKey: string): void {\n if (typeof sessionStorage === \"undefined\") return;\n try {\n sessionStorage.removeItem(sessionKey(sourceKey));\n } catch {\n // A blocked browser storage API is equivalent to an already cleared session.\n }\n}\n\nfunction sessionKey(sourceKey: string): string {\n return `wts-session-${sourceKey}`;\n}\n\nfunction isUuid(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)\n );\n}\n","import { createUuid } from \"./runtime\";\n\nconst LEASE_MS = 10_000;\n\nexport class MultiTabLock {\n private current: Promise<unknown> | undefined;\n\n constructor(private readonly name: string) {}\n\n async run<T>(operation: () => Promise<T>): Promise<T | undefined> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(this.name, operation);\n }\n if (this.current) await this.current;\n const lease = this.acquireLease();\n if (!lease) return undefined;\n const current = operation();\n this.current = current;\n try {\n return await current;\n } finally {\n if (this.current === current) this.current = undefined;\n lease.release();\n }\n }\n\n private acquireLease(): { release(): void } | undefined {\n if (typeof localStorage === \"undefined\") return { release() {} };\n const key = `wts-lock-${this.name}`;\n const token = createUuid();\n const now = Date.now();\n try {\n const current = parseLease(localStorage.getItem(key));\n if (current && current.expiresAt > now) return undefined;\n localStorage.setItem(key, JSON.stringify({ token, expiresAt: now + LEASE_MS }));\n const acquired = parseLease(localStorage.getItem(key));\n if (acquired?.token !== token) return undefined;\n return {\n release() {\n const latest = parseLease(localStorage.getItem(key));\n if (latest?.token === token) localStorage.removeItem(key);\n },\n };\n } catch {\n return { release() {} };\n }\n }\n}\n\nfunction parseLease(value: string | null): { token: string; expiresAt: number } | undefined {\n if (!value) return undefined;\n try {\n const parsed = JSON.parse(value) as { token?: unknown; expiresAt?: unknown };\n return typeof parsed.token === \"string\" && typeof parsed.expiresAt === \"number\"\n ? { token: parsed.token, expiresAt: parsed.expiresAt }\n : undefined;\n } catch {\n return undefined;\n }\n}\n","export function installSpaTracker(onNavigate: () => void): () => void {\n if (typeof window === \"undefined\") return () => undefined;\n const historyApi = window.history;\n const originalPush = historyApi.pushState;\n const originalReplace = historyApi.replaceState;\n let scheduled = false;\n const notify = () => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n onNavigate();\n });\n };\n historyApi.pushState = function (...args) {\n originalPush.apply(this, args);\n notify();\n };\n historyApi.replaceState = function (...args) {\n originalReplace.apply(this, args);\n notify();\n };\n window.addEventListener(\"popstate\", notify);\n return () => {\n historyApi.pushState = originalPush;\n historyApi.replaceState = originalReplace;\n window.removeEventListener(\"popstate\", notify);\n };\n}\n","import { MAX_QUEUE_BYTES, MAX_QUEUE_EVENTS } from \"./constants\";\nimport { byteLength } from \"./runtime\";\nimport type { Identity, StorageAdapter, StoredState, WebEvent } from \"./types\";\n\nconst META_STORE = \"meta\";\nconst EVENT_STORE = \"events\";\n\nexport async function createStorage(sourceKey: string): Promise<StorageAdapter> {\n if (typeof indexedDB === \"undefined\") throw new Error(\"IndexedDB is unavailable.\");\n return IndexedDbStorage.open(sourceKey);\n}\n\nexport async function deleteStorage(sourceKey: string): Promise<void> {\n if (typeof indexedDB === \"undefined\") return;\n const request = indexedDB.deleteDatabase(databaseName(sourceKey));\n await new Promise<void>((resolve, reject) => {\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error ?? new Error(\"IndexedDB deletion failed.\"));\n request.onblocked = () => reject(new Error(\"IndexedDB deletion was blocked by another tab.\"));\n });\n}\n\nexport class MemoryStorage implements StorageAdapter {\n private state: StoredState = { queue: [] };\n\n async load(): Promise<StoredState> {\n return clone(this.state);\n }\n\n async saveIdentity(identity: Identity): Promise<void> {\n this.state.identity = { ...identity };\n }\n\n async saveAttributionContext(value?: string, expiresAt?: string): Promise<void> {\n if (value && expiresAt) {\n this.state.attributionContextId = value;\n this.state.attributionContextExpiresAt = expiresAt;\n } else {\n delete this.state.attributionContextId;\n delete this.state.attributionContextExpiresAt;\n }\n }\n\n async enqueue(event: WebEvent): Promise<void> {\n this.state.queue.push(clone(event));\n trimQueue(this.state.queue);\n }\n\n async remove(clientEventIds: ReadonlySet<string>): Promise<void> {\n this.state.queue = this.state.queue.filter((event) => !clientEventIds.has(event.clientEventId));\n }\n\n async clear(): Promise<void> {\n this.state = { queue: [] };\n }\n\n close(): void {}\n}\n\nclass IndexedDbStorage implements StorageAdapter {\n private constructor(private readonly database: IDBDatabase) {}\n\n static async open(sourceKey: string): Promise<IndexedDbStorage> {\n const request = indexedDB.open(databaseName(sourceKey), 1);\n request.onupgradeneeded = () => {\n const database = request.result;\n if (!database.objectStoreNames.contains(META_STORE)) database.createObjectStore(META_STORE);\n if (!database.objectStoreNames.contains(EVENT_STORE)) {\n database.createObjectStore(EVENT_STORE, { keyPath: \"clientEventId\" });\n }\n };\n return new IndexedDbStorage(await requestResult(request));\n }\n\n async load(): Promise<StoredState> {\n const transaction = this.database.transaction([META_STORE, EVENT_STORE], \"readonly\");\n const meta = transaction.objectStore(META_STORE);\n const events = transaction.objectStore(EVENT_STORE);\n const [identity, attributionContextId, attributionContextExpiresAt, queue] = await Promise.all([\n requestResult(meta.get(\"identity\") as IDBRequest<Identity | undefined>),\n requestResult(meta.get(\"attributionContextId\") as IDBRequest<string | undefined>),\n requestResult(meta.get(\"attributionContextExpiresAt\") as IDBRequest<string | undefined>),\n requestResult(events.getAll() as IDBRequest<WebEvent[]>),\n ]);\n await transactionDone(transaction);\n queue.sort((left, right) => left.occurredAt.localeCompare(right.occurredAt));\n return {\n ...(identity ? { identity } : {}),\n ...(attributionContextId && attributionContextExpiresAt\n ? { attributionContextId, attributionContextExpiresAt }\n : {}),\n queue,\n };\n }\n\n async saveIdentity(identity: Identity): Promise<void> {\n await this.writeMeta(\"identity\", identity);\n }\n\n async saveAttributionContext(value?: string, expiresAt?: string): Promise<void> {\n const transaction = this.database.transaction(META_STORE, \"readwrite\");\n const store = transaction.objectStore(META_STORE);\n if (value && expiresAt) {\n store.put(value, \"attributionContextId\");\n store.put(expiresAt, \"attributionContextExpiresAt\");\n } else {\n store.delete(\"attributionContextId\");\n store.delete(\"attributionContextExpiresAt\");\n }\n await transactionDone(transaction);\n }\n\n async enqueue(event: WebEvent): Promise<void> {\n const state = await this.load();\n const queue = [...state.queue, event];\n trimQueue(queue);\n const retainedIds = new Set(queue.map((item) => item.clientEventId));\n const transaction = this.database.transaction(EVENT_STORE, \"readwrite\");\n const store = transaction.objectStore(EVENT_STORE);\n store.put(event);\n for (const queued of state.queue) {\n if (!retainedIds.has(queued.clientEventId)) store.delete(queued.clientEventId);\n }\n await transactionDone(transaction);\n }\n\n async remove(clientEventIds: ReadonlySet<string>): Promise<void> {\n if (clientEventIds.size === 0) return;\n const transaction = this.database.transaction(EVENT_STORE, \"readwrite\");\n const store = transaction.objectStore(EVENT_STORE);\n for (const id of clientEventIds) store.delete(id);\n await transactionDone(transaction);\n }\n\n async clear(): Promise<void> {\n const transaction = this.database.transaction([META_STORE, EVENT_STORE], \"readwrite\");\n transaction.objectStore(META_STORE).clear();\n transaction.objectStore(EVENT_STORE).clear();\n await transactionDone(transaction);\n }\n\n close(): void {\n this.database.close();\n }\n\n private async writeMeta(key: string, value: unknown): Promise<void> {\n const transaction = this.database.transaction(META_STORE, \"readwrite\");\n transaction.objectStore(META_STORE).put(value, key);\n await transactionDone(transaction);\n }\n}\n\nfunction trimQueue(queue: WebEvent[]): void {\n while (queue.length > MAX_QUEUE_EVENTS || byteLength(queue) > MAX_QUEUE_BYTES) queue.shift();\n}\n\nfunction requestResult<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error(\"IndexedDB request failed.\"));\n });\n}\n\nfunction transactionDone(transaction: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () =>\n reject(transaction.error ?? new Error(\"IndexedDB transaction failed.\"));\n transaction.onabort = () =>\n reject(transaction.error ?? new Error(\"IndexedDB transaction aborted.\"));\n });\n}\n\nfunction clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction databaseName(sourceKey: string): string {\n return `wts-web-${sourceKey}`;\n}\n","import { SDK_VERSION } from \"./constants\";\nimport { locale } from \"./runtime\";\nimport type { BatchResponse, Identity, Transport, WebEvent } from \"./types\";\n\nexport class HttpTransport implements Transport {\n constructor(\n private readonly collectorOrigin: string,\n private readonly timeoutMs: number,\n ) {}\n\n async bootstrap(input: {\n sourceKey: string;\n identity: Identity;\n clientEventId: string;\n attributionToken?: string;\n }): Promise<{ attributionContextId: string | null; serverTime: string }> {\n const response = await this.post(\n \"/v2/bootstrap\",\n input.sourceKey,\n {\n schemaVersion: 2,\n clientEventId: input.clientEventId,\n ...input.identity,\n occurredAt: new Date().toISOString(),\n metadata: { platform: \"web\", sdkVersion: SDK_VERSION, locale: locale() },\n ...(input.attributionToken ? { attributionToken: input.attributionToken } : {}),\n },\n false,\n );\n return (await response.json()) as { attributionContextId: string | null; serverTime: string };\n }\n\n async send(sourceKey: string, events: WebEvent[], keepalive: boolean): Promise<BatchResponse> {\n const response = await this.post(\n \"/v2/events/batch\",\n sourceKey,\n { schemaVersion: 2, events },\n keepalive,\n );\n return (await response.json()) as BatchResponse;\n }\n\n private async post(\n path: string,\n sourceKey: string,\n body: unknown,\n keepalive: boolean,\n ): Promise<Response> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await fetch(`${this.collectorOrigin}${path}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-WTS-Source-Key\": sourceKey },\n body: JSON.stringify(body),\n credentials: \"omit\",\n mode: \"cors\",\n cache: \"no-store\",\n keepalive,\n signal: controller.signal,\n });\n if (!response.ok) throw await TransportError.fromResponse(response);\n return response;\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class TransportError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly retryable: boolean,\n readonly code?: string,\n ) {\n super(message);\n this.name = \"WtsTransportError\";\n }\n\n static async fromResponse(response: Response): Promise<TransportError> {\n let payload: { code?: string; message?: string } = {};\n try {\n payload = (await response.json()) as typeof payload;\n } catch {\n // The SDK intentionally does not surface response bodies in logs.\n }\n return new TransportError(\n payload.message ?? `Collector request failed with status ${response.status}.`,\n response.status,\n response.status === 429 || response.status >= 500,\n payload.code,\n );\n }\n}\n","import type { EventProperties, Revenue, WtsClientOptions } from \"./types\";\n\nconst eventKeyPattern = /^[a-z][a-z0-9_]{1,63}$/;\nconst sourceKeyPattern = /^[A-Za-z0-9_-]{8,128}$/;\nconst currencyPattern = /^[A-Z]{3}$/;\nconst amountPattern = /^-?\\d{1,12}(?:\\.\\d{1,6})?$/;\n\nexport function validateOptions(\n options: WtsClientOptions,\n): Required<\n Pick<\n WtsClientOptions,\n \"sourceKey\" | \"autoTrackPageViews\" | \"collectorOrigin\" | \"requestTimeoutMs\" | \"debug\"\n >\n> & { consent: NonNullable<WtsClientOptions[\"consent\"]> } {\n if (!sourceKeyPattern.test(options.sourceKey)) {\n throw new TypeError(\"sourceKey must be a valid wts.is Web App source key.\");\n }\n const collector = new URL(options.collectorOrigin ?? \"https://collect.wts.is\");\n if (collector.protocol !== \"https:\" && !isLocalhost(collector.hostname)) {\n throw new TypeError(\"collectorOrigin must use HTTPS outside localhost.\");\n }\n if (collector.pathname !== \"/\" || collector.search || collector.hash) {\n throw new TypeError(\"collectorOrigin must not include a path, query, or fragment.\");\n }\n const timeout = options.requestTimeoutMs ?? 2_000;\n if (!Number.isInteger(timeout) || timeout < 250 || timeout > 30_000) {\n throw new TypeError(\"requestTimeoutMs must be an integer between 250 and 30000.\");\n }\n return {\n sourceKey: options.sourceKey,\n consent: options.consent ?? \"pending\",\n autoTrackPageViews: options.autoTrackPageViews ?? false,\n collectorOrigin: collector.origin,\n requestTimeoutMs: timeout,\n debug: options.debug ?? false,\n };\n}\n\nexport function validateEvent(\n eventKey: string,\n properties: EventProperties,\n revenue?: Revenue,\n): void {\n if (!eventKeyPattern.test(eventKey)) {\n throw new TypeError(\"eventKey must match ^[a-z][a-z0-9_]{1,63}$.\");\n }\n const entries = Object.entries(properties);\n if (entries.length > 20) throw new TypeError(\"Events can contain at most 20 properties.\");\n for (const [key, value] of entries) {\n if (!/^[a-z][a-z0-9_]{0,63}$/.test(key)) throw new TypeError(`Invalid property key: ${key}`);\n if (![\"string\", \"number\", \"boolean\"].includes(typeof value)) {\n throw new TypeError(`Property ${key} must be a string, number, or boolean.`);\n }\n if (typeof value === \"string\" && value.length > 512) {\n throw new TypeError(`Property ${key} cannot exceed 512 characters.`);\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(`Property ${key} must be finite.`);\n }\n }\n if (revenue && (!amountPattern.test(revenue.amount) || !currencyPattern.test(revenue.currency))) {\n throw new TypeError(\"Revenue requires a decimal amount and uppercase ISO-4217 currency.\");\n }\n}\n\nexport function normalizePathname(pathname: string): string {\n const normalized = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n if (normalized.includes(\"?\") || normalized.includes(\"#\")) {\n throw new TypeError(\"Page pathname cannot include a query or fragment.\");\n }\n if (normalized.length > 2_048)\n throw new TypeError(\"Page pathname cannot exceed 2048 characters.\");\n return normalized;\n}\n\nfunction isLocalhost(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\";\n}\n","import { ATTRIBUTION_QUERY_KEY, MAX_BATCH_BYTES, MAX_BATCH_EVENTS, SDK_VERSION } from \"./constants\";\nimport { MultiTabLock } from \"./multitab-lock\";\nimport {\n byteLength,\n clearBrowserSession,\n createUuid,\n loadBrowserSession,\n locale,\n referrerHost,\n safeWarn,\n saveBrowserSession,\n} from \"./runtime\";\nimport { installSpaTracker } from \"./spa-tracker\";\nimport { createStorage, deleteStorage, MemoryStorage } from \"./storage\";\nimport { HttpTransport, TransportError } from \"./transport\";\nimport type {\n ConsentState,\n EventProperties,\n FlushResult,\n Identity,\n OperationResult,\n Revenue,\n StorageAdapter,\n Transport,\n WebEvent,\n WtsClient,\n WtsClientOptions,\n} from \"./types\";\nimport { normalizePathname, validateEvent, validateOptions } from \"./validation\";\n\ntype ResolvedOptions = ReturnType<typeof validateOptions>;\nconst ATTRIBUTION_CONTEXT_TTL_MS = 7 * 24 * 60 * 60_000;\n\nexport class WtsClientImpl implements WtsClient {\n private consent: ConsentState;\n private storage: StorageAdapter | undefined;\n private identity: Identity | undefined;\n private attributionContextId: string | undefined;\n private attributionContextExpiresAt: number | undefined;\n private attributionToken: string | undefined;\n private bootstrapClientEventId = createUuid();\n private bootstrapped = false;\n private destroyed = false;\n private retryAttempt = 0;\n private retryTimer: ReturnType<typeof setTimeout> | undefined;\n private enablePromise: Promise<void> | undefined;\n private removeSpaTracker: (() => void) | undefined;\n private lastPagePath: string | undefined;\n private readonly options: ResolvedOptions;\n private readonly transport: Transport;\n private readonly lock: MultiTabLock;\n\n constructor(options: WtsClientOptions, transport?: Transport) {\n this.options = validateOptions(options);\n this.consent = this.options.consent;\n this.transport =\n transport ?? new HttpTransport(this.options.collectorOrigin, this.options.requestTimeoutMs);\n this.lock = new MultiTabLock(`flush-${this.options.sourceKey}`);\n this.attributionToken = captureAttributionToken();\n this.installLifecycleListeners();\n if (this.consent === \"granted\") void this.startEnable();\n if (this.consent === \"denied\") this.attributionToken = undefined;\n }\n\n async setConsent(consent: \"granted\" | \"denied\"): Promise<void> {\n if (this.destroyed) return;\n if (consent === \"denied\") {\n this.consent = \"denied\";\n this.cancelRetry();\n const storage = this.storage;\n if (storage) {\n await this.lock.run(async () => {\n await storage.clear();\n storage.close();\n });\n }\n try {\n await deleteStorage(this.options.sourceKey);\n } catch {\n safeWarn(this.options.debug, \"Stored SDK data could not be deleted because it is in use.\");\n }\n this.storage = undefined;\n this.identity = undefined;\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n this.attributionToken = undefined;\n this.bootstrapped = false;\n clearBrowserSession(this.options.sourceKey);\n this.removeSpaTracking();\n return;\n }\n const wasGranted = this.consent === \"granted\";\n this.consent = \"granted\";\n if (!wasGranted || !this.storage) await this.startEnable();\n }\n\n async page(name?: string): Promise<OperationResult> {\n let unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n await this.ensureReady();\n unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n const pathname = currentPathname();\n const referrer = referrerHost();\n const event: WebEvent = {\n ...this.eventBase(\"page_view\"),\n pathname,\n ...(name?.trim() ? { pageName: name.trim().slice(0, 120) } : {}),\n ...(referrer ? { referrerHost: referrer } : {}),\n properties: {},\n };\n await this.enqueue(event);\n this.lastPagePath = pathname;\n return { accepted: true, clientEventId: event.clientEventId };\n }\n\n async track(\n eventKey: string,\n properties: EventProperties = {},\n revenue?: Revenue,\n ): Promise<OperationResult> {\n let unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n await this.ensureReady();\n unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n validateEvent(eventKey, properties, revenue);\n const event: WebEvent = {\n ...this.eventBase(\"custom\"),\n eventKey,\n properties: { ...properties },\n ...(revenue ? { revenue: { ...revenue } } : {}),\n };\n await this.enqueue(event);\n return { accepted: true, clientEventId: event.clientEventId };\n }\n\n async flush(): Promise<FlushResult> {\n if (this.consent !== \"granted\" || this.destroyed || !this.storage) {\n return { sent: 0, pending: 0 };\n }\n const result = await this.lock.run(async () => this.flushExclusive(false));\n return result ?? { sent: 0, pending: (await this.storage.load()).queue.length };\n }\n\n async reset(): Promise<void> {\n this.cancelRetry();\n await this.storage?.clear();\n this.identity = undefined;\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n this.attributionToken = undefined;\n clearBrowserSession(this.options.sourceKey);\n this.bootstrapClientEventId = createUuid();\n this.bootstrapped = false;\n this.lastPagePath = undefined;\n if (this.consent === \"granted\" && !this.destroyed) await this.initializeIdentity();\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cancelRetry();\n this.removeSpaTracking();\n this.removeLifecycleListeners();\n const storage = this.storage;\n if (storage) void this.lock.run(async () => storage.close());\n }\n\n private async enable(): Promise<void> {\n if (this.destroyed || this.consent !== \"granted\") return;\n if (!this.storage) {\n try {\n this.storage = await createStorage(this.options.sourceKey);\n await this.storage.load();\n } catch {\n this.storage?.close();\n this.storage = new MemoryStorage();\n safeWarn(this.options.debug, \"IndexedDB unavailable; using a memory-only event queue.\");\n }\n }\n await this.initializeIdentity();\n try {\n await this.ensureBootstrapped();\n } catch (error) {\n this.handleRetryableError(error);\n }\n if (this.options.autoTrackPageViews && !this.removeSpaTracker) {\n this.removeSpaTracker = installSpaTracker(() => {\n void this.trackAutomaticPage();\n });\n await this.trackAutomaticPage();\n }\n void this.flush();\n }\n\n private startEnable(): Promise<void> {\n if (this.enablePromise) return this.enablePromise;\n const pending = this.enable();\n this.enablePromise = pending;\n void pending.finally(() => {\n if (this.enablePromise === pending) this.enablePromise = undefined;\n });\n return pending;\n }\n\n private async ensureReady(): Promise<void> {\n if (this.consent === \"granted\" && (!this.storage || !this.identity)) {\n await this.startEnable();\n }\n }\n\n private async initializeIdentity(): Promise<void> {\n if (!this.storage) return;\n const state = await this.storage.load();\n const browserSession = loadBrowserSession(this.options.sourceKey);\n this.identity = {\n anonymousId: state.identity?.anonymousId ?? createUuid(),\n sessionId: browserSession?.sessionId ?? createUuid(),\n };\n this.bootstrapClientEventId = browserSession?.bootstrapClientEventId ?? createUuid();\n saveBrowserSession(this.options.sourceKey, {\n sessionId: this.identity.sessionId,\n bootstrapClientEventId: this.bootstrapClientEventId,\n });\n const contextExpiry = state.attributionContextExpiresAt\n ? Date.parse(state.attributionContextExpiresAt)\n : Number.NaN;\n if (\n state.attributionContextId &&\n Number.isFinite(contextExpiry) &&\n contextExpiry > Date.now()\n ) {\n this.attributionContextId = state.attributionContextId;\n this.attributionContextExpiresAt = contextExpiry;\n } else if (state.attributionContextId || state.attributionContextExpiresAt) {\n await this.storage.saveAttributionContext();\n }\n if (\n !state.identity ||\n state.identity.anonymousId !== this.identity.anonymousId ||\n state.identity.sessionId !== this.identity.sessionId\n ) {\n await this.storage.saveIdentity(this.identity);\n }\n }\n\n private async ensureBootstrapped(): Promise<void> {\n if (this.bootstrapped || !this.identity || !this.storage) return;\n const result = await this.transport.bootstrap({\n sourceKey: this.options.sourceKey,\n identity: this.identity,\n clientEventId: this.bootstrapClientEventId,\n ...(this.attributionToken ? { attributionToken: this.attributionToken } : {}),\n });\n this.bootstrapped = true;\n this.attributionToken = undefined;\n if (result.attributionContextId) {\n this.attributionContextId = result.attributionContextId;\n const serverTime = Date.parse(result.serverTime);\n this.attributionContextExpiresAt =\n (Number.isFinite(serverTime) ? serverTime : Date.now()) + ATTRIBUTION_CONTEXT_TTL_MS;\n await this.storage.saveAttributionContext(\n result.attributionContextId,\n new Date(this.attributionContextExpiresAt).toISOString(),\n );\n }\n this.retryAttempt = 0;\n }\n\n private async enqueue(event: WebEvent): Promise<void> {\n if (!this.storage) return;\n await this.storage.enqueue(event);\n queueMicrotask(() => void this.flush());\n }\n\n private async flushExclusive(keepalive: boolean): Promise<FlushResult> {\n if (!this.storage) return { sent: 0, pending: 0 };\n if (this.retryTimer && !keepalive) {\n return { sent: 0, pending: (await this.storage.load()).queue.length };\n }\n try {\n await this.ensureBootstrapped();\n const state = await this.storage.load();\n const batch = takeBatch(state.queue, this.activeAttributionContextId());\n if (batch.length === 0) return { sent: 0, pending: state.queue.length };\n const response = await this.transport.send(this.options.sourceKey, batch, keepalive);\n const remove = new Set([...response.accepted, ...response.duplicates]);\n let hasRetryableRejection = false;\n for (const rejection of response.rejected) {\n if (rejection.retryable) hasRetryableRejection = true;\n else remove.add(rejection.clientEventId);\n }\n await this.storage.remove(remove);\n const pending = (await this.storage.load()).queue.length;\n if (hasRetryableRejection) this.scheduleRetry();\n else {\n this.retryAttempt = 0;\n if (pending > 0) queueMicrotask(() => void this.flush());\n }\n return { sent: remove.size, pending };\n } catch (error) {\n this.handleRetryableError(error);\n return { sent: 0, pending: (await this.storage.load()).queue.length };\n }\n }\n\n private handleRetryableError(error: unknown): void {\n if (error instanceof TransportError && !error.retryable) {\n safeWarn(\n this.options.debug,\n `Collector rejected the request (${error.code ?? error.status}).`,\n );\n return;\n }\n this.scheduleRetry();\n }\n\n private scheduleRetry(): void {\n if (this.consent !== \"granted\" || this.destroyed || this.retryTimer) return;\n const base = Math.min(60_000, 1_000 * 2 ** Math.min(this.retryAttempt, 6));\n const jitter = Math.floor(Math.random() * Math.max(1, base * 0.25));\n this.retryAttempt += 1;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined;\n void this.flush();\n }, base + jitter);\n }\n\n private async trackAutomaticPage(): Promise<void> {\n const pathname = currentPathname();\n if (pathname === this.lastPagePath) return;\n await this.page();\n }\n\n private eventBase(type: WebEvent[\"type\"]): Omit<WebEvent, \"properties\"> {\n if (!this.identity) throw new Error(\"Web SDK identity is unavailable.\");\n const attributionContextId = this.activeAttributionContextId();\n return {\n schemaVersion: 2,\n clientEventId: createUuid(),\n ...this.identity,\n type,\n occurredAt: new Date().toISOString(),\n metadata: { platform: \"web\", sdkVersion: SDK_VERSION, locale: locale() },\n ...(attributionContextId ? { attributionContextId } : {}),\n };\n }\n\n private unavailableResult(): OperationResult | undefined {\n if (this.destroyed) return { accepted: false, reason: \"destroyed\" };\n if (this.consent === \"pending\") return { accepted: false, reason: \"consent_pending\" };\n if (this.consent === \"denied\") return { accepted: false, reason: \"consent_denied\" };\n return undefined;\n }\n\n private activeAttributionContextId(): string | undefined {\n if (\n this.attributionContextId &&\n this.attributionContextExpiresAt &&\n this.attributionContextExpiresAt > Date.now()\n ) {\n return this.attributionContextId;\n }\n if (this.attributionContextId || this.attributionContextExpiresAt) {\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n void this.storage?.saveAttributionContext();\n }\n return undefined;\n }\n\n private installLifecycleListeners(): void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n window.addEventListener(\"pagehide\", this.onPageHide);\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n private removeLifecycleListeners(): void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n window.removeEventListener(\"pagehide\", this.onPageHide);\n document.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n private readonly onPageHide = () => {\n if (this.consent === \"granted\") void this.lock.run(() => this.flushExclusive(true));\n };\n\n private readonly onVisibilityChange = () => {\n if (document.visibilityState === \"hidden\" && this.consent === \"granted\") {\n void this.lock.run(() => this.flushExclusive(true));\n }\n };\n\n private removeSpaTracking(): void {\n this.removeSpaTracker?.();\n this.removeSpaTracker = undefined;\n }\n\n private cancelRetry(): void {\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n}\n\nfunction currentPathname(): string {\n return normalizePathname(typeof location === \"undefined\" ? \"/\" : location.pathname);\n}\n\nfunction captureAttributionToken(): string | undefined {\n if (typeof location === \"undefined\" || typeof history === \"undefined\") return undefined;\n const url = new URL(location.href);\n const token = url.searchParams.get(ATTRIBUTION_QUERY_KEY) ?? undefined;\n if (!token) return undefined;\n url.searchParams.delete(ATTRIBUTION_QUERY_KEY);\n history.replaceState(history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n return token;\n}\n\nfunction takeBatch(queue: WebEvent[], attributionContextId?: string): WebEvent[] {\n const batch: WebEvent[] = [];\n for (const queued of queue.slice(0, MAX_BATCH_EVENTS)) {\n const event = attributionContextId ? { ...queued, attributionContextId } : queued;\n if (byteLength({ schemaVersion: 2, events: [...batch, event] }) > MAX_BATCH_BYTES) break;\n batch.push(event);\n }\n return batch;\n}\n","import { WtsClientImpl } from \"./client\";\nimport type { WtsClient, WtsClientOptions } from \"./types\";\n\nexport type {\n ConsentState,\n EventProperties,\n FlushResult,\n OperationResult,\n Revenue,\n Scalar,\n WtsClient,\n WtsClientOptions,\n} from \"./types\";\n\nexport function createWtsClient(options: WtsClientOptions): WtsClient {\n return new WtsClientImpl(options);\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/runtime.ts","../src/multitab-lock.ts","../src/spa-tracker.ts","../src/storage.ts","../src/transport.ts","../src/validation.ts","../src/client.ts","../src/index.ts"],"names":["SDK_VERSION","ATTRIBUTION_QUERY_KEY","createUuid","cryptoApi","bytes","hex","value","byteLength","locale","referrerHost","safeWarn","enabled","message","loadBrowserSession","sourceKey","parsed","sessionKey","isUuid","saveBrowserSession","state","clearBrowserSession","LEASE_MS","MultiTabLock","name","operation","lease","current","key","token","now","parseLease","installSpaTracker","onNavigate","historyApi","originalPush","originalReplace","scheduled","notify","args","META_STORE","EVENT_STORE","IDENTITY_STORE","createStorage","IndexedDbStorage","deleteStorage","request","databaseName","resolve","reject","MemoryStorage","clone","identity","expiresAt","event","trimQueues","mutation","clientEventIds","clientMutationIds","_IndexedDbStorage","database","requestResult","transaction","meta","events","mutations","attributionContextId","attributionContextExpiresAt","queue","identityQueue","transactionDone","left","right","store","existing","retainedIds","item","retainedMutations","identityStore","queued","retainedEvents","eventStore","id","HttpTransport","collectorOrigin","timeoutMs","input","keepalive","path","body","controller","timeout","response","TransportError","_TransportError","status","retryable","code","payload","eventKeyPattern","sourceKeyPattern","currencyPattern","amountPattern","attributeKeyPattern","validateOptions","options","collector","isLocalhost","validateEvent","eventKey","properties","revenue","entries","validateExternalUserId","validateUserAttributes","attributes","validateAttributeEntries","validateUserUpdate","operations","keys","validateAttributeKey","validateReportedAttribution","max","normalizePathname","pathname","normalized","hostname","ATTRIBUTION_CONTEXT_TTL_MS","WtsClientImpl","transport","captureAttributionToken","consent","storage","wasGranted","unavailable","currentPathname","referrer","externalUserId","normalizeUserAttributes","structuredCloneSafe","attribution","result","error","pending","browserSession","contextExpiry","serverTime","identityBatch","takeIdentityBatch","identityResponse","permanentlyRejected","hasRetryableRejection","pendingState","refreshedState","batch","takeBatch","remove","rejection","base","jitter","type","url","createWtsClient"],"mappings":"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","file":"index.cjs","sourcesContent":["export const SDK_VERSION = \"0.2.0-alpha.1\";\nexport const DEFAULT_COLLECTOR_ORIGIN = \"https://collect.wts.is\";\nexport const MAX_QUEUE_EVENTS = 100;\nexport const MAX_QUEUE_BYTES = 1024 * 1024;\nexport const MAX_BATCH_EVENTS = 50;\nexport const MAX_BATCH_BYTES = 64 * 1024;\nexport const DEFAULT_TIMEOUT_MS = 2_000;\nexport const ATTRIBUTION_QUERY_KEY = \"_wts\";\n","export function createUuid(): string {\n const cryptoApi = globalThis.crypto;\n if (!cryptoApi) throw new Error(\"A secure random number generator is required.\");\n if (typeof cryptoApi.randomUUID === \"function\") return cryptoApi.randomUUID();\n const bytes = cryptoApi.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\"));\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10).join(\"\")}`;\n}\n\nexport function byteLength(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nexport function locale(): string {\n return typeof navigator === \"undefined\" ? \"en\" : navigator.language || \"en\";\n}\n\nexport function referrerHost(): string | undefined {\n if (typeof document === \"undefined\" || !document.referrer) return undefined;\n try {\n return new URL(document.referrer).hostname.toLowerCase() || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function safeWarn(enabled: boolean, message: string): void {\n if (enabled && typeof console !== \"undefined\") console.warn(`[wts.is] ${message}`);\n}\n\nexport type BrowserSessionState = {\n sessionId: string;\n bootstrapClientEventId: string;\n};\n\nexport function loadBrowserSession(sourceKey: string): BrowserSessionState | undefined {\n if (typeof sessionStorage === \"undefined\") return undefined;\n try {\n const parsed = JSON.parse(sessionStorage.getItem(sessionKey(sourceKey)) ?? \"null\") as {\n sessionId?: unknown;\n bootstrapClientEventId?: unknown;\n } | null;\n return parsed && isUuid(parsed.sessionId) && isUuid(parsed.bootstrapClientEventId)\n ? {\n sessionId: parsed.sessionId,\n bootstrapClientEventId: parsed.bootstrapClientEventId,\n }\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function saveBrowserSession(sourceKey: string, state: BrowserSessionState): void {\n if (typeof sessionStorage === \"undefined\") return;\n try {\n sessionStorage.setItem(sessionKey(sourceKey), JSON.stringify(state));\n } catch {\n // Storage restrictions are handled by the SDK's memory-only fallback.\n }\n}\n\nexport function clearBrowserSession(sourceKey: string): void {\n if (typeof sessionStorage === \"undefined\") return;\n try {\n sessionStorage.removeItem(sessionKey(sourceKey));\n } catch {\n // A blocked browser storage API is equivalent to an already cleared session.\n }\n}\n\nfunction sessionKey(sourceKey: string): string {\n return `wts-session-${sourceKey}`;\n}\n\nfunction isUuid(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)\n );\n}\n","import { createUuid } from \"./runtime\";\n\nconst LEASE_MS = 10_000;\n\nexport class MultiTabLock {\n private current: Promise<unknown> | undefined;\n\n constructor(private readonly name: string) {}\n\n async run<T>(operation: () => Promise<T>): Promise<T | undefined> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(this.name, operation);\n }\n if (this.current) await this.current;\n const lease = this.acquireLease();\n if (!lease) return undefined;\n const current = operation();\n this.current = current;\n try {\n return await current;\n } finally {\n if (this.current === current) this.current = undefined;\n lease.release();\n }\n }\n\n private acquireLease(): { release(): void } | undefined {\n if (typeof localStorage === \"undefined\") return { release() {} };\n const key = `wts-lock-${this.name}`;\n const token = createUuid();\n const now = Date.now();\n try {\n const current = parseLease(localStorage.getItem(key));\n if (current && current.expiresAt > now) return undefined;\n localStorage.setItem(key, JSON.stringify({ token, expiresAt: now + LEASE_MS }));\n const acquired = parseLease(localStorage.getItem(key));\n if (acquired?.token !== token) return undefined;\n return {\n release() {\n const latest = parseLease(localStorage.getItem(key));\n if (latest?.token === token) localStorage.removeItem(key);\n },\n };\n } catch {\n return { release() {} };\n }\n }\n}\n\nfunction parseLease(value: string | null): { token: string; expiresAt: number } | undefined {\n if (!value) return undefined;\n try {\n const parsed = JSON.parse(value) as { token?: unknown; expiresAt?: unknown };\n return typeof parsed.token === \"string\" && typeof parsed.expiresAt === \"number\"\n ? { token: parsed.token, expiresAt: parsed.expiresAt }\n : undefined;\n } catch {\n return undefined;\n }\n}\n","export function installSpaTracker(onNavigate: () => void): () => void {\n if (typeof window === \"undefined\") return () => undefined;\n const historyApi = window.history;\n const originalPush = historyApi.pushState;\n const originalReplace = historyApi.replaceState;\n let scheduled = false;\n const notify = () => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n onNavigate();\n });\n };\n historyApi.pushState = function (...args) {\n originalPush.apply(this, args);\n notify();\n };\n historyApi.replaceState = function (...args) {\n originalReplace.apply(this, args);\n notify();\n };\n window.addEventListener(\"popstate\", notify);\n return () => {\n historyApi.pushState = originalPush;\n historyApi.replaceState = originalReplace;\n window.removeEventListener(\"popstate\", notify);\n };\n}\n","import { MAX_QUEUE_BYTES, MAX_QUEUE_EVENTS } from \"./constants\";\nimport { byteLength } from \"./runtime\";\nimport type { Identity, IdentityMutation, StorageAdapter, StoredState, WebEvent } from \"./types\";\n\nconst META_STORE = \"meta\";\nconst EVENT_STORE = \"events\";\nconst IDENTITY_STORE = \"identity_mutations\";\n\nexport async function createStorage(sourceKey: string): Promise<StorageAdapter> {\n if (typeof indexedDB === \"undefined\") throw new Error(\"IndexedDB is unavailable.\");\n return IndexedDbStorage.open(sourceKey);\n}\n\nexport async function deleteStorage(sourceKey: string): Promise<void> {\n if (typeof indexedDB === \"undefined\") return;\n const request = indexedDB.deleteDatabase(databaseName(sourceKey));\n await new Promise<void>((resolve, reject) => {\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error ?? new Error(\"IndexedDB deletion failed.\"));\n request.onblocked = () => reject(new Error(\"IndexedDB deletion was blocked by another tab.\"));\n });\n}\n\nexport class MemoryStorage implements StorageAdapter {\n private state: StoredState = { queue: [], identityQueue: [] };\n\n async load(): Promise<StoredState> {\n return clone(this.state);\n }\n\n async saveIdentity(identity: Identity): Promise<void> {\n this.state.identity = { ...identity };\n }\n\n async saveAttributionContext(value?: string, expiresAt?: string): Promise<void> {\n if (value && expiresAt) {\n this.state.attributionContextId = value;\n this.state.attributionContextExpiresAt = expiresAt;\n } else {\n delete this.state.attributionContextId;\n delete this.state.attributionContextExpiresAt;\n }\n }\n\n async enqueue(event: WebEvent): Promise<void> {\n this.state.queue.push(clone(event));\n trimQueues(this.state);\n }\n\n async enqueueIdentity(mutation: IdentityMutation): Promise<void> {\n this.state.identityQueue.push(clone(mutation));\n trimQueues(this.state);\n }\n\n async remove(clientEventIds: ReadonlySet<string>): Promise<void> {\n this.state.queue = this.state.queue.filter((event) => !clientEventIds.has(event.clientEventId));\n }\n\n async removeIdentity(clientMutationIds: ReadonlySet<string>): Promise<void> {\n this.state.identityQueue = this.state.identityQueue.filter(\n (mutation) => !clientMutationIds.has(mutation.clientMutationId),\n );\n }\n\n async clear(): Promise<void> {\n this.state = { queue: [], identityQueue: [] };\n }\n\n close(): void {}\n}\n\nclass IndexedDbStorage implements StorageAdapter {\n private constructor(private readonly database: IDBDatabase) {}\n\n static async open(sourceKey: string): Promise<IndexedDbStorage> {\n const request = indexedDB.open(databaseName(sourceKey), 2);\n request.onupgradeneeded = () => {\n const database = request.result;\n if (!database.objectStoreNames.contains(META_STORE)) database.createObjectStore(META_STORE);\n if (!database.objectStoreNames.contains(EVENT_STORE)) {\n database.createObjectStore(EVENT_STORE, { keyPath: \"clientEventId\" });\n }\n if (!database.objectStoreNames.contains(IDENTITY_STORE)) {\n database.createObjectStore(IDENTITY_STORE, { keyPath: \"clientMutationId\" });\n }\n };\n return new IndexedDbStorage(await requestResult(request));\n }\n\n async load(): Promise<StoredState> {\n const transaction = this.database.transaction(\n [META_STORE, EVENT_STORE, IDENTITY_STORE],\n \"readonly\",\n );\n const meta = transaction.objectStore(META_STORE);\n const events = transaction.objectStore(EVENT_STORE);\n const mutations = transaction.objectStore(IDENTITY_STORE);\n const [identity, attributionContextId, attributionContextExpiresAt, queue, identityQueue] =\n await Promise.all([\n requestResult(meta.get(\"identity\") as IDBRequest<Identity | undefined>),\n requestResult(meta.get(\"attributionContextId\") as IDBRequest<string | undefined>),\n requestResult(meta.get(\"attributionContextExpiresAt\") as IDBRequest<string | undefined>),\n requestResult(events.getAll() as IDBRequest<WebEvent[]>),\n requestResult(mutations.getAll() as IDBRequest<IdentityMutation[]>),\n ]);\n await transactionDone(transaction);\n queue.sort((left, right) => left.occurredAt.localeCompare(right.occurredAt));\n identityQueue.sort((left, right) => left.occurredAt.localeCompare(right.occurredAt));\n return {\n ...(identity ? { identity } : {}),\n ...(attributionContextId && attributionContextExpiresAt\n ? { attributionContextId, attributionContextExpiresAt }\n : {}),\n queue,\n identityQueue,\n };\n }\n\n async saveIdentity(identity: Identity): Promise<void> {\n await this.writeMeta(\"identity\", identity);\n }\n\n async saveAttributionContext(value?: string, expiresAt?: string): Promise<void> {\n const transaction = this.database.transaction(META_STORE, \"readwrite\");\n const store = transaction.objectStore(META_STORE);\n if (value && expiresAt) {\n store.put(value, \"attributionContextId\");\n store.put(expiresAt, \"attributionContextExpiresAt\");\n } else {\n store.delete(\"attributionContextId\");\n store.delete(\"attributionContextExpiresAt\");\n }\n await transactionDone(transaction);\n }\n\n async enqueue(event: WebEvent): Promise<void> {\n const existing = await this.load();\n const state = clone(existing);\n state.queue.push(event);\n trimQueues(state);\n const retainedIds = new Set(state.queue.map((item) => item.clientEventId));\n const retainedMutations = new Set(state.identityQueue.map((item) => item.clientMutationId));\n const transaction = this.database.transaction([EVENT_STORE, IDENTITY_STORE], \"readwrite\");\n const store = transaction.objectStore(EVENT_STORE);\n const identityStore = transaction.objectStore(IDENTITY_STORE);\n store.put(event);\n for (const queued of existing.queue) {\n if (!retainedIds.has(queued.clientEventId)) store.delete(queued.clientEventId);\n }\n for (const mutation of state.identityQueue) identityStore.put(mutation);\n for (const mutation of existing.identityQueue) {\n if (!retainedMutations.has(mutation.clientMutationId)) {\n identityStore.delete(mutation.clientMutationId);\n }\n }\n await transactionDone(transaction);\n }\n\n async enqueueIdentity(mutation: IdentityMutation): Promise<void> {\n const existing = await this.load();\n const state = clone(existing);\n state.identityQueue.push(mutation);\n trimQueues(state);\n const retainedEvents = new Set(state.queue.map((item) => item.clientEventId));\n const retainedMutations = new Set(state.identityQueue.map((item) => item.clientMutationId));\n const transaction = this.database.transaction([EVENT_STORE, IDENTITY_STORE], \"readwrite\");\n const eventStore = transaction.objectStore(EVENT_STORE);\n const identityStore = transaction.objectStore(IDENTITY_STORE);\n identityStore.put(mutation);\n for (const event of existing.queue) {\n if (!retainedEvents.has(event.clientEventId)) eventStore.delete(event.clientEventId);\n }\n for (const queued of existing.identityQueue) {\n if (!retainedMutations.has(queued.clientMutationId)) {\n identityStore.delete(queued.clientMutationId);\n }\n }\n await transactionDone(transaction);\n }\n\n async remove(clientEventIds: ReadonlySet<string>): Promise<void> {\n if (clientEventIds.size === 0) return;\n const transaction = this.database.transaction(EVENT_STORE, \"readwrite\");\n const store = transaction.objectStore(EVENT_STORE);\n for (const id of clientEventIds) store.delete(id);\n await transactionDone(transaction);\n }\n\n async removeIdentity(clientMutationIds: ReadonlySet<string>): Promise<void> {\n if (clientMutationIds.size === 0) return;\n const transaction = this.database.transaction(IDENTITY_STORE, \"readwrite\");\n const store = transaction.objectStore(IDENTITY_STORE);\n for (const id of clientMutationIds) store.delete(id);\n await transactionDone(transaction);\n }\n\n async clear(): Promise<void> {\n const transaction = this.database.transaction(\n [META_STORE, EVENT_STORE, IDENTITY_STORE],\n \"readwrite\",\n );\n transaction.objectStore(META_STORE).clear();\n transaction.objectStore(EVENT_STORE).clear();\n transaction.objectStore(IDENTITY_STORE).clear();\n await transactionDone(transaction);\n }\n\n close(): void {\n this.database.close();\n }\n\n private async writeMeta(key: string, value: unknown): Promise<void> {\n const transaction = this.database.transaction(META_STORE, \"readwrite\");\n transaction.objectStore(META_STORE).put(value, key);\n await transactionDone(transaction);\n }\n}\n\nfunction trimQueues(state: StoredState): void {\n while (\n state.queue.length + state.identityQueue.length > MAX_QUEUE_EVENTS ||\n byteLength({ events: state.queue, mutations: state.identityQueue }) > MAX_QUEUE_BYTES\n ) {\n if (state.queue.length > 0) state.queue.shift();\n else state.identityQueue.shift();\n }\n}\n\nfunction requestResult<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error ?? new Error(\"IndexedDB request failed.\"));\n });\n}\n\nfunction transactionDone(transaction: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () =>\n reject(transaction.error ?? new Error(\"IndexedDB transaction failed.\"));\n transaction.onabort = () =>\n reject(transaction.error ?? new Error(\"IndexedDB transaction aborted.\"));\n });\n}\n\nfunction clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction databaseName(sourceKey: string): string {\n return `wts-web-${sourceKey}`;\n}\n","import { SDK_VERSION } from \"./constants\";\nimport { locale } from \"./runtime\";\nimport type {\n BatchResponse,\n Identity,\n IdentityBatchResponse,\n IdentityMutation,\n Transport,\n WebEvent,\n} from \"./types\";\n\nexport class HttpTransport implements Transport {\n constructor(\n private readonly collectorOrigin: string,\n private readonly timeoutMs: number,\n ) {}\n\n async bootstrap(input: {\n sourceKey: string;\n identity: Identity;\n clientEventId: string;\n attributionToken?: string;\n }): Promise<{ attributionContextId: string | null; serverTime: string }> {\n const response = await this.post(\n \"/v3/bootstrap\",\n input.sourceKey,\n {\n schemaVersion: 3,\n clientEventId: input.clientEventId,\n ...input.identity,\n occurredAt: new Date().toISOString(),\n metadata: { platform: \"web\", sdkVersion: SDK_VERSION, locale: locale() },\n ...(input.attributionToken ? { attributionToken: input.attributionToken } : {}),\n },\n false,\n );\n return (await response.json()) as { attributionContextId: string | null; serverTime: string };\n }\n\n async send(sourceKey: string, events: WebEvent[], keepalive: boolean): Promise<BatchResponse> {\n const response = await this.post(\n \"/v3/events/batch\",\n sourceKey,\n { schemaVersion: 3, events },\n keepalive,\n );\n return (await response.json()) as BatchResponse;\n }\n\n async sendIdentity(\n sourceKey: string,\n mutations: IdentityMutation[],\n ): Promise<IdentityBatchResponse> {\n const response = await this.post(\n \"/v3/identity/mutations\",\n sourceKey,\n { schemaVersion: 1, mutations },\n false,\n );\n return (await response.json()) as IdentityBatchResponse;\n }\n\n private async post(\n path: string,\n sourceKey: string,\n body: unknown,\n keepalive: boolean,\n ): Promise<Response> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await fetch(`${this.collectorOrigin}${path}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-WTS-Source-Key\": sourceKey },\n body: JSON.stringify(body),\n credentials: \"omit\",\n mode: \"cors\",\n cache: \"no-store\",\n keepalive,\n signal: controller.signal,\n });\n if (!response.ok) throw await TransportError.fromResponse(response);\n return response;\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class TransportError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly retryable: boolean,\n readonly code?: string,\n ) {\n super(message);\n this.name = \"WtsTransportError\";\n }\n\n static async fromResponse(response: Response): Promise<TransportError> {\n let payload: { code?: string; message?: string } = {};\n try {\n payload = (await response.json()) as typeof payload;\n } catch {\n // The SDK intentionally does not surface response bodies in logs.\n }\n return new TransportError(\n payload.message ?? `Collector request failed with status ${response.status}.`,\n response.status,\n response.status === 429 || response.status >= 500,\n payload.code,\n );\n }\n}\n","import type {\n EventProperties,\n ReportedAttribution,\n Revenue,\n UserAttributes,\n UserUpdateOperations,\n WtsClientOptions,\n} from \"./types\";\n\nconst eventKeyPattern = /^[a-z][a-z0-9_]{1,63}$/;\nconst sourceKeyPattern = /^[A-Za-z0-9_-]{8,128}$/;\nconst currencyPattern = /^[A-Z]{3}$/;\nconst amountPattern = /^-?\\d{1,12}(?:\\.\\d{1,6})?$/;\nconst attributeKeyPattern = /^[a-z][a-z0-9_]{0,63}$/;\n\nexport function validateOptions(\n options: WtsClientOptions,\n): Required<\n Pick<\n WtsClientOptions,\n \"sourceKey\" | \"autoTrackPageViews\" | \"collectorOrigin\" | \"requestTimeoutMs\" | \"debug\"\n >\n> & { consent: NonNullable<WtsClientOptions[\"consent\"]> } {\n if (!sourceKeyPattern.test(options.sourceKey)) {\n throw new TypeError(\"sourceKey must be a valid wts.is Web App source key.\");\n }\n const collector = new URL(options.collectorOrigin ?? \"https://collect.wts.is\");\n if (collector.protocol !== \"https:\" && !isLocalhost(collector.hostname)) {\n throw new TypeError(\"collectorOrigin must use HTTPS outside localhost.\");\n }\n if (collector.pathname !== \"/\" || collector.search || collector.hash) {\n throw new TypeError(\"collectorOrigin must not include a path, query, or fragment.\");\n }\n const timeout = options.requestTimeoutMs ?? 2_000;\n if (!Number.isInteger(timeout) || timeout < 250 || timeout > 30_000) {\n throw new TypeError(\"requestTimeoutMs must be an integer between 250 and 30000.\");\n }\n return {\n sourceKey: options.sourceKey,\n consent: options.consent ?? \"pending\",\n autoTrackPageViews: options.autoTrackPageViews ?? false,\n collectorOrigin: collector.origin,\n requestTimeoutMs: timeout,\n debug: options.debug ?? false,\n };\n}\n\nexport function validateEvent(\n eventKey: string,\n properties: EventProperties,\n revenue?: Revenue,\n): void {\n if (!eventKeyPattern.test(eventKey)) {\n throw new TypeError(\"eventKey must match ^[a-z][a-z0-9_]{1,63}$.\");\n }\n const entries = Object.entries(properties);\n if (entries.length > 20) throw new TypeError(\"Events can contain at most 20 properties.\");\n for (const [key, value] of entries) {\n if (!/^[a-z][a-z0-9_]{0,63}$/.test(key)) throw new TypeError(`Invalid property key: ${key}`);\n if (![\"string\", \"number\", \"boolean\"].includes(typeof value)) {\n throw new TypeError(`Property ${key} must be a string, number, or boolean.`);\n }\n if (typeof value === \"string\" && value.length > 512) {\n throw new TypeError(`Property ${key} cannot exceed 512 characters.`);\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(`Property ${key} must be finite.`);\n }\n }\n if (revenue && (!amountPattern.test(revenue.amount) || !currencyPattern.test(revenue.currency))) {\n throw new TypeError(\"Revenue requires a decimal amount and uppercase ISO-4217 currency.\");\n }\n}\n\nexport function validateExternalUserId(value: string): void {\n if (typeof value !== \"string\" || value.length < 1 || value.length > 128) {\n throw new TypeError(\"externalUserId must contain 1–128 characters.\");\n }\n}\n\nexport function validateUserAttributes(attributes: UserAttributes): void {\n validateAttributeEntries(Object.entries(attributes));\n}\n\nexport function validateUserUpdate(operations: UserUpdateOperations): void {\n const keys = [\n ...Object.keys(operations.set ?? {}),\n ...Object.keys(operations.setOnce ?? {}),\n ...(operations.unset ?? []),\n ...Object.keys(operations.increment ?? {}),\n ];\n if (keys.length === 0) throw new TypeError(\"At least one user update operation is required.\");\n if (keys.length > 50) throw new TypeError(\"A user update can contain at most 50 operations.\");\n if (new Set(keys).size !== keys.length) {\n throw new TypeError(\"An attribute can be changed only once within a user update.\");\n }\n validateAttributeEntries([\n ...Object.entries(operations.set ?? {}),\n ...Object.entries(operations.setOnce ?? {}),\n ]);\n for (const key of operations.unset ?? []) validateAttributeKey(key);\n for (const [key, value] of Object.entries(operations.increment ?? {})) {\n validateAttributeKey(key);\n if (!Number.isFinite(value)) throw new TypeError(`Increment ${key} must be finite.`);\n }\n}\n\nexport function validateReportedAttribution(value: ReportedAttribution): void {\n for (const [key, item, max] of [\n [\"source\", value.source, 120],\n [\"medium\", value.medium, 120],\n [\"campaign\", value.campaign, 160],\n [\"externalRef\", value.externalRef, 256],\n ] as const) {\n if (item === undefined) continue;\n if (!item.trim() || item.length > max) {\n throw new TypeError(`${key} must contain 1–${max} characters.`);\n }\n }\n}\n\nexport function normalizePathname(pathname: string): string {\n const normalized = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n if (normalized.includes(\"?\") || normalized.includes(\"#\")) {\n throw new TypeError(\"Page pathname cannot include a query or fragment.\");\n }\n if (normalized.length > 2_048)\n throw new TypeError(\"Page pathname cannot exceed 2048 characters.\");\n return normalized;\n}\n\nfunction isLocalhost(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\";\n}\n\nfunction validateAttributeEntries(entries: Array<[string, unknown]>): void {\n if (entries.length > 50) throw new TypeError(\"A mutation can contain at most 50 attributes.\");\n for (const [key, value] of entries) {\n validateAttributeKey(key);\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) {\n throw new TypeError(`Attribute ${key} must contain a valid Date.`);\n }\n continue;\n }\n if (Array.isArray(value)) {\n if (\n value.length > 50 ||\n value.some((item) => typeof item !== \"string\" || item.length > 512)\n ) {\n throw new TypeError(`Attribute ${key} must be an array of at most 50 short strings.`);\n }\n continue;\n }\n if (![\"string\", \"number\", \"boolean\"].includes(typeof value)) {\n throw new TypeError(`Attribute ${key} has an unsupported value type.`);\n }\n if (typeof value === \"string\" && value.length > 2_048) {\n throw new TypeError(`Attribute ${key} cannot exceed 2048 characters.`);\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(`Attribute ${key} must be finite.`);\n }\n }\n}\n\nfunction validateAttributeKey(key: string): void {\n if (!attributeKeyPattern.test(key)) throw new TypeError(`Invalid attribute key: ${key}`);\n}\n","import { ATTRIBUTION_QUERY_KEY, MAX_BATCH_BYTES, MAX_BATCH_EVENTS, SDK_VERSION } from \"./constants\";\nimport { MultiTabLock } from \"./multitab-lock\";\nimport {\n byteLength,\n clearBrowserSession,\n createUuid,\n loadBrowserSession,\n locale,\n referrerHost,\n safeWarn,\n saveBrowserSession,\n} from \"./runtime\";\nimport { installSpaTracker } from \"./spa-tracker\";\nimport { createStorage, deleteStorage, MemoryStorage } from \"./storage\";\nimport { HttpTransport, TransportError } from \"./transport\";\nimport type {\n ConsentState,\n EventProperties,\n FlushResult,\n Identity,\n IdentityMutation,\n OperationResult,\n ReportedAttribution,\n Revenue,\n StorageAdapter,\n Transport,\n UserAttributes,\n UserUpdateOperations,\n WebEvent,\n WtsClient,\n WtsClientOptions,\n} from \"./types\";\nimport {\n normalizePathname,\n validateEvent,\n validateExternalUserId,\n validateOptions,\n validateReportedAttribution,\n validateUserAttributes,\n validateUserUpdate,\n} from \"./validation\";\n\ntype ResolvedOptions = ReturnType<typeof validateOptions>;\nconst ATTRIBUTION_CONTEXT_TTL_MS = 7 * 24 * 60 * 60_000;\n\nexport class WtsClientImpl implements WtsClient {\n private consent: ConsentState;\n private storage: StorageAdapter | undefined;\n private identity: Identity | undefined;\n private attributionContextId: string | undefined;\n private attributionContextExpiresAt: number | undefined;\n private attributionToken: string | undefined;\n private bootstrapClientEventId = createUuid();\n private bootstrapped = false;\n private destroyed = false;\n private retryAttempt = 0;\n private retryTimer: ReturnType<typeof setTimeout> | undefined;\n private enablePromise: Promise<void> | undefined;\n private removeSpaTracker: (() => void) | undefined;\n private lastPagePath: string | undefined;\n private readonly options: ResolvedOptions;\n private readonly transport: Transport;\n private readonly lock: MultiTabLock;\n\n constructor(options: WtsClientOptions, transport?: Transport) {\n this.options = validateOptions(options);\n this.consent = this.options.consent;\n this.transport =\n transport ?? new HttpTransport(this.options.collectorOrigin, this.options.requestTimeoutMs);\n this.lock = new MultiTabLock(`flush-${this.options.sourceKey}`);\n this.attributionToken = captureAttributionToken();\n this.installLifecycleListeners();\n if (this.consent === \"granted\") void this.startEnable();\n if (this.consent === \"denied\") this.attributionToken = undefined;\n }\n\n async setConsent(consent: \"granted\" | \"denied\"): Promise<void> {\n if (this.destroyed) return;\n if (consent === \"denied\") {\n this.consent = \"denied\";\n this.cancelRetry();\n const storage = this.storage;\n if (storage) {\n await this.lock.run(async () => {\n await storage.clear();\n storage.close();\n });\n }\n try {\n await deleteStorage(this.options.sourceKey);\n } catch {\n safeWarn(this.options.debug, \"Stored SDK data could not be deleted because it is in use.\");\n }\n this.storage = undefined;\n this.identity = undefined;\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n this.attributionToken = undefined;\n this.bootstrapped = false;\n clearBrowserSession(this.options.sourceKey);\n this.removeSpaTracking();\n return;\n }\n const wasGranted = this.consent === \"granted\";\n this.consent = \"granted\";\n if (!wasGranted || !this.storage) await this.startEnable();\n }\n\n async page(name?: string): Promise<OperationResult> {\n let unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n await this.ensureReady();\n unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n const pathname = currentPathname();\n const referrer = referrerHost();\n const event: WebEvent = {\n ...this.eventBase(\"page_view\"),\n pathname,\n ...(name?.trim() ? { pageName: name.trim().slice(0, 120) } : {}),\n ...(referrer ? { referrerHost: referrer } : {}),\n properties: {},\n };\n await this.enqueue(event);\n this.lastPagePath = pathname;\n return { accepted: true, clientEventId: event.clientEventId };\n }\n\n async track(\n eventKey: string,\n properties: EventProperties = {},\n revenue?: Revenue,\n ): Promise<OperationResult> {\n let unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n await this.ensureReady();\n unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n validateEvent(eventKey, properties, revenue);\n const event: WebEvent = {\n ...this.eventBase(\"custom\"),\n eventKey,\n properties: { ...properties },\n ...(revenue ? { revenue: { ...revenue } } : {}),\n };\n await this.enqueue(event);\n return { accepted: true, clientEventId: event.clientEventId };\n }\n\n async identify(\n externalUserId: string,\n attributes: UserAttributes = {},\n ): Promise<OperationResult> {\n const unavailable = await this.prepareIdentityOperation();\n if (unavailable) return unavailable;\n validateExternalUserId(externalUserId);\n validateUserAttributes(attributes);\n return this.enqueueIdentityMutation({\n type: \"identify\",\n externalUserId,\n ...(Object.keys(attributes).length\n ? { attributes: normalizeUserAttributes(attributes) }\n : {}),\n });\n }\n\n async updateUser(operations: UserUpdateOperations): Promise<OperationResult> {\n const unavailable = await this.prepareIdentityOperation();\n if (unavailable) return unavailable;\n validateUserUpdate(operations);\n return this.enqueueIdentityMutation({\n type: \"update_user\",\n operations: structuredCloneSafe(operations),\n });\n }\n\n async setReportedAttribution(attribution: ReportedAttribution): Promise<OperationResult> {\n const unavailable = await this.prepareIdentityOperation();\n if (unavailable) return unavailable;\n validateReportedAttribution(attribution);\n return this.enqueueIdentityMutation({\n type: \"reported_attribution\",\n attribution: { ...attribution },\n });\n }\n\n async resetIdentity(): Promise<OperationResult> {\n const unavailable = await this.prepareIdentityOperation();\n if (unavailable) return unavailable;\n const result = await this.enqueueIdentityMutation({ type: \"reset_identity\" });\n if (!this.storage) return result;\n this.identity = { anonymousId: createUuid(), sessionId: createUuid() };\n this.bootstrapClientEventId = createUuid();\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n this.attributionToken = undefined;\n this.bootstrapped = false;\n this.lastPagePath = undefined;\n clearBrowserSession(this.options.sourceKey);\n saveBrowserSession(this.options.sourceKey, {\n sessionId: this.identity.sessionId,\n bootstrapClientEventId: this.bootstrapClientEventId,\n });\n await this.storage.saveIdentity(this.identity);\n await this.storage.saveAttributionContext();\n return result;\n }\n\n async flush(): Promise<FlushResult> {\n if (this.consent !== \"granted\" || this.destroyed || !this.storage) {\n return { sent: 0, pending: 0 };\n }\n const result = await this.lock.run(async () => this.flushExclusive(false));\n if (result) return result;\n const state = await this.storage.load();\n return { sent: 0, pending: state.queue.length + state.identityQueue.length };\n }\n\n async reset(): Promise<void> {\n this.cancelRetry();\n await this.storage?.clear();\n this.identity = undefined;\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n this.attributionToken = undefined;\n clearBrowserSession(this.options.sourceKey);\n this.bootstrapClientEventId = createUuid();\n this.bootstrapped = false;\n this.lastPagePath = undefined;\n if (this.consent === \"granted\" && !this.destroyed) await this.initializeIdentity();\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cancelRetry();\n this.removeSpaTracking();\n this.removeLifecycleListeners();\n const storage = this.storage;\n if (storage) void this.lock.run(async () => storage.close());\n }\n\n private async enable(): Promise<void> {\n if (this.destroyed || this.consent !== \"granted\") return;\n if (!this.storage) {\n try {\n this.storage = await createStorage(this.options.sourceKey);\n await this.storage.load();\n } catch {\n this.storage?.close();\n this.storage = new MemoryStorage();\n safeWarn(this.options.debug, \"IndexedDB unavailable; using a memory-only event queue.\");\n }\n }\n await this.initializeIdentity();\n try {\n await this.ensureBootstrapped();\n } catch (error) {\n this.handleRetryableError(error);\n }\n if (this.options.autoTrackPageViews && !this.removeSpaTracker) {\n this.removeSpaTracker = installSpaTracker(() => {\n void this.trackAutomaticPage();\n });\n await this.trackAutomaticPage();\n }\n void this.flush();\n }\n\n private startEnable(): Promise<void> {\n if (this.enablePromise) return this.enablePromise;\n const pending = this.enable();\n this.enablePromise = pending;\n void pending.finally(() => {\n if (this.enablePromise === pending) this.enablePromise = undefined;\n });\n return pending;\n }\n\n private async ensureReady(): Promise<void> {\n if (this.consent === \"granted\" && (!this.storage || !this.identity)) {\n await this.startEnable();\n }\n }\n\n private async initializeIdentity(): Promise<void> {\n if (!this.storage) return;\n const state = await this.storage.load();\n const browserSession = loadBrowserSession(this.options.sourceKey);\n this.identity = {\n anonymousId: state.identity?.anonymousId ?? createUuid(),\n sessionId: browserSession?.sessionId ?? createUuid(),\n };\n this.bootstrapClientEventId = browserSession?.bootstrapClientEventId ?? createUuid();\n saveBrowserSession(this.options.sourceKey, {\n sessionId: this.identity.sessionId,\n bootstrapClientEventId: this.bootstrapClientEventId,\n });\n const contextExpiry = state.attributionContextExpiresAt\n ? Date.parse(state.attributionContextExpiresAt)\n : Number.NaN;\n if (\n state.attributionContextId &&\n Number.isFinite(contextExpiry) &&\n contextExpiry > Date.now()\n ) {\n this.attributionContextId = state.attributionContextId;\n this.attributionContextExpiresAt = contextExpiry;\n } else if (state.attributionContextId || state.attributionContextExpiresAt) {\n await this.storage.saveAttributionContext();\n }\n if (\n !state.identity ||\n state.identity.anonymousId !== this.identity.anonymousId ||\n state.identity.sessionId !== this.identity.sessionId\n ) {\n await this.storage.saveIdentity(this.identity);\n }\n }\n\n private async ensureBootstrapped(): Promise<void> {\n if (this.bootstrapped || !this.identity || !this.storage) return;\n const result = await this.transport.bootstrap({\n sourceKey: this.options.sourceKey,\n identity: this.identity,\n clientEventId: this.bootstrapClientEventId,\n ...(this.attributionToken ? { attributionToken: this.attributionToken } : {}),\n });\n this.bootstrapped = true;\n this.attributionToken = undefined;\n if (result.attributionContextId) {\n this.attributionContextId = result.attributionContextId;\n const serverTime = Date.parse(result.serverTime);\n this.attributionContextExpiresAt =\n (Number.isFinite(serverTime) ? serverTime : Date.now()) + ATTRIBUTION_CONTEXT_TTL_MS;\n await this.storage.saveAttributionContext(\n result.attributionContextId,\n new Date(this.attributionContextExpiresAt).toISOString(),\n );\n }\n this.retryAttempt = 0;\n }\n\n private async enqueue(event: WebEvent): Promise<void> {\n if (!this.storage) return;\n await this.storage.enqueue(event);\n queueMicrotask(() => void this.flush());\n }\n\n private async flushExclusive(keepalive: boolean): Promise<FlushResult> {\n if (!this.storage) return { sent: 0, pending: 0 };\n if (this.retryTimer && !keepalive) {\n const state = await this.storage.load();\n return { sent: 0, pending: state.queue.length + state.identityQueue.length };\n }\n try {\n await this.ensureBootstrapped();\n const state = await this.storage.load();\n const identityBatch = takeIdentityBatch(state.identityQueue);\n if (identityBatch.length > 0) {\n try {\n const identityResponse = await this.transport.sendIdentity(\n this.options.sourceKey,\n identityBatch,\n );\n const permanentlyRejected = (identityResponse.rejected ?? [])\n .filter((item) => !item.retryable)\n .map((item) => item.clientMutationId);\n const hasRetryableRejection = (identityResponse.rejected ?? []).some(\n (item) => item.retryable,\n );\n await this.storage.removeIdentity(\n new Set([\n ...identityResponse.accepted,\n ...identityResponse.duplicates,\n ...permanentlyRejected,\n ]),\n );\n if (permanentlyRejected.length > 0) {\n safeWarn(\n this.options.debug,\n `Collector permanently rejected ${permanentlyRejected.length} identity mutation(s).`,\n );\n }\n if (hasRetryableRejection) {\n this.scheduleRetry();\n const pendingState = await this.storage.load();\n return {\n sent:\n identityResponse.accepted.length +\n identityResponse.duplicates.length +\n permanentlyRejected.length,\n pending: pendingState.queue.length + pendingState.identityQueue.length,\n };\n }\n } catch (error) {\n if (error instanceof TransportError && !error.retryable) {\n await this.storage.removeIdentity(\n new Set(identityBatch.map((mutation) => mutation.clientMutationId)),\n );\n safeWarn(\n this.options.debug,\n `Collector rejected an identity mutation (${error.code ?? error.status}).`,\n );\n } else {\n this.handleRetryableError(error);\n return {\n sent: 0,\n pending: state.queue.length + state.identityQueue.length,\n };\n }\n }\n }\n const refreshedState = await this.storage.load();\n const batch = takeBatch(refreshedState.queue, this.activeAttributionContextId());\n if (batch.length === 0) {\n return {\n sent: identityBatch.length,\n pending: refreshedState.queue.length + refreshedState.identityQueue.length,\n };\n }\n const response = await this.transport.send(this.options.sourceKey, batch, keepalive);\n const remove = new Set([...response.accepted, ...response.duplicates]);\n let hasRetryableRejection = false;\n for (const rejection of response.rejected) {\n if (rejection.retryable) hasRetryableRejection = true;\n else remove.add(rejection.clientEventId);\n }\n await this.storage.remove(remove);\n const pendingState = await this.storage.load();\n const pending = pendingState.queue.length + pendingState.identityQueue.length;\n if (hasRetryableRejection) this.scheduleRetry();\n else {\n this.retryAttempt = 0;\n if (pending > 0) queueMicrotask(() => void this.flush());\n }\n return { sent: remove.size + identityBatch.length, pending };\n } catch (error) {\n this.handleRetryableError(error);\n const state = await this.storage.load();\n return { sent: 0, pending: state.queue.length + state.identityQueue.length };\n }\n }\n\n private handleRetryableError(error: unknown): void {\n if (error instanceof TransportError && !error.retryable) {\n safeWarn(\n this.options.debug,\n `Collector rejected the request (${error.code ?? error.status}).`,\n );\n return;\n }\n this.scheduleRetry();\n }\n\n private scheduleRetry(): void {\n if (this.consent !== \"granted\" || this.destroyed || this.retryTimer) return;\n const base = Math.min(60_000, 1_000 * 2 ** Math.min(this.retryAttempt, 6));\n const jitter = Math.floor(Math.random() * Math.max(1, base * 0.25));\n this.retryAttempt += 1;\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined;\n void this.flush();\n }, base + jitter);\n }\n\n private async trackAutomaticPage(): Promise<void> {\n const pathname = currentPathname();\n if (pathname === this.lastPagePath) return;\n await this.page();\n }\n\n private eventBase(type: WebEvent[\"type\"]): Omit<WebEvent, \"properties\"> {\n if (!this.identity) throw new Error(\"Web SDK identity is unavailable.\");\n const attributionContextId = this.activeAttributionContextId();\n return {\n schemaVersion: 3,\n clientEventId: createUuid(),\n ...this.identity,\n type,\n occurredAt: new Date().toISOString(),\n metadata: { platform: \"web\", sdkVersion: SDK_VERSION, locale: locale() },\n ...(attributionContextId ? { attributionContextId } : {}),\n };\n }\n\n private async prepareIdentityOperation(): Promise<OperationResult | undefined> {\n let unavailable = this.unavailableResult();\n if (unavailable) return unavailable;\n await this.ensureReady();\n unavailable = this.unavailableResult();\n return unavailable;\n }\n\n private async enqueueIdentityMutation(\n value: Omit<\n IdentityMutation,\n \"schemaVersion\" | \"clientMutationId\" | \"occurredAt\" | \"identity\" | \"metadata\"\n >,\n ): Promise<OperationResult> {\n if (!this.storage || !this.identity) throw new Error(\"Web SDK identity is unavailable.\");\n const mutation: IdentityMutation = {\n schemaVersion: 1,\n clientMutationId: createUuid(),\n occurredAt: new Date().toISOString(),\n identity: { ...this.identity },\n metadata: { platform: \"web\", sdkVersion: SDK_VERSION, locale: locale() },\n ...value,\n };\n if (byteLength({ schemaVersion: 1, mutations: [mutation] }) > MAX_BATCH_BYTES) {\n throw new TypeError(\"Identity mutation cannot exceed 64 KiB.\");\n }\n await this.storage.enqueueIdentity(mutation);\n queueMicrotask(() => void this.flush());\n return { accepted: true, clientEventId: mutation.clientMutationId };\n }\n\n private unavailableResult(): OperationResult | undefined {\n if (this.destroyed) return { accepted: false, reason: \"destroyed\" };\n if (this.consent === \"pending\") return { accepted: false, reason: \"consent_pending\" };\n if (this.consent === \"denied\") return { accepted: false, reason: \"consent_denied\" };\n return undefined;\n }\n\n private activeAttributionContextId(): string | undefined {\n if (\n this.attributionContextId &&\n this.attributionContextExpiresAt &&\n this.attributionContextExpiresAt > Date.now()\n ) {\n return this.attributionContextId;\n }\n if (this.attributionContextId || this.attributionContextExpiresAt) {\n this.attributionContextId = undefined;\n this.attributionContextExpiresAt = undefined;\n void this.storage?.saveAttributionContext();\n }\n return undefined;\n }\n\n private installLifecycleListeners(): void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n window.addEventListener(\"pagehide\", this.onPageHide);\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n private removeLifecycleListeners(): void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n window.removeEventListener(\"pagehide\", this.onPageHide);\n document.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n private readonly onPageHide = () => {\n if (this.consent === \"granted\") void this.lock.run(() => this.flushExclusive(true));\n };\n\n private readonly onVisibilityChange = () => {\n if (document.visibilityState === \"hidden\" && this.consent === \"granted\") {\n void this.lock.run(() => this.flushExclusive(true));\n }\n };\n\n private removeSpaTracking(): void {\n this.removeSpaTracker?.();\n this.removeSpaTracker = undefined;\n }\n\n private cancelRetry(): void {\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n}\n\nfunction currentPathname(): string {\n return normalizePathname(typeof location === \"undefined\" ? \"/\" : location.pathname);\n}\n\nfunction captureAttributionToken(): string | undefined {\n if (typeof location === \"undefined\" || typeof history === \"undefined\") return undefined;\n const url = new URL(location.href);\n const token = url.searchParams.get(ATTRIBUTION_QUERY_KEY) ?? undefined;\n if (!token) return undefined;\n url.searchParams.delete(ATTRIBUTION_QUERY_KEY);\n history.replaceState(history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n return token;\n}\n\nfunction takeBatch(queue: WebEvent[], attributionContextId?: string): WebEvent[] {\n const batch: WebEvent[] = [];\n for (const queued of queue.slice(0, MAX_BATCH_EVENTS)) {\n const event = attributionContextId ? { ...queued, attributionContextId } : queued;\n if (byteLength({ schemaVersion: 3, events: [...batch, event] }) > MAX_BATCH_BYTES) break;\n batch.push(event);\n }\n return batch;\n}\n\nfunction takeIdentityBatch(queue: IdentityMutation[]): IdentityMutation[] {\n const batch: IdentityMutation[] = [];\n for (const mutation of queue.slice(0, MAX_BATCH_EVENTS)) {\n if (byteLength({ schemaVersion: 1, mutations: [...batch, mutation] }) > MAX_BATCH_BYTES) {\n if (batch.length === 0) batch.push(mutation);\n break;\n }\n batch.push(mutation);\n }\n return batch;\n}\n\nfunction structuredCloneSafe<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction normalizeUserAttributes(attributes: UserAttributes): UserAttributes {\n return Object.fromEntries(\n Object.entries(attributes).map(([key, value]) => [\n key,\n value instanceof Date ? value.toISOString() : value,\n ]),\n );\n}\n","import { WtsClientImpl } from \"./client\";\nimport type { WtsClient, WtsClientOptions } from \"./types\";\n\nexport type {\n ConsentState,\n EventProperties,\n FlushResult,\n OperationResult,\n Revenue,\n ReportedAttribution,\n Scalar,\n UserAttributes,\n UserAttributeValue,\n UserUpdateOperations,\n WtsClient,\n WtsClientOptions,\n} from \"./types\";\n\nexport function createWtsClient(options: WtsClientOptions): WtsClient {\n return new WtsClientImpl(options);\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,8 @@
1
1
  type ConsentState = "pending" | "granted" | "denied";
2
2
  type Scalar = string | number | boolean;
3
3
  type EventProperties = Record<string, Scalar>;
4
+ type UserAttributeValue = Scalar | string[] | Date;
5
+ type UserAttributes = Record<string, UserAttributeValue>;
4
6
  interface Revenue {
5
7
  amount: string;
6
8
  currency: string;
@@ -26,11 +28,27 @@ interface WtsClient {
26
28
  setConsent(consent: "granted" | "denied"): Promise<void>;
27
29
  page(name?: string): Promise<OperationResult>;
28
30
  track(eventKey: string, properties?: EventProperties, revenue?: Revenue): Promise<OperationResult>;
31
+ identify(externalUserId: string, attributes?: UserAttributes): Promise<OperationResult>;
32
+ updateUser(operations: UserUpdateOperations): Promise<OperationResult>;
33
+ setReportedAttribution(attribution: ReportedAttribution): Promise<OperationResult>;
34
+ resetIdentity(): Promise<OperationResult>;
29
35
  flush(): Promise<FlushResult>;
30
36
  reset(): Promise<void>;
31
37
  destroy(): void;
32
38
  }
39
+ interface UserUpdateOperations {
40
+ set?: UserAttributes;
41
+ setOnce?: UserAttributes;
42
+ unset?: string[];
43
+ increment?: Record<string, number>;
44
+ }
45
+ interface ReportedAttribution {
46
+ source: string;
47
+ medium?: string;
48
+ campaign?: string;
49
+ externalRef?: string;
50
+ }
33
51
 
34
52
  declare function createWtsClient(options: WtsClientOptions): WtsClient;
35
53
 
36
- export { type ConsentState, type EventProperties, type FlushResult, type OperationResult, type Revenue, type Scalar, type WtsClient, type WtsClientOptions, createWtsClient };
54
+ export { type ConsentState, type EventProperties, type FlushResult, type OperationResult, type ReportedAttribution, type Revenue, type Scalar, type UserAttributeValue, type UserAttributes, type UserUpdateOperations, type WtsClient, type WtsClientOptions, createWtsClient };