@faststats/web 0.3.1 → 0.4.0

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.
@@ -0,0 +1 @@
1
+ function e(e){return e.replace(/\/+$/,``)}function t(t,n){return t===void 0||t===``?n:e(t)||n}function n(e){return t(e,`https://metrics.faststats.dev`)}function r(e){return t(e,`https://flags.faststats.dev`)}const i={events:`/v1/web`,identify:`/v1/identify`,replay:`/v1/replay`,vitals:`/v1/vitals`,flags:`/v1/check`},a=[`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`];function o(){let e={page:location.pathname,url:location.href,referrer:document.referrer||null,title:document.title||``};if(!location.search)return e;let t=new URLSearchParams(location.search);for(let n of a){let r=t.get(n);r&&(e[n]=r)}return e}export{r as i,o as n,n as r,i as t};
@@ -1 +1 @@
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};
1
+ import{o as e,r as t}from"./send-data-BXrEi1iz.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};
@@ -30,6 +30,11 @@ declare class ReplayTracker {
30
30
  private readonly options;
31
31
  private readonly endpoint;
32
32
  private readonly compressionSupported;
33
+ private readonly flushInterval;
34
+ private readonly maxEvents;
35
+ private readonly maxPendingBatches;
36
+ private readonly maxQueueSizeBytes;
37
+ private readonly minReplayLengthMs;
33
38
  private readonly sampled;
34
39
  private readonly events;
35
40
  private readonly pending;
@@ -37,6 +42,7 @@ declare class ReplayTracker {
37
42
  private viewId;
38
43
  private chunkStartedAt;
39
44
  private started;
45
+ private startGeneration;
40
46
  private startTime;
41
47
  private sequence;
42
48
  private intervalId;
@@ -45,18 +51,16 @@ declare class ReplayTracker {
45
51
  private minLengthFlushTask;
46
52
  private stopRecording?;
47
53
  private sending;
54
+ private flushQueued;
55
+ private flushQueuedLowLatency;
48
56
  private unsubscribeRotation?;
49
57
  private cookieless;
50
58
  constructor(options: ReplayTrackerOptions);
51
- private get flushInterval();
52
- private get maxEvents();
53
- private get maxPendingBatches();
54
- private get maxQueueSizeBytes();
55
- private get minReplayLengthMs();
56
59
  private log;
57
60
  private sessionContext;
61
+ private clearFlushTimers;
62
+ private clearQueues;
58
63
  setCookielessMode(cookieless: boolean): void;
59
- private resetChunk;
60
64
  start(): void;
61
65
  trackPageChange(url?: string): void;
62
66
  onPageHidden(persisted?: boolean): void;
@@ -69,9 +73,10 @@ declare class ReplayTracker {
69
73
  private hasReachedMinLength;
70
74
  private requestFlush;
71
75
  private scheduleMinLengthFlush;
76
+ private enqueueEventsIfReady;
72
77
  private createBatch;
73
- private getBatchSizeBytes;
74
- private dropOldestPendingBatch;
78
+ private batchSizeBytes;
79
+ private dropOldestPending;
75
80
  private enqueueBatch;
76
81
  private flush;
77
82
  private scheduleRetry;
@@ -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(){let t=i();if(!t)return n;let r=t.getItem(e);if(r)try{let e=JSON.parse(r);if(e.id)return e}catch{}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 c=t.getItem(`faststats_session_start`),u=c===null?s:Number(c),d={id:a,start:Number.isFinite(u)?u:s,activity:s};return l(d),t.removeItem(`faststats_session_id`),t.removeItem(`faststats_session_activity`),t.removeItem(`faststats_session_start`),d}function l(t){let r=i();if(!r){n=t;return}try{r.setItem(e,JSON.stringify(t))}catch{n=t}}function u(){n=null;try{i()?.removeItem(e)}catch{}}function d(e,t){return t-e.activity>=18e5||t-e.start>=864e5}function f(e,t){for(let n of r)n(e,t)}function p(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=c();if(i&&!d(i,r))return t&&(i.activity=r,l(i)),{session:i,rotated:!1,previous:null};let a=i,s={id:o(),start:r,activity:r};return l(s),{session:s,rotated:a!==null,previous:a}}function m(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 h(e,t,n,r){let i=r??m(e,n,t.id);return{sessionId:t.id,windowId:i,sessionStart:t.start}}function g(e){t=e,n=null}function _(){return t}function v(e,n){let r=n??t,{session:i}=p(r,!1);return h(e,i,r)}function y(e,n){let r=n??t,{session:i,rotated:a,previous:o}=p(r,!0);if(!a||!o)return null;let s=m(e,r,i.id),c={prev:h(e,o,r,s),next:h(e,i,r,s)};return f(c.prev,c.next),c}function b(e){let r=t,i=v(e,r);if(u(),r){let e=Date.now();n={id:o(),start:e,activity:e}}else try{a()?.removeItem(`faststats_window_id_${e}`)}catch{}let s=v(e,r);return i.sessionId!==s.sessionId&&f(i,s),s}function x(e){return r.add(e),()=>r.delete(e)}function S(e){return typeof e!=`number`||!Number.isFinite(e)?100:Math.max(0,Math.min(100,e))}async function C(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||typeof Blob>`u`?n:new Blob([n],{type:r});if(globalThis.navigator.sendBeacon(t,e))return a&&console.log(`${o} Sent via beacon`),!0}catch{}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{s as a,b as c,v as i,g as l,C as n,_ as o,o as r,x as s,S as t,y 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-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
+ import{n as e,r as t,t as n}from"./chunks/api-urls-DYXBPqSP.js";import{i as r,n as i}from"./chunks/send-data-BXrEi1iz.js";import{t as a}from"./chunks/identifiers-CWMNnPWe.js";const o=/(?:^|\()(chrome|moz|ms-browser|safari-web)-extension:\/\//;function s(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 c({error:e,message:t,handled:n}){return`${e}\0${t??``}\0${n}`}function l(e,t){let n=t instanceof Error?t.stack??``:``;return o.test(`${e}\n${n}`)}var u=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(s(`Error`,e,!0,e.message))}onError=e=>{l(e.filename??``,e.error)||this.enqueue(s(`Error`,e.error,!1,e.message||`Unknown error`))};onRejection=e=>{l(``,e.reason)||this.enqueue(s(`UnhandledRejection`,e.reason,!1,`Unhandled promise rejection`))};enqueue(e){let t=c(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 o=globalThis.__SOURCEMAPS_BUILD__?.buildId,s=a(),c=r(this.options.siteKey);if(!await i({url:this.endpoint,data:JSON.stringify({token:this.options.siteKey,...s?{userId:s}:{},sessionId:c.sessionId,windowId:c.windowId,...typeof o==`string`&&o.trim()?{buildId:o}:{},sdkName:this.options.sdkName??`@faststats/web`,sdkVersion:this.options.sdkVersion??`0.4.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{u 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}:{}},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};
1
+ import{i as e,t}from"./chunks/api-urls-DYXBPqSP.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,8 +1,9 @@
1
1
  import { FeatureFlagEvaluation } from "./feature-flags.js";
2
- import { n as ReplayTrackerOptions } from "./chunks/replay-DR_T0Iz4.js";
2
+ import { n as ReplayTrackerOptions } from "./chunks/replay-BL2Ev5IF.js";
3
3
 
4
4
  //#region src/analytics.d.ts
5
5
  type ConsentMode = "pending" | "granted" | "denied";
6
+ type PendingBehavior = "anonymous" | "disabled";
6
7
  interface IdentifyOptions {
7
8
  name?: string;
8
9
  phone?: string;
@@ -16,13 +17,10 @@ interface WebAnalyticsOptions {
16
17
  debug?: boolean;
17
18
  autoTrack?: boolean;
18
19
  trackHash?: boolean;
19
- trackErrors?: boolean;
20
- trackWebVitals?: boolean;
21
- trackReplay?: boolean;
22
20
  cookieless?: boolean;
23
21
  consent?: {
24
22
  mode?: ConsentMode;
25
- cookielessWhilePending?: boolean;
23
+ pendingBehavior?: PendingBehavior;
26
24
  };
27
25
  webVitals?: {
28
26
  enabled?: boolean;
@@ -37,6 +35,9 @@ interface WebAnalyticsOptions {
37
35
  percentage?: number;
38
36
  };
39
37
  };
38
+ errorTracking?: {
39
+ enabled?: boolean;
40
+ };
40
41
  replayOptions?: Partial<ReplayTrackerOptions>;
41
42
  /** @internal */
42
43
  sdkName?: string;
@@ -54,37 +55,34 @@ declare function reportError(error: Error): void;
54
55
  declare function isTrackingDisabled(): boolean;
55
56
  declare class WebAnalytics {
56
57
  private readonly options;
57
- private readonly webEndpoint;
58
58
  private readonly baseUrl;
59
- private readonly featureFlagsBaseUrl;
60
59
  private readonly debug;
61
60
  private started;
62
61
  private destroyed;
63
- private pageKey;
62
+ private epoch;
64
63
  private navTimer;
65
64
  private heartbeatTimer;
66
- private pagePath;
67
- private pageUrl;
68
- private pageHash;
69
- private hasLeftCurrentPage;
65
+ private pageKey;
66
+ private entry;
67
+ private left;
70
68
  private consentMode;
71
- private readonly cookielessWhilePending;
72
- private readonly cleanupCallbacks;
69
+ private readonly pendingBehavior;
70
+ private readonly cleanup;
73
71
  private readonly childTrackers;
74
- private readonly pendingReportedErrors;
75
- private errorTracker;
76
- private readonly handleVisibilityChange;
77
- private readonly handlePageHide;
78
- private readonly handlePageShow;
79
72
  constructor(options: WebAnalyticsOptions);
80
73
  private log;
81
- private init;
82
- private ensureStarted;
83
- private addListener;
84
- private patchHistory;
85
- private notifyChildren;
86
- private startChildTracker;
87
- private startOptionalTrackers;
74
+ private ensureActive;
75
+ private canTrack;
76
+ private cookieless;
77
+ private touch;
78
+ private bind;
79
+ private loadChild;
80
+ private loadOptionalTrackers;
81
+ private beginTracking;
82
+ private readonly onLinkClick;
83
+ private readonly onVisibilityChange;
84
+ private readonly onPageHide;
85
+ private readonly onPageShow;
88
86
  start(): Promise<void>;
89
87
  destroy(): void;
90
88
  pageview(extra?: Record<string, unknown>): void;
@@ -101,13 +99,10 @@ declare class WebAnalytics {
101
99
  signal?: AbortSignal;
102
100
  }): Promise<FeatureFlagEvaluation>;
103
101
  reportError(error: Error): void;
104
- private isCookielessMode;
105
102
  private send;
106
- private enterPage;
107
103
  private leavePage;
108
104
  private startHeartbeat;
109
- private stopHeartbeat;
110
105
  private navigate;
111
106
  }
112
107
  //#endregion
113
- export { type ConsentMode, type FeatureFlagEvaluation, type IdentifyOptions, WebAnalytics, type WebAnalyticsOptions, getInstance, identify, isTrackingDisabled, logout, optIn, optOut, reportError, setConsentMode, trackEvent };
108
+ export { type ConsentMode, type FeatureFlagEvaluation, type IdentifyOptions, type PendingBehavior, 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-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};
1
+ import{i as e,n as t,r as n,t as r}from"./chunks/api-urls-DYXBPqSP.js";import{c as i,i as a,l as o,n as s,t as c,u as l}from"./chunks/send-data-BXrEi1iz.js";import{n as u,t as d}from"./chunks/identifiers-CWMNnPWe.js";let f=null,p;function m(){return f}function h(e,t){typeof window>`u`||S()||f?.track(e,t??{})}function g(e,t,n){return typeof window>`u`||S()?Promise.resolve(!1):f?.identify(e,t,n??{})??Promise.resolve(!1)}function _(e=!0){typeof window>`u`||S()||f?.logout(e)}function v(e){f?f.setConsentMode(e):p=e}function y(){v(`granted`)}function b(){v(`denied`)}function x(e){typeof window>`u`||S()||f?.reportError(e)}function S(){try{let e=globalThis.localStorage?.getItem(`disable-faststats`);return e===`true`||e===`1`}catch{return!1}}var C=class{baseUrl;debug;started=!1;destroyed=!1;epoch=0;navTimer=null;heartbeatTimer=null;pageKey=``;entry={path:``,url:``,hash:``};left=!1;consentMode;pendingBehavior;cleanup=[];childTrackers=[];constructor(e){if(this.options=e,this.baseUrl=n(e.baseUrl),this.debug=e.debug??!1,this.consentMode=p??e.consent?.mode??`granted`,p=void 0,this.pendingBehavior=e.consent?.pendingBehavior??`anonymous`,e.autoTrack??!0){if(typeof window>`u`)return;if(S()){this.log(`disabled`);return}setTimeout(()=>void this.start(),0)}}log(e){this.debug&&console.log(`[Analytics] ${e}`)}ensureActive(){return typeof window>`u`||this.destroyed||S()?!1:(this.started||this.start(),this.started&&!this.destroyed&&f===this)}canTrack(){return!(this.consentMode===`pending`&&this.pendingBehavior===`disabled`)}cookieless(){return!!this.options.cookieless||this.consentMode===`denied`||this.consentMode===`pending`&&this.pendingBehavior===`anonymous`}touch(){this.canTrack()&&l(this.options.siteKey,this.cookieless())}bind(e,t,n,r){e.addEventListener(t,n,r),this.cleanup.push(()=>e.removeEventListener(t,n,r))}loadChild(e,t){let n=this.epoch;t().then(async t=>{if(this.epoch!==n||!this.started||(await t.start(),this.epoch!==n||!this.started))return t.stop?.();this.childTrackers.push(t),this.log(`${e} loaded`)}).catch(t=>this.log(`failed to initialize ${e} tracker: ${String(t)}`))}loadOptionalTrackers(){let e=this.options,t={siteKey:e.siteKey,baseUrl:this.baseUrl,debug:this.debug};if(e.sessionReplays?.enabled){let n=e.replayOptions??{};this.loadChild(`replay`,async()=>{let{default:r}=await import(`./replay.js`);return new r({...t,...n,samplingPercentage:c(n.samplingPercentage??e.sessionReplays?.sampling?.percentage),cookieless:this.cookieless()})})}e.errorTracking?.enabled&&this.loadChild(`error`,async()=>{let{default:n}=await import(`./error.js`);return new n({...t,sdkName:e.sdkName,sdkVersion:e.sdkVersion})}),e.webVitals?.enabled&&this.loadChild(`web-vitals`,async()=>{let{default:n}=await import(`./web-vitals.js`);return new n({...t,samplingPercentage:c(e.webVitals?.sampling?.percentage),attribution:e.webVitals?.attribution??!1})})}beginTracking(e){this.touch(),this.loadOptionalTrackers(),this.entry={path:location.pathname,url:location.href,hash:location.hash},this.left=!1,this.pageKey=``,this.pageview({trigger:e})}onLinkClick=e=>{let t=e.target;for(;t;){if(t instanceof HTMLAnchorElement&&t.href&&t.host!==location.host){this.track(`outbound_link`,{outbound_link:t.href});return}t=t.parentNode}};onVisibilityChange=()=>{if(this.touch(),document.visibilityState===`hidden`){for(let e of this.childTrackers)e.onPageHidden?.();this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null;return}this.startHeartbeat()};onPageHide=e=>{let t=e.persisted;for(let e of this.childTrackers)e.onPageHidden?.(t);t||this.leavePage()};onPageShow=e=>{for(let t of this.childTrackers)t.onPageShow?.(e.persisted)};async start(){if(this.started||this.destroyed||typeof window>`u`)return;if(f&&f!==this){this.log(`already started by another instance`);return}if(S()){this.log(`disabled`);return}this.started=!0,f=this,o(this.cookieless()),this.canTrack()&&this.beginTracking(`load`),this.startHeartbeat();let e=()=>this.navigate(),t=[[document,`click`,this.onLinkClick],[document,`auxclick`,this.onLinkClick],[document,`visibilitychange`,this.onVisibilityChange],[window,`pagehide`,this.onPageHide],[window,`pageshow`,this.onPageShow],[window,`popstate`,e]];(this.options.trackHash??!1)&&t.push([window,`hashchange`,e]);for(let[e,n,r]of t)this.bind(e,n,r);for(let e of[`pushState`,`replaceState`]){let t=history[e].bind(history);history[e]=(e,n,r)=>{t(e,n,r),this.navigate()},this.cleanup.push(()=>{history[e]=t})}}destroy(){if(!this.destroyed){this.epoch++,this.started&&typeof window<`u`&&this.leavePage(),this.navTimer&&clearTimeout(this.navTimer),this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null;for(let e of this.cleanup.splice(0))e();for(let e of this.childTrackers.splice(0))e.stop?.();f===this&&(f=null),this.started=!1,this.destroyed=!0}}pageview(e={}){if(!this.ensureActive())return;let t=this.options.trackHash??!1,n=`${location.pathname}|${t?location.hash:``}`;n!==this.pageKey&&(this.pageKey=n,this.send(`pageview`,e))}track(e,t={}){if(!this.ensureActive())return;let n=e.trim();n&&this.send(n,t)}identify(e,t,n={}){if(!this.ensureActive()||!this.canTrack()||this.cookieless())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.ensureActive()&&(e&&u(this.cookieless()),i(this.options.siteKey))}setConsentMode(e){let t=!this.canTrack();this.consentMode=e;let n=this.cookieless();o(n);for(let e of this.childTrackers)e.setCookielessMode?.(n);t&&this.canTrack()&&this.started&&this.beginTracking(`consent`)}getConsentMode(){return this.consentMode}getAnonymousId(){return this.canTrack()?d(this.cookieless()):``}getSessionId(){return a(this.options.siteKey,this.cookieless()).sessionId}getWindowId(){return a(this.options.siteKey,this.cookieless()).windowId}async checkFeatureFlag(t,n,r){if(typeof window>`u`||S()||!this.canTrack())return{value:`false`};let i=r?.externalId?.trim(),a=this.getAnonymousId();if(!i&&!a)return{value:`false`};let{fetchFeatureFlagEvaluation:o}=await import(`./feature-flags.js`);return o(t,{baseUrl:e(this.options.featureFlagsBaseUrl),projectToken:this.options.siteKey,...a?{identifier:a}:{},...i?{externalId:i}:{},sessionId:this.getSessionId(),attributes:n,signal:r?.signal})}reportError(e){!this.ensureActive()||!this.options.errorTracking?.enabled||!this.canTrack()||this.childTrackers.find(e=>`captureError`in e)?.captureError(e)}send(e,n={},i={}){if(typeof window>`u`||this.destroyed||S()||!this.canTrack())return;let o=this.cookieless(),c=d(o),l=a(this.options.siteKey,o);this.log(e),s({url:`${this.baseUrl}${r.events}`,data:JSON.stringify({token:this.options.siteKey,...c?{userId:c}:{},sessionId:l.sessionId,windowId:l.windowId,event:e,...t(),...i,properties:n}),contentType:`text/plain`,debug:this.debug,debugPrefix:`[Analytics] ${e}`})}leavePage(){if(this.destroyed||this.left)return;this.left=!0;let e=a(this.options.siteKey,this.cookieless());this.send(`page_leave`,{session_duration:Date.now()-e.sessionStart},{page:this.entry.path,url:this.entry.url})}startHeartbeat(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=setInterval(()=>{if(document.visibilityState===`hidden`){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=null;return}this.touch()},300*1e3)}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.entry.path&&(!e||location.hash===this.entry.hash))){for(let e of this.childTrackers)e.trackPageChange?.(location.href);this.leavePage(),this.entry={path:location.pathname,url:location.href,hash:location.hash},this.left=!1,this.pageview({trigger:`navigation`})}},300))}};export{C as WebAnalytics,m as getInstance,g as identify,S as isTrackingDisabled,_ as logout,y as optIn,b as optOut,x as reportError,v as setConsentMode,h as trackEvent};
package/dist/replay.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as ReplayTrackerOptions, t as ReplayTracker } from "./chunks/replay-DR_T0Iz4.js";
1
+ import { n as ReplayTrackerOptions, t as ReplayTracker } from "./chunks/replay-BL2Ev5IF.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-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};
1
+ import{r as e,t}from"./chunks/api-urls-DYXBPqSP.js";import{a as n,i as r,n as i,r as a,s as o,t as s,u as c}from"./chunks/send-data-BXrEi1iz.js";import{t as l}from"./chunks/identifiers-CWMNnPWe.js";import{record as u}from"@rrweb/record";const d={mousemove:50,mouseInteraction:!0,scroll:150,media:800,input:`last`};function f(e){return`faststats_replay_sampled_${e}`}function p(e,t,i){let a=s(t);if(a>=100)return!0;if(a<=0)return!1;let o=r(e,i).sessionId,c=f(e),l=`${o}:${a}`;try{let e=sessionStorage?.getItem(c);if(e===l)return!0;if(e?.startsWith(`${o}:`))return!1}catch{}let u=n(o)%100<a;try{sessionStorage?.setItem(c,u?l:`${o}:out`)}catch{}return u}var m=class{endpoint;compressionSupported=typeof window<`u`&&`CompressionStream`in window;flushInterval;maxEvents;maxPendingBatches;maxQueueSizeBytes;minReplayLengthMs;sampled;events=[];pending=[];pendingSizeBytes=0;viewId=a();chunkStartedAt=0;started=!1;startGeneration=0;startTime=0;sequence=0;intervalId=null;flushTask=null;retryTask=null;minLengthFlushTask=null;stopRecording;sending=!1;flushQueued=!1;flushQueuedLowLatency=!1;unsubscribeRotation;cookieless;constructor(n){this.options=n,this.endpoint=`${e(n.baseUrl)}${t.replay}`,this.cookieless=n.cookieless??!1,this.flushInterval=n.flushInterval??1e4,this.maxEvents=n.maxEvents??500,this.maxPendingBatches=n.maxPendingBatches??30,this.maxQueueSizeBytes=n.maxQueueSizeBytes??2097152,this.minReplayLengthMs=n.minReplayLengthMs??3e3,this.sampled=p(n.siteKey,n.samplingPercentage??100,this.cookieless)}log(...e){this.options.debug&&console.log(`[Replay]`,...e)}sessionContext(){return r(this.options.siteKey,this.cookieless)}clearFlushTimers(){this.flushTask&&clearTimeout(this.flushTask),this.retryTask&&clearTimeout(this.retryTask),this.minLengthFlushTask&&clearTimeout(this.minLengthFlushTask),this.flushTask=null,this.retryTask=null,this.minLengthFlushTask=null}clearQueues(){this.events.length=0,this.pending.length=0,this.pendingSizeBytes=0}setCookielessMode(e){this.cookieless!==e&&(this.cookieless=e,e&&(this.clearQueues(),this.clearFlushTimers()),this.startTime=this.sessionContext().sessionStart,this.chunkStartedAt=Date.now())}start(){if(this.started||typeof window>`u`||!this.sampled)return;this.started=!0,this.viewId=a(),this.startTime=this.sessionContext().sessionStart,this.chunkStartedAt=Date.now(),this.unsubscribeRotation=o(e=>{this.onSessionRotated(e)});let e=++this.startGeneration;this.beginRecording(e),this.intervalId=setInterval(this.requestFlush,this.flushInterval),window.addEventListener(`beforeunload`,this.onUnload),this.log(`Recording started`)}trackPageChange(e){this.started&&(this.viewId=a(),this.chunkStartedAt=Date.now(),this.onEvent({type:5,timestamp:Date.now(),data:{tag:`faststats:view`,payload:{href:e??window.location.href,viewId:this.viewId}}},!1))}onPageHidden(e=!1){e||this.flush(!0,!0)}onPageShow(e=!1){!e||!this.started||this.pending.length>0&&this.flush(!1)}async beginRecording(e){let t=this.options.recordConsole===!1?null:await import(`@rrweb/rrweb-plugin-console-record`);if(e!==this.startGeneration)return;let n=[];t&&n.push(t.getRecordConsolePlugin());let r=u({emit:this.onEvent,sampling:this.options.sampling??d,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:n});if(e!==this.startGeneration){r?.();return}this.stopRecording=r}stop(){this.started&&(this.started=!1,this.startGeneration++,this.unsubscribeRotation?.(),this.unsubscribeRotation=void 0,this.stopRecording?.(),this.stopRecording=void 0,this.intervalId&&clearInterval(this.intervalId),this.clearFlushTimers(),this.intervalId=null,window.removeEventListener(`beforeunload`,this.onUnload),this.hasReachedMinLength()||(this.events.length=0,this.log(`Session too short (${Date.now()-this.startTime}ms), discarding events`)),this.flush(!0,!0),this.log(`Recording stopped`))}onSessionRotated(e){this.started&&(this.enqueueEventsIfReady(e,!0),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,!0)};hasReachedMinLength(){return this.minReplayLengthMs<=0||Date.now()-this.startTime>=this.minReplayLengthMs}requestFlush=()=>{this.flushTask||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));this.minLengthFlushTask=setTimeout(()=>{this.minLengthFlushTask=null,this.requestFlush()},Math.min(e,2147483647))}enqueueEventsIfReady(e,t){if(this.events.length!==0){if(!t&&!this.hasReachedMinLength()){this.scheduleMinLengthFlush();return}this.enqueueBatch(this.createBatch(this.events.splice(0),e,t))}}createBatch(e,t,n){let r=l(this.cookieless),i=this.sequence++,a=this.chunkStartedAt,o=Date.now();return this.chunkStartedAt=o,{token:this.options.siteKey,sessionId:t.sessionId,windowId:t.windowId,viewId:this.viewId,sessionStart:t.sessionStart,chunkStartedAt:a,chunkEndedAt:o,...r?{identifier:r}:{},batchId:`${t.sessionId}-${i}-${a}`,sequence:i,timestamp:o,url:window.location.href,...n?{isFinal:!0}:{},events:e}}batchSizeBytes(e){return new TextEncoder().encode(JSON.stringify(e)).byteLength}dropOldestPending(e){let t=this.pending.shift();t&&(this.pendingSizeBytes=Math.max(0,this.pendingSizeBytes-this.batchSizeBytes(t)),this.log(`${e}, dropping batch ${t.sequence}`))}enqueueBatch(e){let t=this.batchSizeBytes(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>=this.maxPendingBatches||this.pendingSizeBytes+t>this.maxQueueSizeBytes)&&this.pending.length>0;)this.dropOldestPending(`Pending queue limit reached`);this.pending.push(e),this.pendingSizeBytes+=t}async flush(e,t){let n=c(this.options.siteKey,this.cookieless);if(n&&this.enqueueEventsIfReady(n.prev,!0),this.enqueueEventsIfReady(this.sessionContext(),t),this.pending.length!==0){if(this.sending){this.flushQueued=!0,this.flushQueuedLowLatency||=e;return}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.dropOldestPending(`Sent replay batch`),e=!1}}finally{if(this.sending=!1,this.flushQueued){let e=this.flushQueuedLowLatency;this.flushQueued=!1,this.flushQueuedLowLatency=!1,this.flush(e)}}}}scheduleRetry(){this.retryTask||=setTimeout(()=>{this.retryTask=null,this.flush(!1)},1e3)}async sendBatch(e,t){let n=JSON.stringify(e),r={debug:!1,useBeacon:t,keepalive:t};if(!t&&(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)}%)`),i({url:`${this.endpoint}?encoding=gzip`,data:t,contentType:`application/octet-stream`,...r})}catch{this.log(`Compression failed, using uncompressed`)}return i({url:this.endpoint,data:n,contentType:`application/json`,...r})}};export{m as default};
@@ -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-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};
1
+ import{r as e,t}from"./chunks/api-urls-DYXBPqSP.js";import{a as n,i as r,n as i,t as a}from"./chunks/send-data-BXrEi1iz.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(i.siteKey).sessionId)%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;let t=r(this.options.siteKey);i({url:this.endpoint,data:JSON.stringify({token:this.options.siteKey,sessionId:t.sessionId,windowId:t.windowId,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.1",
45
+ "version": "0.4.0",
46
46
  "scripts": {
47
47
  "build": "tsdown && bun run check-size",
48
48
  "dev": "bun run build",
@@ -51,7 +51,7 @@
51
51
  "check-size": "node scripts/check-bundle-size.mjs"
52
52
  },
53
53
  "devDependencies": {
54
- "@biomejs/biome": "2.4.2",
54
+ "@rrweb/types": "^2.0.1",
55
55
  "@types/bun": "latest",
56
56
  "tsdown": "^0.21.4",
57
57
  "typescript": "^5.9.3"
@@ -1 +0,0 @@
1
- function e(e){return e.replace(/\/+$/,``)}function t(t,n){return t===void 0||t===``?n:e(t)||n}function n(e){return t(e,`https://metrics.faststats.dev`)}function r(e){return t(e,`https://flags.faststats.dev`)}const i={events:`/v1/web`,identify:`/v1/identify`,replay:`/v1/replay`,vitals:`/v1/vitals`,flags:`/v1/check`};function a(){return{page:location.pathname,url:location.href,referrer:document.referrer||null,title:document.title||``}}export{r as i,a as n,n as r,i as t};
@@ -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`&&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};