@faststats/web 0.7.0 → 0.8.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,10 @@
1
+ import { t as AnalyticsExtension } from "./chunks/extensions-DW7tJY0T.js";
2
+ //#region src/outbound-links.d.ts
3
+ declare function outboundLinks(): AnalyticsExtension;
4
+ declare class OutboundLinkTracker {
5
+ private lastActivation;
6
+ getHref(event: Event): string | null;
7
+ private isDuplicate;
8
+ }
9
+ //#endregion
10
+ export { OutboundLinkTracker, outboundLinks };
@@ -0,0 +1,62 @@
1
+ import { a as sanitizeUrl } from "./chunks/api-urls-DWk43fu6.js";
2
+ //#region src/outbound-links.ts
3
+ function outboundLinks() {
4
+ return {
5
+ name: "outbound-links",
6
+ setup(context) {
7
+ const tracker = new OutboundLinkTracker();
8
+ const onClick = (event) => {
9
+ const href = tracker.getHref(event);
10
+ if (href) context.capture("outbound_link", { outbound_link: sanitizeUrl(href) });
11
+ };
12
+ document.addEventListener("click", onClick, true);
13
+ document.addEventListener("auxclick", onClick, true);
14
+ return () => {
15
+ document.removeEventListener("click", onClick, true);
16
+ document.removeEventListener("auxclick", onClick, true);
17
+ };
18
+ }
19
+ };
20
+ }
21
+ const DEDUPE_MS = 500;
22
+ var OutboundLinkTracker = class {
23
+ lastActivation = null;
24
+ getHref(event) {
25
+ if (!(event instanceof MouseEvent) || !isEligibleActivation(event)) return null;
26
+ const anchor = findOutboundAnchor(event);
27
+ if (!anchor || this.isDuplicate(event, anchor.href)) return null;
28
+ return anchor.href;
29
+ }
30
+ isDuplicate(event, href) {
31
+ const activation = {
32
+ button: event.button,
33
+ href,
34
+ clientX: event.clientX,
35
+ clientY: event.clientY,
36
+ at: Date.now()
37
+ };
38
+ const previous = this.lastActivation;
39
+ this.lastActivation = activation;
40
+ return !!(previous && previous.href === activation.href && previous.button === activation.button && previous.clientX === activation.clientX && previous.clientY === activation.clientY && activation.at - previous.at <= DEDUPE_MS);
41
+ }
42
+ };
43
+ function isEligibleActivation(event) {
44
+ if (event.defaultPrevented) return false;
45
+ if (event.type === "click") return event.button === 0;
46
+ if (event.type === "auxclick") return event.button === 1;
47
+ return false;
48
+ }
49
+ function findOutboundAnchor(event) {
50
+ for (const node of event.composedPath()) if (isOutboundAnchor(node)) return node;
51
+ let node = event.target;
52
+ while (node) {
53
+ if (isOutboundAnchor(node)) return node;
54
+ node = node.parentNode;
55
+ }
56
+ return null;
57
+ }
58
+ function isOutboundAnchor(node) {
59
+ return node instanceof HTMLAnchorElement && (node.protocol === "http:" || node.protocol === "https:") && node.host !== location.host;
60
+ }
61
+ //#endregion
62
+ export { OutboundLinkTracker, outboundLinks };
package/dist/replay.d.ts CHANGED
@@ -1,2 +1,128 @@
1
- import { n as ReplayTrackerOptions, t as ReplayTracker } from "./chunks/replay-BeC2XA4N.js";
2
- export { ReplayTrackerOptions, ReplayTracker as default };
1
+ import { t as AnalyticsExtension } from "./chunks/extensions-DW7tJY0T.js";
2
+ import { record } from "@rrweb/record";
3
+ import { LogLevel } from "@rrweb/rrweb-plugin-console-record";
4
+ //#region ../../node_modules/.bun/@rrweb+types@2.1.1/node_modules/@rrweb/types/dist/index.d.ts
5
+ declare global {
6
+ interface Window {
7
+ FontFace: typeof FontFace;
8
+ }
9
+ }
10
+ //#endregion
11
+ //#region src/replay-mutation-throttler.d.ts
12
+ type ReplayMutationThrottleOptions = {
13
+ enabled?: boolean;
14
+ bucketSize?: number;
15
+ refillRate?: number;
16
+ };
17
+ //#endregion
18
+ //#region src/replay.d.ts
19
+ type RecordOptions = NonNullable<Parameters<typeof record>[0]>;
20
+ interface ReplayTrackerOptions {
21
+ siteKey: string;
22
+ baseUrl?: string;
23
+ debug?: boolean;
24
+ trackHash?: boolean;
25
+ cookieless?: boolean;
26
+ compress?: boolean;
27
+ flushInterval?: number;
28
+ maxEvents?: number;
29
+ maxBatchSizeBytes?: number;
30
+ maxLowLatencyBatchSizeBytes?: number;
31
+ maxPendingBatches?: number;
32
+ maxQueueSizeBytes?: number;
33
+ minReplayLengthMs?: number;
34
+ sampling?: RecordOptions["sampling"];
35
+ slimDOMOptions?: RecordOptions["slimDOMOptions"];
36
+ maskAllInputs?: boolean;
37
+ maskInputOptions?: RecordOptions["maskInputOptions"];
38
+ blockClass?: string;
39
+ blockSelector?: string;
40
+ maskTextClass?: string;
41
+ maskTextSelector?: string;
42
+ checkoutEveryNms?: number;
43
+ checkoutEveryNth?: number;
44
+ recordConsole?: boolean;
45
+ consoleLevel?: LogLevel[];
46
+ consoleLengthThreshold?: number;
47
+ consoleStringLengthLimit?: number;
48
+ mutationThrottle?: ReplayMutationThrottleOptions;
49
+ }
50
+ type SessionReplayExtensionOptions = Omit<ReplayTrackerOptions, "siteKey" | "baseUrl" | "debug" | "trackHash" | "cookieless">;
51
+ declare function sessionReplay(options?: SessionReplayExtensionOptions): AnalyticsExtension;
52
+ declare class ReplayTracker {
53
+ private readonly options;
54
+ private readonly endpoint;
55
+ private readonly compressionSupported;
56
+ private readonly flushInterval;
57
+ private readonly maxEvents;
58
+ private readonly maxBatchSizeBytes;
59
+ private readonly maxLowLatencyBatchSizeBytes;
60
+ private readonly maxPendingBatches;
61
+ private readonly maxQueueSizeBytes;
62
+ private readonly minReplayLengthMs;
63
+ private readonly events;
64
+ private readonly pending;
65
+ private readonly minLengthBlockedBatches;
66
+ private queuedEventsSizeBytes;
67
+ private pendingSizeBytes;
68
+ private viewId;
69
+ private viewUrl;
70
+ private chunkStartedAt;
71
+ private started;
72
+ private disposed;
73
+ private startTime;
74
+ private sequence;
75
+ private intervalId;
76
+ private flushTask;
77
+ private retryTask;
78
+ private retryAttempt;
79
+ private minLengthFlushTask;
80
+ private stopRecording?;
81
+ private sending;
82
+ private inFlightBatch;
83
+ private queuedFlush;
84
+ private unsubscribeRotation?;
85
+ private lastCookielessMode;
86
+ private terminalFlushRequested;
87
+ private overflowed;
88
+ private replayEventSequence;
89
+ private readonly mutationThrottler;
90
+ constructor(options: ReplayTrackerOptions);
91
+ private log;
92
+ private clearFlushTimers;
93
+ private clearQueues;
94
+ private dropMinLengthBlockedBatches;
95
+ private unblockSessionBatches;
96
+ private finalizeSessionPending;
97
+ private nextBatchSequence;
98
+ setCookielessMode(cookieless: boolean): void;
99
+ start(): void;
100
+ trackPageChange(url?: string): void;
101
+ onPageHidden(persisted?: boolean, terminal?: boolean): void;
102
+ onPageShow(persisted?: boolean): void;
103
+ private beginRecording;
104
+ stop(discard?: boolean): void;
105
+ private onSessionRotated;
106
+ private subscribeToSessionRotation;
107
+ private applySessionRotation;
108
+ private resetSessionTiming;
109
+ private onEvent;
110
+ private onUnload;
111
+ private requestTerminalFlush;
112
+ private hasReachedMinLength;
113
+ private requestFlush;
114
+ private scheduleMinLengthFlush;
115
+ private enqueueEventsIfReady;
116
+ private takeEventBatches;
117
+ private createBatch;
118
+ private eventSizeBytes;
119
+ private batchSizeBytes;
120
+ private removePending;
121
+ private enqueueBatch;
122
+ private flush;
123
+ private scheduleRetry;
124
+ private retryDelay;
125
+ private sendBatch;
126
+ }
127
+ //#endregion
128
+ export { ReplayTrackerOptions, SessionReplayExtensionOptions, ReplayTracker as default, sessionReplay };
package/dist/replay.js CHANGED
@@ -1,7 +1,8 @@
1
- import { a as resolveBaseUrl, o as sanitizeUrl, r as URLS, t as ANALYTICS_BASE } from "./chunks/api-urls-Dp2XNjRF.js";
2
- import { a as onSessionRotated, c as touchActivity, d as setStorageItem, i as isCookielessMode, l as getStorageItem, n as createId, r as getSessionContext, t as sendData } from "./chunks/send-data-DR1JUXka.js";
3
- import { t as getAnonymousId } from "./chunks/identifiers-BvRNbiwA.js";
1
+ import { a as sanitizeUrl, i as resolveBaseUrl, n as URLS, t as ANALYTICS_BASE } from "./chunks/api-urls-DWk43fu6.js";
2
+ import { i as onSessionRotated, l as setStorageItem, n as createId, o as touchActivity, r as getSessionContext, s as getStorageItem, t as sendData } from "./chunks/send-data-DFZnsaL2.js";
3
+ import { t as getAnonymousId } from "./chunks/identifiers-KgQDX74Q.js";
4
4
  import { record } from "@rrweb/record";
5
+ import { getRecordConsolePlugin } from "@rrweb/rrweb-plugin-console-record";
5
6
  //#region src/replay-mutation-throttler.ts
6
7
  const INCREMENTAL_SNAPSHOT_EVENT_TYPE = 3;
7
8
  const MUTATION_SOURCE_TYPE = 0;
@@ -52,18 +53,39 @@ var ReplayMutationThrottler = class {
52
53
  //#endregion
53
54
  //#region src/replay.ts
54
55
  const MAX_TIMEOUT_MS = 2147483647;
55
- const DEFAULT_MAX_QUEUE_SIZE_BYTES = 2 * 1024 * 1024;
56
- const DEFAULT_MAX_BATCH_SIZE_BYTES = 900 * 1024;
57
- const DEFAULT_MAX_LOW_LATENCY_BATCH_SIZE_BYTES = 60 * 1024;
56
+ const DEFAULT_MAX_QUEUE_SIZE_BYTES = 2097152;
57
+ const DEFAULT_MAX_BATCH_SIZE_BYTES = 921600;
58
+ const DEFAULT_MAX_LOW_LATENCY_BATCH_SIZE_BYTES = 61440;
58
59
  const RETRY_BASE_DELAY_MS = 2e3;
59
60
  const RETRY_MAX_ATTEMPTS = 5;
60
- const RETRY_COOLDOWN_MS = 5 * 6e4;
61
+ const RETRY_COOLDOWN_MS = 3e5;
61
62
  const VIEW_META_EVENT_TYPE = 5;
62
63
  const RRWEB_EVENT_FULL_SNAPSHOT = 2;
63
64
  const RRWEB_EVENT_META = 4;
64
65
  const REPLAY_SEQUENTIAL_ID_KEY = "_faststatsSeqId";
65
66
  const textEncoder = new TextEncoder();
66
67
  const batchSizeCache = /* @__PURE__ */ new WeakMap();
68
+ function sessionReplay(options = {}) {
69
+ return {
70
+ name: "session-replay",
71
+ setup(context) {
72
+ const tracker = new ReplayTracker({
73
+ ...options,
74
+ siteKey: context.siteKey,
75
+ baseUrl: context.baseUrl,
76
+ debug: context.debug,
77
+ trackHash: context.trackHash,
78
+ cookieless: context.isCookieless()
79
+ });
80
+ context.on("pageChange", ({ url }) => tracker.trackPageChange(url));
81
+ context.on("pageHide", ({ persisted, terminal }) => tracker.onPageHidden(persisted, terminal));
82
+ context.on("pageShow", ({ persisted }) => tracker.onPageShow(persisted));
83
+ context.on("consentChange", ({ cookieless }) => tracker.setCookielessMode(cookieless));
84
+ tracker.start();
85
+ return ({ discard }) => tracker.stop(discard);
86
+ }
87
+ };
88
+ }
67
89
  var ReplayTracker = class {
68
90
  options;
69
91
  endpoint;
@@ -85,7 +107,6 @@ var ReplayTracker = class {
85
107
  chunkStartedAt = 0;
86
108
  started = false;
87
109
  disposed = false;
88
- startGeneration = 0;
89
110
  startTime = 0;
90
111
  sequence = 0;
91
112
  intervalId = null;
@@ -98,12 +119,14 @@ var ReplayTracker = class {
98
119
  inFlightBatch = null;
99
120
  queuedFlush = null;
100
121
  unsubscribeRotation;
101
- lastCookielessMode = isCookielessMode();
122
+ lastCookielessMode;
102
123
  terminalFlushRequested = false;
103
124
  overflowed = false;
125
+ replayEventSequence = 0;
104
126
  mutationThrottler;
105
127
  constructor(options) {
106
128
  this.options = options;
129
+ this.lastCookielessMode = options.cookieless ?? false;
107
130
  this.endpoint = `${resolveBaseUrl(options.baseUrl, ANALYTICS_BASE)}${URLS.replay}`;
108
131
  this.flushInterval = options.flushInterval ?? 15e3;
109
132
  this.maxEvents = options.maxEvents ?? 1e3;
@@ -166,9 +189,10 @@ var ReplayTracker = class {
166
189
  setCookielessMode(cookieless) {
167
190
  if (this.lastCookielessMode === cookieless) return;
168
191
  this.lastCookielessMode = cookieless;
192
+ if (this.started) this.subscribeToSessionRotation();
169
193
  this.clearQueues();
170
194
  this.clearFlushTimers();
171
- this.startTime = getSessionContext(this.options.siteKey).sessionStart;
195
+ this.startTime = getSessionContext(this.options.siteKey, this.lastCookielessMode).sessionStart;
172
196
  this.chunkStartedAt = Date.now();
173
197
  }
174
198
  start() {
@@ -179,13 +203,10 @@ var ReplayTracker = class {
179
203
  this.overflowed = false;
180
204
  this.viewId = createId();
181
205
  this.viewUrl = sanitizeUrl(window.location.href, this.options.trackHash ?? false);
182
- this.startTime = getSessionContext(this.options.siteKey).sessionStart;
206
+ this.startTime = getSessionContext(this.options.siteKey, this.lastCookielessMode).sessionStart;
183
207
  this.chunkStartedAt = Date.now();
184
- this.unsubscribeRotation = onSessionRotated((prev, next) => {
185
- this.onSessionRotated(prev, next);
186
- });
187
- const generation = ++this.startGeneration;
188
- this.beginRecording(generation);
208
+ this.subscribeToSessionRotation();
209
+ this.beginRecording();
189
210
  this.intervalId = setInterval(() => this.requestFlush("interval"), this.flushInterval);
190
211
  window.addEventListener("beforeunload", this.onUnload);
191
212
  this.log("Recording started");
@@ -219,11 +240,9 @@ var ReplayTracker = class {
219
240
  if (!persisted || !this.started) return;
220
241
  if (this.pending.length > 0) this.flush(false, false, "pageShow");
221
242
  }
222
- async beginRecording(generation) {
223
- const [consolePluginModule, sequentialIdPluginModule] = await Promise.all([this.options.recordConsole === true ? import("@rrweb/rrweb-plugin-console-record") : Promise.resolve(null), import("@rrweb/rrweb-plugin-sequential-id-record")]);
224
- if (generation !== this.startGeneration) return;
225
- const plugins = [sequentialIdPluginModule.getRecordSequentialIdPlugin({ key: REPLAY_SEQUENTIAL_ID_KEY })];
226
- if (consolePluginModule) plugins.push(consolePluginModule.getRecordConsolePlugin({
243
+ beginRecording() {
244
+ const plugins = [];
245
+ if (this.options.recordConsole === true) plugins.push(getRecordConsolePlugin({
227
246
  level: this.options.consoleLevel ?? [
228
247
  "error",
229
248
  "warn",
@@ -267,21 +286,16 @@ var ReplayTracker = class {
267
286
  blockSelector: this.options.blockSelector,
268
287
  maskTextClass: this.options.maskTextClass,
269
288
  maskTextSelector: this.options.maskTextSelector,
270
- checkoutEveryNms: this.options.checkoutEveryNms ?? 5 * 6e4,
289
+ checkoutEveryNms: this.options.checkoutEveryNms ?? 3e5,
271
290
  checkoutEveryNth: this.options.checkoutEveryNth,
272
291
  plugins
273
292
  });
274
- if (generation !== this.startGeneration) {
275
- stop?.();
276
- return;
277
- }
278
293
  this.stopRecording = stop;
279
294
  }
280
295
  stop(discard = false) {
281
296
  if (!this.started) return;
282
297
  this.started = false;
283
298
  this.disposed = true;
284
- this.startGeneration++;
285
299
  this.unsubscribeRotation?.();
286
300
  this.unsubscribeRotation = void 0;
287
301
  this.stopRecording?.();
@@ -309,6 +323,10 @@ var ReplayTracker = class {
309
323
  this.applySessionRotation(prev, next);
310
324
  if (this.pending.length > 0) queueMicrotask(() => void this.flush(false, false, "sessionRotate"));
311
325
  }
326
+ subscribeToSessionRotation() {
327
+ this.unsubscribeRotation?.();
328
+ this.unsubscribeRotation = onSessionRotated(this.options.siteKey, this.lastCookielessMode, (prev, next) => this.onSessionRotated(prev, next));
329
+ }
312
330
  applySessionRotation(prev, next) {
313
331
  this.enqueueEventsIfReady(prev, {
314
332
  isFinal: true,
@@ -343,6 +361,7 @@ var ReplayTracker = class {
343
361
  if (this.mutationThrottler && !throttled) return;
344
362
  if (throttled) capturedEvent = throttled;
345
363
  }
364
+ capturedEvent = Object.assign(capturedEvent, { [REPLAY_SEQUENTIAL_ID_KEY]: ++this.replayEventSequence });
346
365
  this.events.push(capturedEvent);
347
366
  this.queuedEventsSizeBytes += this.eventSizeBytes(capturedEvent);
348
367
  let reason;
@@ -421,7 +440,7 @@ var ReplayTracker = class {
421
440
  return batches;
422
441
  }
423
442
  createBatch(events, context, isFinal, flushReason = "manual") {
424
- const identifier = getAnonymousId(this.options.siteKey);
443
+ const identifier = getAnonymousId(this.options.siteKey, this.lastCookielessMode);
425
444
  const sequence = this.nextBatchSequence(context);
426
445
  const chunkStartedAt = this.chunkStartedAt;
427
446
  const now = Date.now();
@@ -475,9 +494,9 @@ var ReplayTracker = class {
475
494
  this.pendingSizeBytes += size;
476
495
  }
477
496
  async flush(lowLatency, isFinal = false, flushReason = "manual") {
478
- const rotation = touchActivity(this.options.siteKey);
497
+ const rotation = touchActivity(this.options.siteKey, this.lastCookielessMode);
479
498
  if (rotation) this.applySessionRotation(rotation.prev, rotation.next);
480
- const context = getSessionContext(this.options.siteKey);
499
+ const context = getSessionContext(this.options.siteKey, this.lastCookielessMode);
481
500
  this.enqueueEventsIfReady(context, {
482
501
  isFinal,
483
502
  flushReason,
@@ -549,7 +568,7 @@ var ReplayTracker = class {
549
568
  }
550
569
  async sendBatch(batch, lowLatency) {
551
570
  const json = JSON.stringify(batch);
552
- const lowLatencySafe = lowLatency && textEncoder.encode(json).byteLength <= 60 * 1024;
571
+ const lowLatencySafe = lowLatency && textEncoder.encode(json).byteLength <= 61440;
553
572
  const sendOptions = {
554
573
  useBeacon: lowLatencySafe,
555
574
  keepalive: lowLatencySafe
@@ -576,4 +595,4 @@ var ReplayTracker = class {
576
595
  }
577
596
  };
578
597
  //#endregion
579
- export { ReplayTracker as default };
598
+ export { ReplayTracker as default, sessionReplay };
@@ -1,3 +1,4 @@
1
+ import { t as AnalyticsExtension } from "./chunks/extensions-DW7tJY0T.js";
1
2
  //#region src/web-vitals.d.ts
2
3
  interface WebVitalsOptions {
3
4
  siteKey: string;
@@ -5,7 +6,10 @@ interface WebVitalsOptions {
5
6
  debug?: boolean;
6
7
  attribution?: boolean;
7
8
  trackHash?: boolean;
9
+ cookieless?: boolean;
8
10
  }
11
+ type WebVitalsExtensionOptions = Pick<WebVitalsOptions, "attribution">;
12
+ declare function webVitals(options?: WebVitalsExtensionOptions): AnalyticsExtension;
9
13
  declare class WebVitalsTracker {
10
14
  private readonly options;
11
15
  private readonly endpoint;
@@ -14,7 +18,9 @@ declare class WebVitalsTracker {
14
18
  private flushing;
15
19
  private initialUrl;
16
20
  private session;
21
+ private cookieless;
17
22
  constructor(options: WebVitalsOptions);
23
+ setCookielessMode(cookieless: boolean): void;
18
24
  start(): Promise<void>;
19
25
  stop(discard?: boolean): void;
20
26
  onPageHidden(persisted?: boolean): void;
@@ -22,4 +28,4 @@ declare class WebVitalsTracker {
22
28
  private flush;
23
29
  }
24
30
  //#endregion
25
- export { WebVitalsOptions, WebVitalsTracker as default };
31
+ export { WebVitalsExtensionOptions, WebVitalsOptions, WebVitalsTracker as default, webVitals };
@@ -1,6 +1,25 @@
1
- import { a as resolveBaseUrl, o as sanitizeUrl, r as URLS, t as ANALYTICS_BASE } from "./chunks/api-urls-Dp2XNjRF.js";
2
- import { r as getSessionContext, t as sendData } from "./chunks/send-data-DR1JUXka.js";
1
+ import { a as sanitizeUrl, i as resolveBaseUrl, n as URLS, t as ANALYTICS_BASE } from "./chunks/api-urls-DWk43fu6.js";
2
+ import { r as getSessionContext, t as sendData } from "./chunks/send-data-DFZnsaL2.js";
3
3
  //#region src/web-vitals.ts
4
+ function webVitals(options = {}) {
5
+ return {
6
+ name: "web-vitals",
7
+ async setup(context) {
8
+ const tracker = new WebVitalsTracker({
9
+ ...options,
10
+ siteKey: context.siteKey,
11
+ baseUrl: context.baseUrl,
12
+ debug: context.debug,
13
+ trackHash: context.trackHash,
14
+ cookieless: context.isCookieless()
15
+ });
16
+ context.on("pageHide", ({ persisted }) => tracker.onPageHidden(persisted));
17
+ context.on("consentChange", ({ cookieless }) => tracker.setCookielessMode(cookieless));
18
+ await tracker.start();
19
+ return ({ discard }) => tracker.stop(discard);
20
+ }
21
+ };
22
+ }
4
23
  const METRIC_NAMES = /* @__PURE__ */ new Set([
5
24
  "CLS",
6
25
  "INP",
@@ -16,23 +35,31 @@ var WebVitalsTracker = class {
16
35
  flushing = false;
17
36
  initialUrl = "";
18
37
  session = null;
38
+ cookieless;
19
39
  constructor(options) {
20
40
  this.options = options;
21
41
  this.endpoint = `${resolveBaseUrl(options.baseUrl, ANALYTICS_BASE)}${URLS.vitals}`;
42
+ this.cookieless = options.cookieless ?? false;
43
+ }
44
+ setCookielessMode(cookieless) {
45
+ if (this.cookieless === cookieless) return;
46
+ this.cookieless = cookieless;
47
+ this.metrics.clear();
48
+ this.session = this.started ? getSessionContext(this.options.siteKey, cookieless) : null;
22
49
  }
23
50
  async start() {
24
51
  if (this.started || typeof window === "undefined") return;
25
52
  this.started = true;
26
53
  this.initialUrl = sanitizeUrl(window.location.href, this.options.trackHash ?? false);
27
- this.session = getSessionContext(this.options.siteKey);
28
- const mod = await (this.options.attribution ? import("web-vitals/attribution") : import("web-vitals"));
54
+ this.session = getSessionContext(this.options.siteKey, this.cookieless);
55
+ const vitals = this.options.attribution ? await import("web-vitals/attribution") : await import("web-vitals");
29
56
  if (!this.started) return;
30
57
  const changes = { reportAllChanges: true };
31
- mod.onCLS(this.onMetric, changes);
32
- mod.onINP(this.onMetric, changes);
33
- mod.onLCP(this.onMetric, changes);
34
- mod.onFCP(this.onMetric);
35
- mod.onTTFB(this.onMetric);
58
+ vitals.onCLS(this.onMetric, changes);
59
+ vitals.onINP(this.onMetric, changes);
60
+ vitals.onLCP(this.onMetric, changes);
61
+ vitals.onFCP(this.onMetric);
62
+ vitals.onTTFB(this.onMetric);
36
63
  }
37
64
  stop(discard = false) {
38
65
  if (!this.started) return;
@@ -49,7 +76,7 @@ var WebVitalsTracker = class {
49
76
  const name = metric.name;
50
77
  if (!METRIC_NAMES.has(name) || !Number.isFinite(metric.value) || metric.value < 0) return;
51
78
  const { id, rating, delta, navigationType } = metric;
52
- const attribution = "attribution" in metric && metric.attribution ? metric.attribution : void 0;
79
+ const attribution = this.options.attribution && "attribution" in metric && metric.attribution ? metric.attribution : void 0;
53
80
  this.metrics.set(name, {
54
81
  metric: name,
55
82
  value: metric.value,
@@ -67,7 +94,7 @@ var WebVitalsTracker = class {
67
94
  this.flushing = true;
68
95
  const batch = this.metrics;
69
96
  this.metrics = /* @__PURE__ */ new Map();
70
- const session = this.session ?? getSessionContext(this.options.siteKey);
97
+ const session = this.session ?? getSessionContext(this.options.siteKey, this.cookieless);
71
98
  let sent = false;
72
99
  try {
73
100
  sent = await sendData({
@@ -91,4 +118,4 @@ var WebVitalsTracker = class {
91
118
  }
92
119
  };
93
120
  //#endregion
94
- export { WebVitalsTracker as default };
121
+ export { WebVitalsTracker as default, webVitals };
package/package.json CHANGED
@@ -13,10 +13,10 @@
13
13
  "import": "./dist/index.js",
14
14
  "default": "./dist/index.js"
15
15
  },
16
- "./feature-flags": {
17
- "types": "./dist/feature-flags.d.ts",
18
- "import": "./dist/feature-flags.js",
19
- "default": "./dist/feature-flags.js"
16
+ "./outbound-links": {
17
+ "types": "./dist/outbound-links.d.ts",
18
+ "import": "./dist/outbound-links.js",
19
+ "default": "./dist/outbound-links.js"
20
20
  },
21
21
  "./replay": {
22
22
  "types": "./dist/replay.d.ts",
@@ -42,7 +42,7 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "version": "0.7.0",
45
+ "version": "0.8.0",
46
46
  "scripts": {
47
47
  "build": "tsdown && bun run check-size",
48
48
  "dev": "bun run build",
@@ -51,15 +51,14 @@
51
51
  "check-size": "node scripts/check-bundle-size.mjs"
52
52
  },
53
53
  "devDependencies": {
54
- "@rrweb/types": "^2.0.1",
55
- "@types/bun": "latest",
56
- "tsdown": "^0.22.3",
54
+ "@rrweb/types": "^2.1.1",
55
+ "@types/bun": "^1.4.0",
56
+ "tsdown": "^0.22.14",
57
57
  "typescript": "^6.0.3"
58
58
  },
59
59
  "dependencies": {
60
- "@rrweb/record": "^2.1.0",
61
- "@rrweb/rrweb-plugin-console-record": "^2.1.0",
62
- "@rrweb/rrweb-plugin-sequential-id-record": "^2.1.0",
63
- "web-vitals": "^6.0.0"
60
+ "@rrweb/record": "^2.1.1",
61
+ "@rrweb/rrweb-plugin-console-record": "^2.1.1",
62
+ "web-vitals": "^6.2.1"
64
63
  }
65
64
  }