@faststats/web 0.3.0 → 0.3.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.
@@ -1 +1 @@
1
- import{l as e,r as t}from"./send-data-D6WdryL7.js";const n=`faststats_anon_id`;function r(){try{return globalThis.localStorage}catch{return}}function i(){let e=r();if(!e)return``;try{let t=e.getItem(n);if(t)return t}catch{return``}let i=t();try{e.setItem(n,i)}catch{return``}return i}function a(t){return t??e()?``:i()}function o(e){if(e)return``;try{let e=r();if(!e)return``;e.removeItem(n)}catch{return``}return i()}export{o as n,a as t};
1
+ import{l as e,r as t}from"./send-data-Cb4xlYF0.js";const n=`faststats_anon_id`;function r(){try{return globalThis.localStorage}catch{return}}function i(){let e=r();if(!e)return``;try{let t=e.getItem(n);if(t)return t}catch{return``}let i=t();try{e.setItem(n,i)}catch{return``}return i}function a(t){return t??e()?``:i()}function o(e){if(e)return``;try{let e=r();if(!e)return``;e.removeItem(n)}catch{return``}return i()}export{o as n,a as t};
@@ -73,11 +73,9 @@ declare class ReplayTracker {
73
73
  private getBatchSizeBytes;
74
74
  private dropOldestPendingBatch;
75
75
  private enqueueBatch;
76
- private encodeBatch;
77
76
  private flush;
78
77
  private scheduleRetry;
79
- private compress;
80
- private send;
78
+ private sendBatch;
81
79
  }
82
80
  //#endregion
83
81
  export { ReplayTrackerOptions as n, ReplayTracker as t };
@@ -0,0 +1 @@
1
+ const e=`faststats_session`;let t=!1,n=null;const r=new Set;function i(){try{return globalThis.localStorage}catch{return null}}function a(){try{return globalThis.sessionStorage}catch{return null}}function o(){return typeof crypto<`u`&&`randomUUID`in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}function s(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t)}function c(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t.id==`string`&&t.id&&Number.isFinite(t.start)&&t.start>0&&Number.isFinite(t.activity)&&t.activity>0)return t}catch{}return null}function l(){let t=i();if(!t)return n;let r=c(t.getItem(e));if(r)return r;let a=t.getItem(`faststats_session_id`),o=t.getItem(`faststats_session_activity`),s=o===null?NaN:Number(o);if(!a||!Number.isFinite(s))return n;let l=t.getItem(`faststats_session_start`),d=l===null?s:Number(l),f={id:a,start:Number.isFinite(d)?d:s,activity:s};return u(f),t.removeItem(`faststats_session_id`),t.removeItem(`faststats_session_activity`),t.removeItem(`faststats_session_start`),f}function u(t){let r=i();if(!r){n=t;return}try{r.setItem(e,JSON.stringify(t))}catch{n=t}}function d(){n=null;try{i()?.removeItem(e)}catch{}}function f(e,t){return t-e.activity>=18e5||t-e.start>=864e5}function p(e,t){for(let n of r)n(e,t)}function m(e,t){let r=Date.now();if(e)return n?t&&(n.activity=r):n={id:o(),start:r,activity:r},{session:n,rotated:!1,previous:null};let i=l();if(i&&!f(i,r))return t&&(i.activity=r,u(i)),{session:i,rotated:!1,previous:null};let a=i,s={id:o(),start:r,activity:r};return u(s),{session:s,rotated:a!==null,previous:a}}function h(e,t,n){if(t)return n;let r=`faststats_window_id_${e}`,i=a();if(!i)return n;try{let e=i.getItem(r);if(e)return e;let t=o();return i.setItem(r,t),t}catch{return n}}function g(e,t,n,r){let i=r??h(e,n,t.id);return{sessionId:t.id,windowId:i,sessionStart:t.start}}function _(e){t=e,e&&(n=null)}function v(){return t}function y(e,n){let r=n??t,{session:i}=m(r,!1);return h(e,r,i.id)}function b(e,n){let r=n??t,{session:i}=m(r,!1);return g(e,i,r)}function x(e){return m(e??t,!0).session.id}function S(e){return m(e??t,!1).session.start}function C(e,n){let r=n??t,{session:i,rotated:a,previous:o}=m(r,!0);if(!a||!o)return null;let s=h(e,r,i.id),c={prev:g(e,o,r,s),next:g(e,i,r,s)};return p(c.prev,c.next),c}function w(e){let r=t,i=b(e,r);if(d(),r){let e=Date.now();n={id:o(),start:e,activity:e}}else try{a()?.removeItem(`faststats_window_id_${e}`)}catch{}let s=b(e,r);return i.sessionId!==s.sessionId&&p(i,s),s}function T(e){return r.add(e),()=>r.delete(e)}function E(e){return typeof e!=`number`||!Number.isFinite(e)?100:Math.max(0,Math.min(100,e))}async function D(e){let{url:t,data:n,contentType:r=`application/json`,headers:i={},debug:a=!1,debugPrefix:o=`[Analytics]`,useBeacon:s=!0,keepalive:c=!0,signal:l}=e;if(l?.aborted)return!1;if(s&&typeof globalThis.navigator?.sendBeacon==`function`)try{let e=n instanceof Blob?n:typeof Blob<`u`?new Blob([n],{type:r}):n;if(globalThis.navigator.sendBeacon(t,e))return a&&console.log(`${o} Sent via beacon`),!0}catch{}if(typeof globalThis.fetch!=`function`)return a&&console.warn(`${o} Failed to send`),!1;try{let e=await fetch(t,{method:`POST`,body:n,headers:{"Content-Type":r,...i},keepalive:c,credentials:`omit`,signal:l}),s=e.ok;if(a){let t=s?`${o} Sent via fetch`:`${o} Failed: ${e.status}`;console[s?`log`:`warn`](t)}return s}catch{return a&&console.warn(`${o} Failed to send`),!1}}export{y as a,s as c,w as d,_ as f,x as i,v as l,D as n,b as o,C as p,o as r,S as s,E as t,T as u};
package/dist/error.js CHANGED
@@ -1,2 +1,2 @@
1
- import{n as e,r as t,t as n}from"./chunks/api-urls-nKmJnyjD.js";import{a as r,i,n as a}from"./chunks/send-data-D6WdryL7.js";import{t as o}from"./chunks/identifiers-wylBcW5K.js";const s=/(?:^|\()(chrome|moz|ms-browser|safari-web)-extension:\/\//;function c(e,t,n,r){return t instanceof Error?{error:e,message:t.message||r,handled:n,stack:t.stack?.split(`
2
- `).map(e=>e.trim()).filter(Boolean)}:{error:e,message:typeof t==`string`?t:r,handled:n}}function l({error:e,message:t,handled:n}){return`${e}\0${t??``}\0${n}`}function u(e,t){let n=t instanceof Error?t.stack??``:``;return s.test(`${e}\n${n}`)}var d=class{endpoint;queue=new Map;timer=null;started=!1;flushing=!1;constructor(e){this.options=e,this.endpoint=`${t(e.baseUrl)}${n.events}`}log(...e){this.options.debug&&console.log(`[ErrorTracker]`,...e)}start(){this.started||typeof window>`u`||(this.started=!0,window.addEventListener(`error`,this.onError),window.addEventListener(`unhandledrejection`,this.onRejection),this.timer=setInterval(()=>void this.flush(),this.options.flushInterval??5e3),this.log(`Started`))}stop(){!this.started||typeof window>`u`||(this.started=!1,window.removeEventListener(`error`,this.onError),window.removeEventListener(`unhandledrejection`,this.onRejection),this.timer&&clearInterval(this.timer),this.timer=null,this.flush(),this.log(`Stopped`))}onPageHidden(e=!1){e||this.flush()}captureError(e){this.enqueue(c(`Error`,e,!0,e.message))}onError=e=>{u(e.filename??``,e.error)||this.enqueue(c(`Error`,e.error,!1,e.message||`Unknown error`))};onRejection=e=>{u(``,e.reason)||this.enqueue(c(`UnhandledRejection`,e.reason,!1,`Unhandled promise rejection`))};enqueue(e){let t=l(e),n=this.queue.get(t);if(n){n.count++;return}this.queue.set(t,{...e,count:1}),this.log(`Captured:`,e),this.queue.size>=(this.options.maxQueueSize??50)&&this.flush()}async flush(){if(this.flushing||this.queue.size===0)return;this.flushing=!0;let t=this.queue;this.queue=new Map;let n=[...t.values()];this.log(`Flushing:`,n);try{let s=globalThis.__SOURCEMAPS_BUILD__?.buildId,c=o();if(!await a({url:this.endpoint,data:JSON.stringify({token:this.options.siteKey,...c?{userId:c}:{},sessionId:i(),windowId:r(this.options.siteKey),...typeof s==`string`&&s.trim()?{buildId:s}:{},sdkName:this.options.sdkName??`@faststats/web`,sdkVersion:this.options.sdkVersion??`0.3.0`,event:`error`,...e(),properties:{},errors:n}),debug:this.options.debug,debugPrefix:`[ErrorTracker]`}))for(let[e,n]of t){let t=this.queue.get(e);t?t.count+=n.count:this.queue.set(e,n)}}finally{this.flushing=!1}}};export{d as default};
1
+ import{n as e,r as t,t as n}from"./chunks/api-urls-nKmJnyjD.js";import{a as r,i,n as a}from"./chunks/send-data-Cb4xlYF0.js";import{t as o}from"./chunks/identifiers-DrjjHcKB.js";const s=/(?:^|\()(chrome|moz|ms-browser|safari-web)-extension:\/\//;function c(e,t,n,r){return t instanceof Error?{error:e,message:t.message||r,handled:n,stack:t.stack?.split(`
2
+ `).map(e=>e.trim()).filter(Boolean)}:{error:e,message:typeof t==`string`?t:r,handled:n}}function l({error:e,message:t,handled:n}){return`${e}\0${t??``}\0${n}`}function u(e,t){let n=t instanceof Error?t.stack??``:``;return s.test(`${e}\n${n}`)}var d=class{endpoint;queue=new Map;timer=null;started=!1;flushing=!1;constructor(e){this.options=e,this.endpoint=`${t(e.baseUrl)}${n.events}`}log(...e){this.options.debug&&console.log(`[ErrorTracker]`,...e)}start(){this.started||typeof window>`u`||(this.started=!0,window.addEventListener(`error`,this.onError),window.addEventListener(`unhandledrejection`,this.onRejection),this.timer=setInterval(()=>void this.flush(),this.options.flushInterval??5e3),this.log(`Started`))}stop(){!this.started||typeof window>`u`||(this.started=!1,window.removeEventListener(`error`,this.onError),window.removeEventListener(`unhandledrejection`,this.onRejection),this.timer&&clearInterval(this.timer),this.timer=null,this.flush(),this.log(`Stopped`))}onPageHidden(e=!1){e||this.flush()}captureError(e){this.enqueue(c(`Error`,e,!0,e.message))}onError=e=>{u(e.filename??``,e.error)||this.enqueue(c(`Error`,e.error,!1,e.message||`Unknown error`))};onRejection=e=>{u(``,e.reason)||this.enqueue(c(`UnhandledRejection`,e.reason,!1,`Unhandled promise rejection`))};enqueue(e){let t=l(e),n=this.queue.get(t);if(n){n.count++;return}this.queue.set(t,{...e,count:1}),this.log(`Captured:`,e),this.queue.size>=(this.options.maxQueueSize??50)&&this.flush()}async flush(){if(this.flushing||this.queue.size===0)return;this.flushing=!0;let t=this.queue;this.queue=new Map;let n=[...t.values()];this.log(`Flushing:`,n);try{let s=globalThis.__SOURCEMAPS_BUILD__?.buildId,c=o();if(!await a({url:this.endpoint,data:JSON.stringify({token:this.options.siteKey,...c?{userId:c}:{},sessionId:i(),windowId:r(this.options.siteKey),...typeof s==`string`&&s.trim()?{buildId:s}:{},sdkName:this.options.sdkName??`@faststats/web`,sdkVersion:this.options.sdkVersion??`0.3.1`,event:`error`,...e(),properties:{},errors:n}),debug:this.options.debug,debugPrefix:`[ErrorTracker]`}))for(let[e,n]of t){let t=this.queue.get(e);t?t.count+=n.count:this.queue.set(e,n)}}finally{this.flushing=!1}}};export{d as default};
@@ -1 +1 @@
1
- import{i as e,t}from"./chunks/api-urls-nKmJnyjD.js";async function n(n,r){if(r.projectToken&&r.projectId)throw Error(`provide either projectToken or projectId, not both`);let i=r.projectToken,a=r.projectId,o=r.identifier,s=r.externalId,c=r.sessionId;if(!i&&!a)throw Error(`feature flag check requires projectToken or projectId`);if(!o&&!s)throw Error(`feature flag check requires serverId or externalId`);let l={key:n,...a?{projectId:a}:{},...o?{identifier:o}:{},...s?{externalId:s}:{},...c?{sessionId:c}:{}};r.attributes&&Object.keys(r.attributes).length>0&&(l.attributes=r.attributes);let u={"Content-Type":`application/json`};i&&(u.Authorization=`Bearer ${i}`);let d=`${e(r.baseUrl)}${t.flags}`,f=await fetch(d,{method:`POST`,headers:u,body:JSON.stringify(l),credentials:`omit`,signal:r.signal});if(!f.ok){let e=``;try{let t=await f.json();typeof t.error==`string`&&t.error.length>0&&(e=` — ${t.error}`)}catch{}throw Error(`feature flag check failed: HTTP ${f.status}${e}`)}return await f.json()}export{n as fetchFeatureFlagEvaluation};
1
+ import{i as e,t}from"./chunks/api-urls-nKmJnyjD.js";async function n(n,r){if(r.projectToken&&r.projectId)throw Error(`provide either projectToken or projectId, not both`);let i=r.projectToken,a=r.projectId,o=r.identifier,s=r.externalId,c=r.sessionId;if(!i&&!a)throw Error(`feature flag check requires projectToken or projectId`);if(!o&&!s)throw Error(`feature flag check requires serverId or externalId`);let l={key:n,...a?{projectId:a}:{},...o?{identifier:o}:{},...s?{externalId:s}:{},...c?{sessionId:c}:{}},u=r.attributes??{};Object.keys(u).length>0&&(l.attributes=u);let d={"Content-Type":`application/json`};i&&(d.Authorization=`Bearer ${i}`);let f=`${e(r.baseUrl)}${t.flags}`,p=await fetch(f,{method:`POST`,headers:d,body:JSON.stringify(l),credentials:`omit`,signal:r.signal});if(!p.ok){let e=``;try{let t=await p.json();typeof t.error==`string`&&t.error.length>0&&(e=` — ${t.error}`)}catch{}throw Error(`feature flag check failed: HTTP ${p.status}${e}`)}return await p.json()}export{n as fetchFeatureFlagEvaluation};
package/dist/index.d.ts CHANGED
@@ -1,24 +1,8 @@
1
1
  import { FeatureFlagEvaluation } from "./feature-flags.js";
2
- import { n as ReplayTrackerOptions } from "./chunks/replay-Dpl1P6cw.js";
2
+ import { n as ReplayTrackerOptions } from "./chunks/replay-DR_T0Iz4.js";
3
3
 
4
4
  //#region src/analytics.d.ts
5
- interface SamplingOptions {
6
- percentage?: number;
7
- }
8
- interface WebVitalsConfig {
9
- enabled?: boolean;
10
- sampling?: SamplingOptions;
11
- attribution?: boolean;
12
- }
13
- interface SessionReplayConfig {
14
- enabled?: boolean;
15
- sampling?: SamplingOptions;
16
- }
17
5
  type ConsentMode = "pending" | "granted" | "denied";
18
- interface ConsentConfig {
19
- mode?: ConsentMode;
20
- cookielessWhilePending?: boolean;
21
- }
22
6
  interface IdentifyOptions {
23
7
  name?: string;
24
8
  phone?: string;
@@ -36,9 +20,23 @@ interface WebAnalyticsOptions {
36
20
  trackWebVitals?: boolean;
37
21
  trackReplay?: boolean;
38
22
  cookieless?: boolean;
39
- consent?: ConsentConfig;
40
- webVitals?: WebVitalsConfig;
41
- sessionReplays?: SessionReplayConfig;
23
+ consent?: {
24
+ mode?: ConsentMode;
25
+ cookielessWhilePending?: boolean;
26
+ };
27
+ webVitals?: {
28
+ enabled?: boolean;
29
+ sampling?: {
30
+ percentage?: number;
31
+ };
32
+ attribution?: boolean;
33
+ };
34
+ sessionReplays?: {
35
+ enabled?: boolean;
36
+ sampling?: {
37
+ percentage?: number;
38
+ };
39
+ };
42
40
  replayOptions?: Partial<ReplayTrackerOptions>;
43
41
  /** @internal */
44
42
  sdkName?: string;
@@ -65,13 +63,10 @@ declare class WebAnalytics {
65
63
  private pageKey;
66
64
  private navTimer;
67
65
  private heartbeatTimer;
68
- private scrollDepth;
69
- private pageEntryTime;
70
66
  private pagePath;
71
67
  private pageUrl;
72
68
  private pageHash;
73
69
  private hasLeftCurrentPage;
74
- private scrollUpdate;
75
70
  private consentMode;
76
71
  private readonly cookielessWhilePending;
77
72
  private readonly cleanupCallbacks;
@@ -84,7 +79,6 @@ declare class WebAnalytics {
84
79
  constructor(options: WebAnalyticsOptions);
85
80
  private log;
86
81
  private init;
87
- private isActive;
88
82
  private ensureStarted;
89
83
  private addListener;
90
84
  private patchHistory;
@@ -111,11 +105,9 @@ declare class WebAnalytics {
111
105
  private send;
112
106
  private enterPage;
113
107
  private leavePage;
114
- private trackScroll;
115
108
  private startHeartbeat;
116
109
  private stopHeartbeat;
117
110
  private navigate;
118
- private links;
119
111
  }
120
112
  //#endregion
121
113
  export { type ConsentMode, type FeatureFlagEvaluation, type IdentifyOptions, WebAnalytics, type WebAnalyticsOptions, getInstance, identify, isTrackingDisabled, logout, optIn, optOut, reportError, setConsentMode, trackEvent };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{i as e,n as t,r as n,t as r}from"./chunks/api-urls-nKmJnyjD.js";import{d as i,f as a,i as o,n as s,o as c,p as l,t as u}from"./chunks/send-data-D6WdryL7.js";import{n as d,t as f}from"./chunks/identifiers-wylBcW5K.js";const p=new Set([`browser`,`browser_version`,`device`,`os`,`os_version`,`referrer`,`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`,`title`,`page`,`url`]);function m(e){let t={},n={};for(let[r,i]of Object.entries(e))p.has(r)?t[r]=i:n[r]=i;return{dimensions:t,properties:n}}function h(e,t,n){if(!(e.sessionReplays?.enabled??e.trackReplay))return null;let r=e.replayOptions??{};return{siteKey:e.siteKey,baseUrl:t,debug:n,...r,samplingPercentage:u(r.samplingPercentage??e.sessionReplays?.sampling?.percentage)}}const g={instance:null,pendingConsentMode:void 0};function _(){return typeof window>`u`||E()?null:g.instance}function v(){return g.instance}function y(e,t){_()?.track(e,t??{})}function b(e,t,n){return _()?.identify(e,t,n??{})??Promise.resolve(!1)}function x(e=!0){_()?.logout(e)}function S(e){if(g.instance){g.instance.setConsentMode(e);return}g.pendingConsentMode=e}function C(){S(`granted`)}function w(){S(`denied`)}function T(e){_()?.reportError(e)}function E(){try{let e=globalThis.localStorage;if(!e)return!1;let t=e.getItem(`disable-faststats`);return t===`true`||t===`1`}catch{return!1}}function D(e){for(;e;){if(e instanceof HTMLAnchorElement&&e.href)return e;e=e.parentNode}return null}function O(){let e={};if(!location.search)return e;let t=new URLSearchParams(location.search);for(let n of[`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`]){let r=t.get(n);r&&(e[n]=r)}return e}var k=class{webEndpoint;baseUrl;featureFlagsBaseUrl;debug;started=!1;destroyed=!1;pageKey=``;navTimer=null;heartbeatTimer=null;scrollDepth=0;pageEntryTime=0;pagePath=``;pageUrl=``;pageHash=``;hasLeftCurrentPage=!1;scrollUpdate=null;consentMode;cookielessWhilePending;cleanupCallbacks=[];childTrackers=[];pendingReportedErrors=[];errorTracker=null;handleVisibilityChange=()=>{if(l(this.options.siteKey,this.isCookielessMode()),document.visibilityState===`hidden`){this.notifyChildren(`onPageHidden`),this.leavePage(),this.stopHeartbeat();return}this.enterPage(),this.startHeartbeat()};handlePageHide=e=>{this.notifyChildren(`onPageHidden`,e.persisted),e.persisted||this.leavePage()};handlePageShow=e=>{this.notifyChildren(`onPageShow`,e.persisted)};constructor(t){this.options=t,this.baseUrl=n(t.baseUrl),this.featureFlagsBaseUrl=e(t.featureFlagsBaseUrl),this.webEndpoint=`${this.baseUrl}${r.events}`,this.debug=t.debug??!1,this.consentMode=t.consent?.mode??`granted`,this.cookielessWhilePending=t.consent?.cookielessWhilePending??!0,g.pendingConsentMode!==void 0&&(this.consentMode=g.pendingConsentMode,g.pendingConsentMode=void 0),(t.autoTrack??!0)&&this.init()}log(e){this.debug&&console.log(`[Analytics] ${e}`)}init(){if(!(typeof window>`u`)){if(E()){this.log(`disabled`);return}setTimeout(()=>void this.start(),0)}}isActive(){return this.started&&!this.destroyed&&g.instance===this}ensureStarted(){return typeof window>`u`||this.destroyed||E()?!1:(this.started||this.start(),this.isActive())}addListener(e,t,n,r){e.addEventListener(t,n,r),this.cleanupCallbacks.push(()=>e.removeEventListener(t,n,r))}patchHistory(){for(let e of[`pushState`,`replaceState`]){let t=history[e].bind(history);history[e]=(e,n,r)=>{t(e,n,r),this.navigate()},this.cleanupCallbacks.push(()=>{history[e]=t})}}notifyChildren(e,t=!1){for(let n of this.childTrackers)n[e]?.(t)}async startChildTracker(e,t){try{let n=await t();return!this.isActive()||(await Promise.resolve(n.start()),!this.isActive())?(n.stop?.(),null):(this.childTrackers.push(n),this.log(`${e} loaded`),n)}catch(t){return this.log(`failed to initialize ${e} tracker: ${String(t)}`),null}}startOptionalTrackers(){let e=this.options,t=h(e,this.baseUrl,this.debug);t&&this.startChildTracker(`replay`,async()=>{let{default:e}=await import(`./replay.js`);return new e({...t,cookieless:this.isCookielessMode()})}),e.trackErrors&&this.startChildTracker(`error`,async()=>{let{default:t}=await import(`./error.js`);return new t({siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug,sdkName:e.sdkName,sdkVersion:e.sdkVersion})}).then(e=>{if(e){this.errorTracker=e;for(let t of this.pendingReportedErrors.splice(0))e.captureError(t)}}),(e.trackWebVitals??e.webVitals?.enabled)&&this.startChildTracker(`web-vitals`,async()=>{let{default:t}=await import(`./web-vitals.js`);return new t({siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug,samplingPercentage:u(e.webVitals?.sampling?.percentage),attribution:e.webVitals?.attribution??!1})})}async start(){if(!(this.started||this.destroyed||typeof window>`u`)){if(g.instance&&g.instance!==this){this.log(`already started by another instance`);return}if(E()){this.log(`disabled`);return}this.started=!0,g.instance=this,a(this.isCookielessMode()),o(),this.startOptionalTrackers(),this.enterPage(),this.pageview({trigger:`load`}),this.links(),this.trackScroll(),this.startHeartbeat(),this.addListener(document,`visibilitychange`,this.handleVisibilityChange),this.addListener(window,`pagehide`,this.handlePageHide),this.addListener(window,`pageshow`,this.handlePageShow),this.addListener(window,`popstate`,()=>this.navigate()),this.options.trackHash&&this.addListener(window,`hashchange`,()=>this.navigate()),this.patchHistory()}}destroy(){if(!this.destroyed){this.started&&typeof window<`u`&&this.leavePage(),this.pendingReportedErrors.length=0,this.navTimer&&clearTimeout(this.navTimer),this.stopHeartbeat();for(let e of this.cleanupCallbacks.splice(0))e();for(let e of this.childTrackers.splice(0))e.stop?.();this.errorTracker=null,g.instance===this&&(g.instance=null),this.started=!1,this.destroyed=!0}}pageview(e={}){if(!this.ensureStarted())return;let t=`${location.pathname}|${this.options.trackHash??!1?location.hash:``}`;t!==this.pageKey&&(this.pageKey=t,this.send(`pageview`,e))}track(e,t={}){this.ensureStarted()&&this.send(e,t)}identify(e,t,n={}){if(!this.ensureStarted()||this.isCookielessMode())return Promise.resolve(!1);let i=e.trim(),a=t.trim();return!i||!a?Promise.resolve(!1):s({url:`${this.baseUrl}${r.identify}`,data:JSON.stringify({token:this.options.siteKey,identifier:this.getAnonymousId(),externalId:i,email:a,name:n.name?.trim()||void 0,phone:n.phone?.trim()||void 0,avatarUrl:n.avatarUrl?.trim()||void 0,traits:n.traits??{}}),contentType:`text/plain`,debug:this.debug,debugPrefix:`[Analytics] identify`,useBeacon:!1})}logout(e=!0){this.ensureStarted()&&(e&&d(this.isCookielessMode()),i(this.options.siteKey))}setConsentMode(e){this.consentMode=e;let t=this.isCookielessMode();a(t);for(let e of this.childTrackers)e.setCookielessMode?.(t)}getConsentMode(){return this.consentMode}getAnonymousId(){return f(this.isCookielessMode())}getSessionId(){return o()}getWindowId(){return c(this.options.siteKey,this.isCookielessMode()).windowId}async checkFeatureFlag(e,t,n){if(typeof window>`u`||E())return{value:`false`};let r=n?.externalId?.trim(),i=this.getAnonymousId();if(!r&&!i)return{value:`false`};let{fetchFeatureFlagEvaluation:a}=await import(`./feature-flags.js`);return a(e,{baseUrl:this.featureFlagsBaseUrl,projectToken:this.options.siteKey,...i?{identifier:i}:{},...r?{externalId:r}:{},sessionId:this.getSessionId(),attributes:t,signal:n?.signal})}reportError(e){if(!(!this.ensureStarted()||!(this.options.trackErrors??!1))){if(this.errorTracker){this.errorTracker.captureError(e);return}this.pendingReportedErrors.length>=50&&this.pendingReportedErrors.shift(),this.pendingReportedErrors.push(e)}}isCookielessMode(){return this.options.cookieless||this.consentMode===`denied`?!0:this.consentMode===`pending`?this.cookielessWhilePending:!1}send(e,n={}){if(typeof window>`u`||this.destroyed||E())return;let r=this.isCookielessMode(),i=f(r),a=c(this.options.siteKey,r),{dimensions:o,properties:l}=m(n);this.log(e),s({url:this.webEndpoint,data:JSON.stringify({token:this.options.siteKey,...i?{userId:i}:{},sessionId:a.sessionId,event:e,...t(),...O(),...o,properties:l}),contentType:`text/plain`,debug:this.debug,debugPrefix:`[Analytics] ${e}`})}enterPage(){this.pageEntryTime=Date.now(),this.pagePath=location.pathname,this.pageUrl=location.href,this.pageHash=location.hash,this.scrollDepth=0,this.hasLeftCurrentPage=!1}leavePage(){if(this.destroyed||this.hasLeftCurrentPage)return;this.hasLeftCurrentPage=!0;let e=Date.now(),t=c(this.options.siteKey,this.isCookielessMode());this.send(`page_leave`,{page:this.pagePath,url:this.pageUrl,time_on_page:e-this.pageEntryTime,scroll_depth:this.scrollDepth,session_duration:e-t.sessionStart})}trackScroll(){let e=()=>{let e=document.documentElement,t=document.body,n=window.innerHeight,r=Math.max(e.scrollHeight,t.scrollHeight);if(r<=n){this.scrollDepth=100;return}let i=Math.min(100,Math.round(((window.scrollY||e.scrollTop)+n)/r*100));i>this.scrollDepth&&(this.scrollDepth=i)};this.scrollUpdate=e,e(),this.addListener(window,`scroll`,e,{passive:!0})}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{if(document.visibilityState===`hidden`){this.stopHeartbeat();return}l(this.options.siteKey,this.isCookielessMode())},300*1e3)}stopHeartbeat(){this.heartbeatTimer&&=(clearInterval(this.heartbeatTimer),null)}navigate(){!this.started||this.destroyed||(this.navTimer&&clearTimeout(this.navTimer),this.navTimer=setTimeout(()=>{this.navTimer=null;let e=location.pathname!==this.pagePath,t=(this.options.trackHash??!1)&&location.hash!==this.pageHash;if(!(!e&&!t)){for(let e of this.childTrackers)e.trackPageChange?.(location.href);this.leavePage(),this.enterPage(),this.scrollUpdate?.(),this.pageview({trigger:`navigation`})}},300))}links(){let e=e=>{let t=D(e.target);t&&t.host!==location.host&&this.track(`outbound_link`,{outbound_link:t.href})};this.addListener(document,`click`,e),this.addListener(document,`auxclick`,e)}};export{k as WebAnalytics,v as getInstance,b as identify,E as isTrackingDisabled,x as logout,C as optIn,w as optOut,T as reportError,S as setConsentMode,y as trackEvent};
1
+ import{i as e,n as t,r as n,t as r}from"./chunks/api-urls-nKmJnyjD.js";import{d as i,f as a,i as o,n as s,o as c,p as l,t as u}from"./chunks/send-data-Cb4xlYF0.js";import{n as d,t as f}from"./chunks/identifiers-DrjjHcKB.js";const p=new Set([`browser`,`browser_version`,`device`,`os`,`os_version`,`referrer`,`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`,`title`,`page`,`url`]);function m(e){let t={},n={};for(let[r,i]of Object.entries(e))(p.has(r)?t:n)[r]=i;return{dimensions:t,properties:n}}const h={instance:null,pendingConsentMode:void 0};function g(){return typeof window>`u`||T()?null:h.instance}function _(){return h.instance}function v(e,t){g()?.track(e,t??{})}function y(e,t,n){return g()?.identify(e,t,n??{})??Promise.resolve(!1)}function b(e=!0){g()?.logout(e)}function x(e){h.instance?h.instance.setConsentMode(e):h.pendingConsentMode=e}function S(){x(`granted`)}function C(){x(`denied`)}function w(e){g()?.reportError(e)}function T(){try{let e=globalThis.localStorage?.getItem(`disable-faststats`);return e===`true`||e===`1`}catch{return!1}}function E(e){for(;e;){if(e instanceof HTMLAnchorElement&&e.href)return e;e=e.parentNode}return null}function D(){let e={};if(!location.search)return e;let t=new URLSearchParams(location.search);for(let n of[`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`]){let r=t.get(n);r&&(e[n]=r)}return e}var O=class{webEndpoint;baseUrl;featureFlagsBaseUrl;debug;started=!1;destroyed=!1;pageKey=``;navTimer=null;heartbeatTimer=null;pagePath=``;pageUrl=``;pageHash=``;hasLeftCurrentPage=!1;consentMode;cookielessWhilePending;cleanupCallbacks=[];childTrackers=[];pendingReportedErrors=[];errorTracker=null;handleVisibilityChange=()=>{if(l(this.options.siteKey,this.isCookielessMode()),document.visibilityState===`hidden`){this.notifyChildren(`onPageHidden`),this.stopHeartbeat();return}this.startHeartbeat()};handlePageHide=e=>{this.notifyChildren(`onPageHidden`,e.persisted),e.persisted||this.leavePage()};handlePageShow=e=>{this.notifyChildren(`onPageShow`,e.persisted)};constructor(t){this.options=t,this.baseUrl=n(t.baseUrl),this.featureFlagsBaseUrl=e(t.featureFlagsBaseUrl),this.webEndpoint=`${this.baseUrl}${r.events}`,this.debug=t.debug??!1,this.consentMode=h.pendingConsentMode??t.consent?.mode??`granted`,h.pendingConsentMode=void 0,this.cookielessWhilePending=t.consent?.cookielessWhilePending??!0,(t.autoTrack??!0)&&this.init()}log(e){this.debug&&console.log(`[Analytics] ${e}`)}init(){if(typeof window>`u`||T()){T()&&this.log(`disabled`);return}setTimeout(()=>void this.start(),0)}ensureStarted(){return typeof window>`u`||this.destroyed||T()?!1:(this.started||this.start(),this.started&&!this.destroyed&&h.instance===this)}addListener(e,t,n,r){e.addEventListener(t,n,r),this.cleanupCallbacks.push(()=>e.removeEventListener(t,n,r))}patchHistory(){for(let e of[`pushState`,`replaceState`]){let t=history[e].bind(history);history[e]=(e,n,r)=>{t(e,n,r),this.navigate()},this.cleanupCallbacks.push(()=>{history[e]=t})}}notifyChildren(e,t=!1){for(let n of this.childTrackers)n[e]?.(t)}async startChildTracker(e,t){try{let n=await t();return!this.started||this.destroyed||h.instance!==this||(await Promise.resolve(n.start()),!this.started||this.destroyed||h.instance!==this)?(n.stop?.(),null):(this.childTrackers.push(n),this.log(`${e} loaded`),n)}catch(t){return this.log(`failed to initialize ${e} tracker: ${String(t)}`),null}}startOptionalTrackers(){let e=this.options;if(e.sessionReplays?.enabled??e.trackReplay){let t=e.replayOptions??{};this.startChildTracker(`replay`,async()=>{let{default:n}=await import(`./replay.js`);return new n({siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug,...t,samplingPercentage:u(t.samplingPercentage??e.sessionReplays?.sampling?.percentage),cookieless:this.isCookielessMode()})})}e.trackErrors&&this.startChildTracker(`error`,async()=>{let{default:t}=await import(`./error.js`);return new t({siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug,sdkName:e.sdkName,sdkVersion:e.sdkVersion})}).then(e=>{if(e){this.errorTracker=e;for(let t of this.pendingReportedErrors.splice(0))e.captureError(t)}}),(e.trackWebVitals??e.webVitals?.enabled)&&this.startChildTracker(`web-vitals`,async()=>{let{default:t}=await import(`./web-vitals.js`);return new t({siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug,samplingPercentage:u(e.webVitals?.sampling?.percentage),attribution:e.webVitals?.attribution??!1})})}async start(){if(this.started||this.destroyed||typeof window>`u`)return;if(h.instance&&h.instance!==this){this.log(`already started by another instance`);return}if(T()){this.log(`disabled`);return}this.started=!0,h.instance=this,a(this.isCookielessMode()),o(),this.startOptionalTrackers(),this.enterPage(),this.pageview({trigger:`load`}),this.startHeartbeat();let e=e=>{let t=E(e.target);t&&t.host!==location.host&&this.track(`outbound_link`,{outbound_link:t.href})};this.addListener(document,`click`,e),this.addListener(document,`auxclick`,e),this.addListener(document,`visibilitychange`,this.handleVisibilityChange),this.addListener(window,`pagehide`,this.handlePageHide),this.addListener(window,`pageshow`,this.handlePageShow),this.addListener(window,`popstate`,()=>this.navigate()),this.options.trackHash&&this.addListener(window,`hashchange`,()=>this.navigate()),this.patchHistory()}destroy(){if(!this.destroyed){this.started&&typeof window<`u`&&this.leavePage(),this.pendingReportedErrors.length=0,this.navTimer&&clearTimeout(this.navTimer),this.stopHeartbeat();for(let e of this.cleanupCallbacks.splice(0))e();for(let e of this.childTrackers.splice(0))e.stop?.();this.errorTracker=null,h.instance===this&&(h.instance=null),this.started=!1,this.destroyed=!0}}pageview(e={}){if(!this.ensureStarted())return;let t=`${location.pathname}|${this.options.trackHash??!1?location.hash:``}`;t!==this.pageKey&&(this.pageKey=t,this.send(`pageview`,e))}track(e,t={}){if(!this.ensureStarted())return;let n=e.trim();n&&this.send(n,t)}identify(e,t,n={}){if(!this.ensureStarted()||this.isCookielessMode())return Promise.resolve(!1);let i=e.trim(),a=t.trim();return!i||!a?Promise.resolve(!1):s({url:`${this.baseUrl}${r.identify}`,data:JSON.stringify({token:this.options.siteKey,identifier:this.getAnonymousId(),externalId:i,email:a,name:n.name?.trim()||void 0,phone:n.phone?.trim()||void 0,avatarUrl:n.avatarUrl?.trim()||void 0,traits:n.traits??{}}),contentType:`text/plain`,debug:this.debug,debugPrefix:`[Analytics] identify`,useBeacon:!1})}logout(e=!0){this.ensureStarted()&&(e&&d(this.isCookielessMode()),i(this.options.siteKey))}setConsentMode(e){this.consentMode=e;let t=this.isCookielessMode();a(t);for(let e of this.childTrackers)e.setCookielessMode?.(t)}getConsentMode(){return this.consentMode}getAnonymousId(){return f(this.isCookielessMode())}getSessionId(){return o()}getWindowId(){return c(this.options.siteKey,this.isCookielessMode()).windowId}async checkFeatureFlag(e,t,n){if(typeof window>`u`||T())return{value:`false`};let r=n?.externalId?.trim(),i=this.getAnonymousId();if(!r&&!i)return{value:`false`};let{fetchFeatureFlagEvaluation:a}=await import(`./feature-flags.js`);return a(e,{baseUrl:this.featureFlagsBaseUrl,projectToken:this.options.siteKey,...i?{identifier:i}:{},...r?{externalId:r}:{},sessionId:this.getSessionId(),attributes:t,signal:n?.signal})}reportError(e){if(!(!this.ensureStarted()||!(this.options.trackErrors??!1))){if(this.errorTracker){this.errorTracker.captureError(e);return}this.pendingReportedErrors.length>=50&&this.pendingReportedErrors.shift(),this.pendingReportedErrors.push(e)}}isCookielessMode(){return this.options.cookieless||this.consentMode===`denied`?!0:this.consentMode===`pending`?this.cookielessWhilePending:!1}send(e,n={}){if(typeof window>`u`||this.destroyed||T())return;let r=this.isCookielessMode(),i=f(r),a=c(this.options.siteKey,r),{dimensions:o,properties:l}=m(n);this.log(e),s({url:this.webEndpoint,data:JSON.stringify({token:this.options.siteKey,...i?{userId:i}:{},sessionId:a.sessionId,event:e,...t(),...D(),...o,properties:l}),contentType:`text/plain`,debug:this.debug,debugPrefix:`[Analytics] ${e}`})}enterPage(){this.pagePath=location.pathname,this.pageUrl=location.href,this.pageHash=location.hash,this.hasLeftCurrentPage=!1}leavePage(){if(this.destroyed||this.hasLeftCurrentPage)return;this.hasLeftCurrentPage=!0;let e=c(this.options.siteKey,this.isCookielessMode());this.send(`page_leave`,{page:this.pagePath,url:this.pageUrl,session_duration:Date.now()-e.sessionStart})}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{if(document.visibilityState===`hidden`){this.stopHeartbeat();return}l(this.options.siteKey,this.isCookielessMode())},300*1e3)}stopHeartbeat(){this.heartbeatTimer&&=(clearInterval(this.heartbeatTimer),null)}navigate(){!this.started||this.destroyed||(this.navTimer&&clearTimeout(this.navTimer),this.navTimer=setTimeout(()=>{this.navTimer=null;let e=this.options.trackHash??!1;if(!(location.pathname===this.pagePath&&(!e||location.hash===this.pageHash))){for(let e of this.childTrackers)e.trackPageChange?.(location.href);this.leavePage(),this.enterPage(),this.pageview({trigger:`navigation`})}},300))}};export{O as WebAnalytics,_ as getInstance,y as identify,T as isTrackingDisabled,b as logout,S as optIn,C as optOut,w as reportError,x as setConsentMode,v as trackEvent};
package/dist/replay.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as ReplayTrackerOptions, t as ReplayTracker } from "./chunks/replay-Dpl1P6cw.js";
1
+ import { n as ReplayTrackerOptions, t as ReplayTracker } from "./chunks/replay-DR_T0Iz4.js";
2
2
  export { ReplayTrackerOptions, ReplayTracker as default };
package/dist/replay.js CHANGED
@@ -1 +1 @@
1
- import{r as e,t}from"./chunks/api-urls-nKmJnyjD.js";import{c as n,n as r,o as i,p as a,r as o,s,t as c,u as l}from"./chunks/send-data-D6WdryL7.js";import{t as u}from"./chunks/identifiers-wylBcW5K.js";import{record as d}from"@rrweb/record";const f={mousemove:50,mouseInteraction:!0,scroll:150,media:800,input:`last`};function p(e){return`faststats_replay_sampled_${e}`}function m(e,t,r){let a=c(t);if(a>=100)return!0;if(a<=0)return!1;let o=i(e,r).sessionId,s=p(e),l=`${o}:${a}`;try{let e=sessionStorage;if(e){let t=e.getItem(s);if(t===l)return!0;if(t?.startsWith(`${o}:`))return!1}}catch{}let u=n(o)%100<a;try{sessionStorage?.setItem(s,u?l:`${o}:out`)}catch{}return u}var h=class{endpoint;compressionSupported=typeof window<`u`&&`CompressionStream`in window;sampled;events=[];pending=[];pendingSizeBytes=0;viewId=o();chunkStartedAt=0;started=!1;startTime=0;sequence=0;intervalId=null;flushTask=null;retryTask=null;minLengthFlushTask=null;stopRecording;sending=!1;unsubscribeRotation;cookieless;constructor(n){this.options=n,this.endpoint=`${e(n.baseUrl)}${t.replay}`,this.cookieless=n.cookieless??!1,this.sampled=m(n.siteKey,n.samplingPercentage??100,this.cookieless)}get flushInterval(){return this.options.flushInterval??1e4}get maxEvents(){return this.options.maxEvents??500}get maxPendingBatches(){return this.options.maxPendingBatches??30}get maxQueueSizeBytes(){return this.options.maxQueueSizeBytes??2097152}get minReplayLengthMs(){return this.options.minReplayLengthMs??3e3}log(...e){this.options.debug&&console.log(`[Replay]`,...e)}sessionContext(){return i(this.options.siteKey,this.cookieless)}setCookielessMode(e){this.cookieless!==e&&(this.cookieless=e,e&&(this.events.length=0,this.pending.length=0,this.pendingSizeBytes=0,this.flushTask&&clearTimeout(this.flushTask),this.retryTask&&clearTimeout(this.retryTask),this.minLengthFlushTask&&clearTimeout(this.minLengthFlushTask),this.flushTask=null,this.retryTask=null,this.minLengthFlushTask=null),this.startTime=s(this.cookieless),this.resetChunk())}resetChunk(){this.chunkStartedAt=Date.now()}start(){this.started||typeof window>`u`||!this.sampled||(this.started=!0,this.viewId=o(),this.startTime=s(this.cookieless),this.resetChunk(),this.unsubscribeRotation=l(e=>{this.onSessionRotated(e)}),this.beginRecording(),this.intervalId=setInterval(this.requestFlush,this.flushInterval),window.addEventListener(`beforeunload`,this.onUnload),this.log(`Recording started`))}trackPageChange(e){if(!this.started)return;let t=e??window.location.href;this.viewId=o(),this.resetChunk();let n={type:5,timestamp:Date.now(),data:{tag:`faststats:view`,payload:{href:t,viewId:this.viewId}}};this.onEvent(n,!1)}onPageHidden(e=!1){e||this.flush(!0,void 0,!0)}onPageShow(e=!1){!e||!this.started||this.pending.length>0&&this.flush(!1)}async beginRecording(){let e=this.options.recordConsole??!1?await import(`@rrweb/rrweb-plugin-console-record`):null;if(!this.started)return;let t=[];e&&t.push(e.getRecordConsolePlugin()),this.stopRecording=d({emit:this.onEvent,sampling:this.options.sampling??f,slimDOMOptions:this.options.slimDOMOptions??{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0},maskAllInputs:this.options.maskAllInputs??!0,maskInputOptions:this.options.maskInputOptions??{password:!0,email:!0,tel:!0},blockClass:this.options.blockClass,blockSelector:this.options.blockSelector,maskTextClass:this.options.maskTextClass,maskTextSelector:this.options.maskTextSelector,checkoutEveryNms:this.options.checkoutEveryNms??6e4,checkoutEveryNth:this.options.checkoutEveryNth,plugins:t})}stop(){if(this.started){if(this.started=!1,this.unsubscribeRotation?.(),this.unsubscribeRotation=void 0,this.stopRecording?.(),this.stopRecording=void 0,this.intervalId&&clearInterval(this.intervalId),this.flushTask&&clearTimeout(this.flushTask),this.retryTask&&clearTimeout(this.retryTask),this.minLengthFlushTask&&clearTimeout(this.minLengthFlushTask),this.intervalId=null,this.flushTask=null,this.retryTask=null,this.minLengthFlushTask=null,window.removeEventListener(`beforeunload`,this.onUnload),!this.hasReachedMinLength()){this.events.length=0,this.log(`Session too short (${Date.now()-this.startTime}ms), discarding events`);return}this.flush(!0,void 0,!0),this.log(`Recording stopped`)}}onSessionRotated(e){if(this.started){if(this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let t=this.createBatch(this.events.splice(0),e,!0);this.enqueueBatch(t)}this.pending.length>0&&queueMicrotask(()=>void this.flush(!1))}}onEvent=(e,t)=>{if(this.events.push(e),t||this.events.length>=this.maxEvents||e.type===2&&this.hasReachedMinLength()){this.requestFlush();return}this.scheduleMinLengthFlush()};onUnload=()=>{this.flush(!0,void 0,!0)};hasReachedMinLength(){return this.minReplayLengthMs<=0||Date.now()-this.startTime>=this.minReplayLengthMs}requestFlush=()=>{this.flushTask||this.sending||this.events.length===0||(this.minLengthFlushTask&&=(clearTimeout(this.minLengthFlushTask),null),this.flushTask=setTimeout(()=>{this.flushTask=null,this.flush(!1)},0))};scheduleMinLengthFlush(){if(this.minLengthFlushTask||this.events.length===0||this.hasReachedMinLength())return;let e=Math.max(0,this.minReplayLengthMs-(Date.now()-this.startTime)),t=Math.min(e,2147483647);this.minLengthFlushTask=setTimeout(()=>{this.minLengthFlushTask=null,this.requestFlush()},t)}createBatch(e,t,n){let r=u(this.cookieless),i=this.sequence++,a=Date.now(),o=this.chunkStartedAt,s={token:this.options.siteKey,sessionId:t.sessionId,windowId:t.windowId,viewId:this.viewId,sessionStart:t.sessionStart,chunkStartedAt:o,chunkEndedAt:a,...r?{identifier:r}:{},batchId:`${t.sessionId}-${i}-${o}`,sequence:i,timestamp:a,url:window.location.href,...n?{isFinal:!0}:{},events:e};return this.resetChunk(),s}getBatchSizeBytes(e){return new TextEncoder().encode(JSON.stringify(e)).byteLength}dropOldestPendingBatch(e){let t=this.pending.shift();t&&(this.pendingSizeBytes=Math.max(0,this.pendingSizeBytes-this.getBatchSizeBytes(t)),this.log(`${e}, dropping batch ${t.sequence}`))}enqueueBatch(e){let t=this.getBatchSizeBytes(e);if(t>this.maxQueueSizeBytes){this.log(`Replay batch ${e.sequence} is ${t}B, exceeding ${this.maxQueueSizeBytes}B queue limit; dropping`);return}for(;this.pending.length>0&&this.pendingSizeBytes+t>this.maxQueueSizeBytes;)this.dropOldestPendingBatch(`Pending queue size limit reached`);for(;this.pending.length>=this.maxPendingBatches;)this.dropOldestPendingBatch(`Pending batch limit reached`);this.pending.push(e),this.pendingSizeBytes+=t}async encodeBatch(e){let t=JSON.stringify(e);if(!(this.options.compress??!0)||!this.compressionSupported)return{data:t,isCompressed:!1};try{let e=await this.compress(t);return this.log(`Compressed ${t.length}B -> ${e.byteLength}B (${Math.round(e.byteLength/t.length*100)}%)`),{data:e,isCompressed:!0}}catch{return this.log(`Compression failed, using uncompressed`),{data:t,isCompressed:!1}}}async flush(e,t,n){if(this.sending)return;let r=t?null:a(this.options.siteKey,this.cookieless);if(r&&this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let e=this.createBatch(this.events.splice(0),r.prev,!0);this.enqueueBatch(e)}let i=t??this.sessionContext();if(this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let e=this.createBatch(this.events.splice(0),i,n);this.enqueueBatch(e)}if(this.pending.length!==0){this.sending=!0;try{for(;this.pending.length>0;){let t=this.pending[0];if(!t)break;let n=await this.encodeBatch(t);if(!await this.send(n.data,n.isCompressed,e)){this.log(`Failed to send replay batch ${t.sequence}, retrying`),this.scheduleRetry();break}this.dropOldestPendingBatch(`Sent replay batch`),e=!1}}finally{this.sending=!1}}}scheduleRetry(){this.retryTask||=setTimeout(()=>{this.retryTask=null,this.flush(!1)},1e3)}async compress(e){let t=new Blob([e]).stream().pipeThrough(new CompressionStream(`gzip`)),n=await new Response(t).arrayBuffer();return new Uint8Array(n)}send(e,t,n){return r({url:t?`${this.endpoint}?encoding=gzip`:this.endpoint,data:e,contentType:t?`application/octet-stream`:`application/json`,debug:!1,useBeacon:n,keepalive:n})??Promise.resolve(!1)}};export{h as default};
1
+ import{r as e,t}from"./chunks/api-urls-nKmJnyjD.js";import{c as n,n as r,o as i,p as a,r as o,s,t as c,u as l}from"./chunks/send-data-Cb4xlYF0.js";import{t as u}from"./chunks/identifiers-DrjjHcKB.js";import{record as d}from"@rrweb/record";const f={mousemove:50,mouseInteraction:!0,scroll:150,media:800,input:`last`};function p(e){return`faststats_replay_sampled_${e}`}function m(e,t,r){let a=c(t);if(a>=100)return!0;if(a<=0)return!1;let o=i(e,r).sessionId,s=p(e),l=`${o}:${a}`;try{let e=sessionStorage;if(e){let t=e.getItem(s);if(t===l)return!0;if(t?.startsWith(`${o}:`))return!1}}catch{}let u=n(o)%100<a;try{sessionStorage?.setItem(s,u?l:`${o}:out`)}catch{}return u}var h=class{endpoint;compressionSupported=typeof window<`u`&&`CompressionStream`in window;sampled;events=[];pending=[];pendingSizeBytes=0;viewId=o();chunkStartedAt=0;started=!1;startTime=0;sequence=0;intervalId=null;flushTask=null;retryTask=null;minLengthFlushTask=null;stopRecording;sending=!1;unsubscribeRotation;cookieless;constructor(n){this.options=n,this.endpoint=`${e(n.baseUrl)}${t.replay}`,this.cookieless=n.cookieless??!1,this.sampled=m(n.siteKey,n.samplingPercentage??100,this.cookieless)}get flushInterval(){return this.options.flushInterval??1e4}get maxEvents(){return this.options.maxEvents??500}get maxPendingBatches(){return this.options.maxPendingBatches??30}get maxQueueSizeBytes(){return this.options.maxQueueSizeBytes??2097152}get minReplayLengthMs(){return this.options.minReplayLengthMs??3e3}log(...e){this.options.debug&&console.log(`[Replay]`,...e)}sessionContext(){return i(this.options.siteKey,this.cookieless)}setCookielessMode(e){this.cookieless!==e&&(this.cookieless=e,e&&(this.events.length=0,this.pending.length=0,this.pendingSizeBytes=0,this.flushTask&&clearTimeout(this.flushTask),this.retryTask&&clearTimeout(this.retryTask),this.minLengthFlushTask&&clearTimeout(this.minLengthFlushTask),this.flushTask=null,this.retryTask=null,this.minLengthFlushTask=null),this.startTime=s(this.cookieless),this.resetChunk())}resetChunk(){this.chunkStartedAt=Date.now()}start(){this.started||typeof window>`u`||!this.sampled||(this.started=!0,this.viewId=o(),this.startTime=s(this.cookieless),this.resetChunk(),this.unsubscribeRotation=l(e=>{this.onSessionRotated(e)}),this.beginRecording(),this.intervalId=setInterval(this.requestFlush,this.flushInterval),window.addEventListener(`beforeunload`,this.onUnload),this.log(`Recording started`))}trackPageChange(e){if(!this.started)return;let t=e??window.location.href;this.viewId=o(),this.resetChunk();let n={type:5,timestamp:Date.now(),data:{tag:`faststats:view`,payload:{href:t,viewId:this.viewId}}};this.onEvent(n,!1)}onPageHidden(e=!1){e||this.flush(!0,void 0,!0)}onPageShow(e=!1){!e||!this.started||this.pending.length>0&&this.flush(!1)}async beginRecording(){let e=this.options.recordConsole??!1?await import(`@rrweb/rrweb-plugin-console-record`):null;if(!this.started)return;let t=[];e&&t.push(e.getRecordConsolePlugin()),this.stopRecording=d({emit:this.onEvent,sampling:this.options.sampling??f,slimDOMOptions:this.options.slimDOMOptions??{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0},maskAllInputs:this.options.maskAllInputs??!0,maskInputOptions:this.options.maskInputOptions??{password:!0,email:!0,tel:!0},blockClass:this.options.blockClass,blockSelector:this.options.blockSelector,maskTextClass:this.options.maskTextClass,maskTextSelector:this.options.maskTextSelector,checkoutEveryNms:this.options.checkoutEveryNms??6e4,checkoutEveryNth:this.options.checkoutEveryNth,plugins:t})}stop(){if(this.started){if(this.started=!1,this.unsubscribeRotation?.(),this.unsubscribeRotation=void 0,this.stopRecording?.(),this.stopRecording=void 0,this.intervalId&&clearInterval(this.intervalId),this.flushTask&&clearTimeout(this.flushTask),this.retryTask&&clearTimeout(this.retryTask),this.minLengthFlushTask&&clearTimeout(this.minLengthFlushTask),this.intervalId=null,this.flushTask=null,this.retryTask=null,this.minLengthFlushTask=null,window.removeEventListener(`beforeunload`,this.onUnload),!this.hasReachedMinLength()){this.events.length=0,this.log(`Session too short (${Date.now()-this.startTime}ms), discarding events`);return}this.flush(!0,void 0,!0),this.log(`Recording stopped`)}}onSessionRotated(e){if(this.started){if(this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let t=this.createBatch(this.events.splice(0),e,!0);this.enqueueBatch(t)}this.pending.length>0&&queueMicrotask(()=>void this.flush(!1))}}onEvent=(e,t)=>{if(this.events.push(e),t||this.events.length>=this.maxEvents||e.type===2&&this.hasReachedMinLength()){this.requestFlush();return}this.scheduleMinLengthFlush()};onUnload=()=>{this.flush(!0,void 0,!0)};hasReachedMinLength(){return this.minReplayLengthMs<=0||Date.now()-this.startTime>=this.minReplayLengthMs}requestFlush=()=>{this.flushTask||this.sending||this.events.length===0||(this.minLengthFlushTask&&=(clearTimeout(this.minLengthFlushTask),null),this.flushTask=setTimeout(()=>{this.flushTask=null,this.flush(!1)},0))};scheduleMinLengthFlush(){if(this.minLengthFlushTask||this.events.length===0||this.hasReachedMinLength())return;let e=Math.max(0,this.minReplayLengthMs-(Date.now()-this.startTime)),t=Math.min(e,2147483647);this.minLengthFlushTask=setTimeout(()=>{this.minLengthFlushTask=null,this.requestFlush()},t)}createBatch(e,t,n){let r=u(this.cookieless),i=this.sequence++,a=Date.now(),o=this.chunkStartedAt,s={token:this.options.siteKey,sessionId:t.sessionId,windowId:t.windowId,viewId:this.viewId,sessionStart:t.sessionStart,chunkStartedAt:o,chunkEndedAt:a,...r?{identifier:r}:{},batchId:`${t.sessionId}-${i}-${o}`,sequence:i,timestamp:a,url:window.location.href,...n?{isFinal:!0}:{},events:e};return this.resetChunk(),s}getBatchSizeBytes(e){return new TextEncoder().encode(JSON.stringify(e)).byteLength}dropOldestPendingBatch(e){let t=this.pending.shift();t&&(this.pendingSizeBytes=Math.max(0,this.pendingSizeBytes-this.getBatchSizeBytes(t)),this.log(`${e}, dropping batch ${t.sequence}`))}enqueueBatch(e){let t=this.getBatchSizeBytes(e);if(t>this.maxQueueSizeBytes){this.log(`Replay batch ${e.sequence} is ${t}B, exceeding ${this.maxQueueSizeBytes}B queue limit; dropping`);return}for(;this.pending.length>0&&this.pendingSizeBytes+t>this.maxQueueSizeBytes;)this.dropOldestPendingBatch(`Pending queue size limit reached`);for(;this.pending.length>=this.maxPendingBatches;)this.dropOldestPendingBatch(`Pending batch limit reached`);this.pending.push(e),this.pendingSizeBytes+=t}async flush(e,t,n){if(this.sending)return;let r=t?null:a(this.options.siteKey,this.cookieless);if(r&&this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let e=this.createBatch(this.events.splice(0),r.prev,!0);this.enqueueBatch(e)}let i=t??this.sessionContext();if(this.events.length>0)if(!this.hasReachedMinLength())this.scheduleMinLengthFlush();else{let e=this.createBatch(this.events.splice(0),i,n);this.enqueueBatch(e)}if(this.pending.length!==0){this.sending=!0;try{for(;this.pending.length>0;){let t=this.pending[0];if(!t)break;if(!await this.sendBatch(t,e)){this.log(`Failed to send replay batch ${t.sequence}, retrying`),this.scheduleRetry();break}this.dropOldestPendingBatch(`Sent replay batch`),e=!1}}finally{this.sending=!1}}}scheduleRetry(){this.retryTask||=setTimeout(()=>{this.retryTask=null,this.flush(!1)},1e3)}async sendBatch(e,t){let n=JSON.stringify(e),i={debug:!1,useBeacon:t,keepalive:t};if((this.options.compress??!0)&&this.compressionSupported)try{let e=new Blob([n]).stream().pipeThrough(new CompressionStream(`gzip`)),t=new Uint8Array(await new Response(e).arrayBuffer());return this.log(`Compressed ${n.length}B -> ${t.byteLength}B (${Math.round(t.byteLength/n.length*100)}%)`),r({url:`${this.endpoint}?encoding=gzip`,data:t,contentType:`application/octet-stream`,...i})??Promise.resolve(!1)}catch{this.log(`Compression failed, using uncompressed`)}return r({url:this.endpoint,data:n,contentType:`application/json`,...i})??Promise.resolve(!1)}};export{h as default};
@@ -10,7 +10,7 @@ declare class WebVitalsTracker {
10
10
  private readonly options;
11
11
  private readonly endpoint;
12
12
  private readonly sampled;
13
- private readonly metrics;
13
+ private metrics;
14
14
  private started;
15
15
  private flushing;
16
16
  private url;
@@ -1 +1 @@
1
- import{r as e,t}from"./chunks/api-urls-nKmJnyjD.js";import{c as n,i as r,n as i,t as a}from"./chunks/send-data-D6WdryL7.js";function o(e){let t=a(e);return t>=100?!0:t<=0?!1:n(r())%100<t}var s=class{endpoint;sampled;metrics=new Map;started=!1;flushing=!1;url=``;constructor(n){this.options=n,this.endpoint=`${e(n.baseUrl)}${t.vitals}`,this.sampled=o(n.samplingPercentage)}async start(){if(this.started||typeof window>`u`)return;this.started=!0,this.url=window.location.href;let e=this.options.attribution?await import(`web-vitals/attribution`):await import(`web-vitals`);if(!this.started)return;let t={reportAllChanges:!0};e.onCLS(this.onMetric,t),e.onINP(this.onMetric,t),e.onLCP(this.onMetric,t),e.onFCP(this.onMetric),e.onTTFB(this.onMetric)}stop(){this.started&&(this.started=!1,this.flush())}onPageHidden(e=!1){e||this.flush()}trackPageChange(e){if(!this.started)return;let t=e??window.location.href;t!==this.url&&(this.flush(),this.url=t)}onMetric=e=>{if(!this.started||!this.sampled)return;let t=e.name;this.metrics.set(t,{metric:t,value:e.value,attributes:{id:e.id,rating:e.rating,delta:e.delta,navigationType:e.navigationType,...e.attribution??{}}})};flush(){if(!this.metrics.size||this.flushing)return;let e=[...this.metrics.values()],t=new Set(e.map(e=>e.metric));this.flushing=!0;let n=JSON.stringify({token:this.options.siteKey,sessionId:r(),vitals:e,metadata:{url:this.url}});i({url:this.endpoint,data:n,debug:this.options.debug,debugPrefix:`[WebVitals]`}).then(e=>{if(e)for(let e of t)this.metrics.delete(e)}).finally(()=>{this.flushing=!1})}};export{s as default};
1
+ import{r as e,t}from"./chunks/api-urls-nKmJnyjD.js";import{c as n,i as r,n as i,t as a}from"./chunks/send-data-Cb4xlYF0.js";var o=class{endpoint;sampled;metrics=new Map;started=!1;flushing=!1;url=``;constructor(i){this.options=i,this.endpoint=`${e(i.baseUrl)}${t.vitals}`;let o=a(i.samplingPercentage);this.sampled=o>=100||o>0&&n(r())%100<o}async start(){if(this.started||typeof window>`u`)return;this.started=!0,this.url=window.location.href;let e=await(this.options.attribution?import(`web-vitals/attribution`):import(`web-vitals`));if(!this.started)return;let t={reportAllChanges:!0};e.onCLS(this.onMetric,t),e.onINP(this.onMetric,t),e.onLCP(this.onMetric,t),e.onFCP(this.onMetric),e.onTTFB(this.onMetric)}stop(){this.started&&(this.started=!1,this.flush())}onPageHidden(e=!1){e||this.flush()}trackPageChange(e){if(!this.started)return;let t=e??window.location.href;t!==this.url&&(this.flush(),this.url=t)}onMetric=e=>{if(!this.started||!this.sampled)return;let t=e.name,{id:n,rating:r,delta:i,navigationType:a}=e,o=`attribution`in e&&e.attribution?e.attribution:void 0;this.metrics.set(t,{metric:t,value:e.value,attributes:{id:n,rating:r,delta:i,navigationType:a,...o}})};flush(){if(!this.metrics.size||this.flushing)return;this.flushing=!0;let e=this.metrics;this.metrics=new Map,i({url:this.endpoint,data:JSON.stringify({token:this.options.siteKey,sessionId:r(),vitals:[...e.values()],metadata:{url:this.url}}),debug:this.options.debug,debugPrefix:`[WebVitals]`}).then(t=>{if(!t)for(let[t,n]of e)this.metrics.has(t)||this.metrics.set(t,n);this.flushing=!1})}};export{o as default};
package/package.json CHANGED
@@ -42,7 +42,7 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "version": "0.3.0",
45
+ "version": "0.3.1",
46
46
  "scripts": {
47
47
  "build": "tsdown && bun run check-size",
48
48
  "dev": "bun run build",
@@ -1 +0,0 @@
1
- const e=`faststats_session`;let t=!1,n=null;const r=new Set;function i(){try{return globalThis.localStorage}catch{return null}}function a(){try{return globalThis.sessionStorage}catch{return null}}function o(){return typeof crypto<`u`&&`randomUUID`in crypto?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}function s(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return Math.abs(t)}function c(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t.id==`string`&&Number.isFinite(t.start)&&Number.isFinite(t.activity))return t}catch{}return null}function l(){let t=i();if(!t)return n;let r=c(t.getItem(e));if(r)return r;let a=t.getItem(`faststats_session_id`),o=t.getItem(`faststats_session_activity`),s=o===null?NaN:Number(o);if(!a||!Number.isFinite(s))return n;let l=t.getItem(`faststats_session_start`),d=l===null?s:Number(l),f={id:a,start:Number.isFinite(d)?d:s,activity:s};return u(f),t.removeItem(`faststats_session_id`),t.removeItem(`faststats_session_activity`),t.removeItem(`faststats_session_start`),f}function u(t){let r=i();if(!r){n=t;return}try{r.setItem(e,JSON.stringify(t))}catch{n=t}}function d(){n=null;try{i()?.removeItem(e)}catch{}}function f(e,t){return t-e.activity>=18e5||t-e.start>=864e5}function p(e,t){for(let n of r)n(e,t)}function m(e,t){let r=Date.now();if(e)return n?t&&(n.activity=r):n={id:o(),start:r,activity:r},{session:n,rotated:!1,previous:null};let i=l();if(i&&!f(i,r))return t&&(i.activity=r,u(i)),{session:i,rotated:!1,previous:null};let a=i,s={id:o(),start:r,activity:r};return u(s),{session:s,rotated:a!==null,previous:a}}function h(e,t,n){if(t)return n;let r=`faststats_window_id_${e}`,i=a();if(!i)return n;try{let e=i.getItem(r);if(e)return e;let t=o();return i.setItem(r,t),t}catch{return n}}function g(e,t,n,r){let i=r??h(e,n,t.id);return{sessionId:t.id,windowId:i,sessionStart:t.start}}function _(e){t=e,e&&(n=null)}function v(){return t}function y(e,n){let r=n??t,{session:i}=m(r,!1);return h(e,r,i.id)}function b(e,n){let r=n??t,{session:i}=m(r,!1);return g(e,i,r)}function x(e){return m(e??t,!0).session.id}function S(e){return m(e??t,!1).session.start}function C(e,n){let r=n??t,{session:i,rotated:a,previous:o}=m(r,!0);if(!a||!o)return null;let s=h(e,r,i.id),c={prev:g(e,o,r,s),next:g(e,i,r,s)};return p(c.prev,c.next),c}function w(e){let r=t,i=b(e,r);if(d(),r){let e=Date.now();n={id:o(),start:e,activity:e}}else try{a()?.removeItem(`faststats_window_id_${e}`)}catch{}let s=b(e,r);return i.sessionId!==s.sessionId&&p(i,s),s}function T(e){return r.add(e),()=>r.delete(e)}function E(e){return typeof e!=`number`||!Number.isFinite(e)?100:Math.max(0,Math.min(100,e))}async function D(e){let{url:t,data:n,contentType:r=`application/json`,headers:i={},debug:a=!1,debugPrefix:o=`[Analytics]`,useBeacon:s=!0,keepalive:c=!0,signal:l}=e;if(l?.aborted)return!1;if(s&&typeof globalThis.navigator?.sendBeacon==`function`)try{let e=n instanceof Blob?n:typeof Blob<`u`?new Blob([n],{type:r}):n;if(globalThis.navigator.sendBeacon(t,e))return a&&console.log(`${o} Sent via beacon`),!0}catch{}if(typeof globalThis.fetch!=`function`)return a&&console.warn(`${o} Failed to send`),!1;try{let e=await fetch(t,{method:`POST`,body:n,headers:{"Content-Type":r,...i},keepalive:c,credentials:`omit`,signal:l}),s=e.ok;if(a){let t=s?`${o} Sent via fetch`:`${o} Failed: ${e.status}`;console[s?`log`:`warn`](t)}return s}catch{return a&&console.warn(`${o} Failed to send`),!1}}export{y as a,s as c,w as d,_ as f,x as i,v as l,D as n,b as o,C as p,o as r,S as s,E as t,T as u};