@loggerjs/browser 0.0.2 → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -1,16 +1,20 @@
1
1
  export * from "@loggerjs/core";
2
2
  export * from "./broadcast-channel-transport.js";
3
3
  export * from "./http-transport.js";
4
+ export * from "./payload-transforms.js";
4
5
  export * from "./service-worker-transport.js";
5
6
  export * from "./websocket-transport.js";
6
7
  export * from "./indexeddb-offline-queue.js";
7
8
  export * from "./indexeddb-transport.js";
9
+ export * from "./offline-first-transport.js";
8
10
  export * from "./zip-export.js";
9
11
  export * from "./console-integration.js";
12
+ export * from "./context-propagation-integration.js";
10
13
  export * from "./error-integration.js";
11
14
  export * from "./fetch-integration.js";
12
15
  export * from "./xhr-integration.js";
13
16
  export * from "./framework-error-integration.js";
17
+ export * from "./framework-router-integrations.js";
14
18
  export * from "./reporting-integration.js";
15
19
  export * from "./router-integration.js";
16
20
  export * from "./runtime-host-integration.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { incrementLoggerMetaCounter, normalizeValue, safeJsonCodec, safeJsonStringify, toLevelValue } from "@loggerjs/core";
1
+ import { addContextProvider, applyPayloadTransforms, encodedPayloadToUint8Array, formatBaggage, formatTraceparent, incrementLoggerMetaCounter, normalizeValue, parseBaggage, parseTraceparent, recordToEvent, retryTransport, safeJsonCodec, safeJsonStringify, toLevelValue } from "@loggerjs/core";
2
2
  export * from "@loggerjs/core";
3
3
  //#region src/broadcast-channel-transport.ts
4
4
  let sourceSequence$1 = 0;
@@ -186,8 +186,9 @@ function browserHttpTransport(options) {
186
186
  let flushing = false;
187
187
  let replayingOffline = false;
188
188
  let lastContext;
189
- const headers = () => ({
190
- "content-type": codec.contentType,
189
+ const headers = (payloadHeaders, contentType = codec.contentType) => ({
190
+ "content-type": contentType,
191
+ ...payloadHeaders,
191
192
  ...options.headers
192
193
  });
193
194
  const clearTimer = () => {
@@ -268,33 +269,40 @@ function browserHttpTransport(options) {
268
269
  });
269
270
  if (!response.ok) throw new Error(`browserHttpTransport failed with status ${response.status}`);
270
271
  };
271
- const createOfflineEntry = (payload) => ({
272
+ const encodeTransformedPayload = async (batch) => {
273
+ return applyPayloadTransforms(codec.encode(batch), {
274
+ contentType: codec.contentType,
275
+ events: batch,
276
+ transport: options.name ?? "browser-http"
277
+ }, options.transformPayload);
278
+ };
279
+ const createOfflineEntry = (payload, payloadHeaders, contentType) => ({
272
280
  id: `${Date.now().toString(36)}-${(offlineEntrySeq++).toString(36)}`,
273
281
  url: options.url,
274
282
  method: options.method ?? "POST",
275
- headers: headers(),
283
+ headers: headers(payloadHeaders, contentType),
276
284
  body: payload,
277
285
  credentials: options.credentials,
278
286
  keepalive: options.keepalive ?? true,
279
287
  createdAt: Date.now()
280
288
  });
281
- const enqueueOfflinePayload = async (payload) => {
289
+ const enqueueOfflinePayload = async (payload, payloadHeaders, contentType) => {
282
290
  if (!offlineQueue) return false;
283
- await offlineQueue.enqueue(createOfflineEntry(payload));
291
+ await offlineQueue.enqueue(createOfflineEntry(payload, payloadHeaders, contentType));
284
292
  incrementLoggerMetaCounter("transport.offline.queued");
285
293
  return true;
286
294
  };
287
295
  const sendFetchBatch = async (batch) => {
288
296
  if (batch.length === 0) return;
289
- const payload = codec.encode(batch);
297
+ const transformed = await encodeTransformedPayload(batch);
290
298
  if (offlineQueue && typeof navigator !== "undefined" && navigator.onLine === false) {
291
- await enqueueOfflinePayload(payload);
299
+ await enqueueOfflinePayload(transformed.payload, transformed.headers, transformed.contentType);
292
300
  return;
293
301
  }
294
302
  try {
295
- await sendPayload(createOfflineEntry(payload));
303
+ await sendPayload(createOfflineEntry(transformed.payload, transformed.headers, transformed.contentType));
296
304
  } catch (error) {
297
- if (await enqueueOfflinePayload(payload)) return;
305
+ if (await enqueueOfflinePayload(transformed.payload, transformed.headers, transformed.contentType)) return;
298
306
  throw error;
299
307
  }
300
308
  };
@@ -330,14 +338,18 @@ function browserHttpTransport(options) {
330
338
  flushing = true;
331
339
  clearTimer();
332
340
  const batch = queue.splice(0, queue.length);
341
+ let pendingBatch = batch;
333
342
  try {
334
- let fetchBatch = batch;
335
- if (preferBeacon) {
343
+ if (preferBeacon && !options.transformPayload) {
336
344
  const beaconResult = sendBeaconBatch(batch);
337
345
  if (beaconResult.ok || beaconResult.remaining.length === 0) return;
338
- fetchBatch = beaconResult.remaining;
346
+ pendingBatch = beaconResult.remaining;
339
347
  }
340
- await sendFetchBatch(fetchBatch);
348
+ await sendFetchBatch(pendingBatch);
349
+ pendingBatch = [];
350
+ } catch (error) {
351
+ if (pendingBatch.length > 0) queue.unshift(...pendingBatch);
352
+ throw error;
341
353
  } finally {
342
354
  flushing = false;
343
355
  if (queue.length > 0) schedule();
@@ -393,6 +405,31 @@ function browserHttpTransport(options) {
393
405
  };
394
406
  }
395
407
  //#endregion
408
+ //#region src/payload-transforms.ts
409
+ async function compressWithStream(payload, format, streamFactory) {
410
+ const stream = (streamFactory ?? ((nextFormat) => {
411
+ if (typeof CompressionStream === "undefined") throw new Error("CompressionStream is not available in this browser");
412
+ return new CompressionStream(nextFormat);
413
+ }))(format);
414
+ const writer = stream.writable.getWriter();
415
+ await writer.write(Uint8Array.from(payload));
416
+ await writer.close();
417
+ return new Uint8Array(await new Response(stream.readable).arrayBuffer());
418
+ }
419
+ function browserCompressionPayloadTransform(options = {}) {
420
+ const format = options.format ?? "gzip";
421
+ return async (payload, context) => ({
422
+ payload: await (options.compress ? options.compress(encodedPayloadToUint8Array(payload), {
423
+ ...context,
424
+ format
425
+ }) : compressWithStream(encodedPayloadToUint8Array(payload), format, options.streamFactory)),
426
+ headers: {
427
+ "content-encoding": format,
428
+ ...options.headers
429
+ }
430
+ });
431
+ }
432
+ //#endregion
396
433
  //#region src/service-worker-transport.ts
397
434
  let sourceSequence = 0;
398
435
  function createSourceId() {
@@ -433,7 +470,7 @@ function browserServiceWorkerTransport(options = {}) {
433
470
  const mapBatch = options.mapBatch ?? defaultMapBatch;
434
471
  const queue = [];
435
472
  let readyWorker;
436
- let readyStarted = false;
473
+ let readyPromise;
437
474
  let lastContext;
438
475
  const reportError = (error, context, operation, droppedEvents = 0) => {
439
476
  try {
@@ -484,27 +521,35 @@ function browserServiceWorkerTransport(options = {}) {
484
521
  post(worker, item, context);
485
522
  }
486
523
  };
487
- const startReady = (context) => {
488
- if (target !== "ready" || readyStarted) return;
489
- readyStarted = true;
524
+ const dropQueued = (reason) => {
525
+ const pending = queue.splice(0);
526
+ for (const item of pending) reportDrop(item, reason);
527
+ return pending.reduce((total, item) => total + item.events.length, 0);
528
+ };
529
+ const waitForReady = (context) => {
530
+ if (currentWorker()) return Promise.resolve();
531
+ if (target !== "ready") return Promise.reject(/* @__PURE__ */ new Error("service worker controller is not available"));
532
+ if (readyPromise) return readyPromise;
490
533
  const container = options.serviceWorker ?? serviceWorkerContainer();
491
534
  if (!container?.ready) {
492
- reportError(/* @__PURE__ */ new Error("serviceWorker.ready is not available"), context, "ready");
493
- return;
535
+ const error = /* @__PURE__ */ new Error("serviceWorker.ready is not available");
536
+ reportError(error, context, "ready", dropQueued("ready"));
537
+ return Promise.reject(error);
494
538
  }
495
- container.ready.then((registration) => {
539
+ readyPromise = container.ready.then((registration) => {
496
540
  readyWorker = workerFromRegistration(registration);
497
- if (!readyWorker) {
498
- const pending = queue.splice(0);
499
- for (const item of pending) reportDrop(item, "unavailable");
500
- return;
501
- }
502
- drain(context);
541
+ if (!readyWorker) throw new Error("service worker registration has no active worker");
542
+ drain(context ?? lastContext);
503
543
  }).catch((error) => {
504
- const pending = queue.splice(0);
505
- for (const item of pending) reportDrop(item, "ready");
506
- reportError(error, context, "ready", pending.reduce((total, item) => total + item.events.length, 0));
544
+ readyPromise = void 0;
545
+ const droppedEvents = dropQueued("ready");
546
+ reportError(error, context ?? lastContext, "ready", droppedEvents);
547
+ throw error;
507
548
  });
549
+ return readyPromise;
550
+ };
551
+ const startReady = (context) => {
552
+ waitForReady(context).catch(() => {});
508
553
  };
509
554
  const enqueue = (item) => {
510
555
  if (queue.length >= maxQueueSize) {
@@ -538,6 +583,9 @@ function browserServiceWorkerTransport(options = {}) {
538
583
  queueSize() {
539
584
  return queue.length;
540
585
  },
586
+ ready() {
587
+ return waitForReady();
588
+ },
541
589
  log(event, context) {
542
590
  send({
543
591
  events: [event],
@@ -1330,6 +1378,14 @@ function indexedDbTransport(options = {}) {
1330
1378
  clearTimer();
1331
1379
  await withStore("readwrite", (store) => requestToPromise(store.clear()));
1332
1380
  },
1381
+ async remove(ids) {
1382
+ await flushPending();
1383
+ const items = typeof ids === "string" ? [ids] : ids;
1384
+ if (items.length === 0) return;
1385
+ await withStore("readwrite", async (store) => {
1386
+ for (const id of items) await requestToPromise(store.delete(id));
1387
+ });
1388
+ },
1333
1389
  async *query(queryOptions = {}) {
1334
1390
  await flushPending();
1335
1391
  const startedAt = nowMs$1();
@@ -1361,6 +1417,150 @@ function indexedDbTransport(options = {}) {
1361
1417
  };
1362
1418
  }
1363
1419
  //#endregion
1420
+ //#region src/offline-first-transport.ts
1421
+ function normalizeBatchSize(value) {
1422
+ if (value === void 0 || !Number.isFinite(value) || value <= 0) return 100;
1423
+ return Math.floor(value);
1424
+ }
1425
+ async function collectBatch(queue, replayBatchSize) {
1426
+ const events = [];
1427
+ for await (const event of queue.query({
1428
+ order: "asc",
1429
+ limit: replayBatchSize
1430
+ })) events.push(event);
1431
+ return events;
1432
+ }
1433
+ function isBrowserOnline(options) {
1434
+ if (options.online) return options.online();
1435
+ if (typeof navigator === "undefined") return true;
1436
+ return navigator.onLine !== false;
1437
+ }
1438
+ function offlineFirstTransport(remote, options = {}) {
1439
+ const name = options.name ?? `offline-first(${remote.name ?? "transport"})`;
1440
+ const replayBatchSize = normalizeBatchSize(options.replayBatchSize);
1441
+ const queue = options.queue ?? indexedDbTransport({
1442
+ dbName: "loggerjs-offline",
1443
+ flushIntervalMs: 0,
1444
+ name: `${name}:queue`,
1445
+ storeName: "offline-events",
1446
+ ...options.queueOptions
1447
+ });
1448
+ const reliableRemote = retryTransport(remote, {
1449
+ maxRetries: 2,
1450
+ retryBaseDelayMs: 250,
1451
+ retryMaxDelayMs: 5e3,
1452
+ ...options.retry,
1453
+ name: `${name}:remote`
1454
+ });
1455
+ let lastContext;
1456
+ let replayPromise;
1457
+ const replayContext = {
1458
+ loggerName: name,
1459
+ now: () => Date.now(),
1460
+ toEvent: recordToEvent,
1461
+ reportInternalError() {}
1462
+ };
1463
+ const contextForReplay = () => lastContext ?? replayContext;
1464
+ const reportInternalError = (error, operation) => {
1465
+ contextForReplay().reportInternalError(error, {
1466
+ phase: "transport",
1467
+ transport: name,
1468
+ operation
1469
+ });
1470
+ };
1471
+ const queueEvent = async (event, context, error) => {
1472
+ await queue.log(event, context);
1473
+ await queue.flush?.();
1474
+ incrementLoggerMetaCounter("transport.offline.queued");
1475
+ options.onQueued?.(event, error);
1476
+ };
1477
+ const sendRemoteBatch = async (events, context) => {
1478
+ await reliableRemote.logBatch?.([...events], context);
1479
+ };
1480
+ const sendOrQueue = async (event, context) => {
1481
+ lastContext = context;
1482
+ if (!isBrowserOnline(options)) {
1483
+ await queueEvent(event, context);
1484
+ return;
1485
+ }
1486
+ try {
1487
+ await reliableRemote.log?.(event, context);
1488
+ } catch (error) {
1489
+ incrementLoggerMetaCounter("transport.offline.remote.failed");
1490
+ await queueEvent(event, context, error);
1491
+ }
1492
+ };
1493
+ const replay = async () => {
1494
+ if (replayPromise) return replayPromise;
1495
+ replayPromise = (async () => {
1496
+ if (!isBrowserOnline(options)) return;
1497
+ const context = contextForReplay();
1498
+ await queue.flush?.();
1499
+ for (;;) {
1500
+ const batch = await collectBatch(queue, replayBatchSize);
1501
+ if (batch.length === 0) return;
1502
+ try {
1503
+ await sendRemoteBatch(batch, context);
1504
+ await queue.remove(batch.map((event) => event.id));
1505
+ incrementLoggerMetaCounter("transport.offline.replayed", batch.length);
1506
+ options.onReplayed?.(batch);
1507
+ } catch (error) {
1508
+ incrementLoggerMetaCounter("transport.offline.replay.failed");
1509
+ reportInternalError(error, "replay");
1510
+ throw error;
1511
+ }
1512
+ }
1513
+ })().finally(() => {
1514
+ replayPromise = void 0;
1515
+ });
1516
+ return replayPromise;
1517
+ };
1518
+ const onOnline = () => {
1519
+ replay().catch((error) => reportInternalError(error, "online-replay"));
1520
+ };
1521
+ if (options.replayOnOnline ?? true) globalThis.addEventListener?.("online", onOnline);
1522
+ return {
1523
+ name,
1524
+ minLevel: options.minLevel ?? remote.minLevel,
1525
+ queue,
1526
+ write(record, context) {
1527
+ return sendOrQueue(context.toEvent(record), context);
1528
+ },
1529
+ writeBatch(records, context) {
1530
+ return Promise.all(records.map((record) => sendOrQueue(context.toEvent(record), context))).then(() => void 0);
1531
+ },
1532
+ log(event, context) {
1533
+ if (options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel)) return;
1534
+ return sendOrQueue(event, context);
1535
+ },
1536
+ logBatch(events, context) {
1537
+ return Promise.all(events.map((event) => options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel) ? void 0 : sendOrQueue(event, context))).then(() => void 0);
1538
+ },
1539
+ replay,
1540
+ async flush() {
1541
+ await replay();
1542
+ await reliableRemote.flush?.();
1543
+ await queue.flush?.();
1544
+ },
1545
+ flushSync() {
1546
+ reliableRemote.flushSync?.();
1547
+ },
1548
+ async close() {
1549
+ globalThis.removeEventListener?.("online", onOnline);
1550
+ await replay();
1551
+ await reliableRemote.close?.();
1552
+ await queue.close?.();
1553
+ },
1554
+ async queuedCount() {
1555
+ await queue.flush?.();
1556
+ return queue.count?.();
1557
+ },
1558
+ async clearQueue() {
1559
+ await queue.clear?.();
1560
+ }
1561
+ };
1562
+ }
1563
+ //#endregion
1364
1564
  //#region src/zip-export.ts
1365
1565
  const ZIP_UTF8_FLAG = 2048;
1366
1566
  const ZIP_STORE_METHOD = 0;
@@ -1688,6 +1888,79 @@ function captureConsoleIntegration(options = {}) {
1688
1888
  };
1689
1889
  }
1690
1890
  //#endregion
1891
+ //#region src/context-propagation-integration.ts
1892
+ const defaultActionEvents = [
1893
+ "click",
1894
+ "input",
1895
+ "change",
1896
+ "submit"
1897
+ ];
1898
+ let fallbackIdSeq = 0;
1899
+ function defaultIdFactory() {
1900
+ const cryptoRandomUUID = globalThis.crypto?.randomUUID;
1901
+ if (cryptoRandomUUID) return cryptoRandomUUID.call(globalThis.crypto);
1902
+ return `${Date.now().toString(36)}-${(fallbackIdSeq++).toString(36)}`;
1903
+ }
1904
+ function resolveValue(value) {
1905
+ return typeof value === "function" ? value() : value;
1906
+ }
1907
+ function normalizeBaggage(value) {
1908
+ if (typeof value === "string") return parseBaggage(value);
1909
+ return value;
1910
+ }
1911
+ function actionTargetName(target) {
1912
+ const item = target;
1913
+ if (!item) return void 0;
1914
+ return item.id || item.name || item.tagName?.toLowerCase();
1915
+ }
1916
+ function browserContextPropagationIntegration(options = {}) {
1917
+ const actionEvents = options.actionEvents ?? defaultActionEvents;
1918
+ const actionTtlMs = Math.max(0, Math.floor(options.actionTtlMs ?? 5e3));
1919
+ const clock = options.clock ?? Date.now;
1920
+ const idFactory = options.idFactory ?? defaultIdFactory;
1921
+ let lastAction;
1922
+ return {
1923
+ name: "browser-context-propagation",
1924
+ setup() {
1925
+ const root = options.root ?? globalThis.document;
1926
+ const disposeProvider = addContextProvider(() => {
1927
+ const sessionId = resolveValue(options.sessionId);
1928
+ const requestId = options.requestId?.();
1929
+ const trace = resolveValue(options.trace) ?? parseTraceparent(resolveValue(options.traceparent));
1930
+ const baggage = normalizeBaggage(resolveValue(options.baggage)) ?? trace?.baggage;
1931
+ const traceparent = formatTraceparent(trace);
1932
+ const now = clock();
1933
+ const action = lastAction && now - lastAction.time <= actionTtlMs ? {
1934
+ actionId: lastAction.id,
1935
+ actionType: lastAction.type,
1936
+ actionTarget: lastAction.target
1937
+ } : void 0;
1938
+ return {
1939
+ sessionId,
1940
+ requestId,
1941
+ traceparent,
1942
+ baggage: formatBaggage(baggage),
1943
+ ...action
1944
+ };
1945
+ });
1946
+ if (!root?.addEventListener || !root.removeEventListener || actionEvents.length === 0) return disposeProvider;
1947
+ const onAction = (event) => {
1948
+ lastAction = {
1949
+ id: idFactory(),
1950
+ type: event.type,
1951
+ target: actionTargetName(event.target),
1952
+ time: clock()
1953
+ };
1954
+ };
1955
+ for (const event of actionEvents) root.addEventListener(event, onAction, true);
1956
+ return () => {
1957
+ for (const event of actionEvents) root.removeEventListener(event, onAction, true);
1958
+ disposeProvider();
1959
+ };
1960
+ }
1961
+ };
1962
+ }
1963
+ //#endregion
1691
1964
  //#region src/error-integration.ts
1692
1965
  function resourceInfo(target) {
1693
1966
  const element = target;
@@ -2098,6 +2371,86 @@ function captureFrameworkErrorsIntegration(options = {}) {
2098
2371
  };
2099
2372
  }
2100
2373
  //#endregion
2374
+ //#region src/framework-router-integrations.ts
2375
+ function routePath(input) {
2376
+ if (typeof input === "string") return input;
2377
+ if (input && typeof input === "object") {
2378
+ const route = input;
2379
+ if (typeof route.fullPath === "string") return route.fullPath;
2380
+ if (typeof route.pathname === "string") return route.pathname;
2381
+ if (typeof route.path === "string") return route.path;
2382
+ if (route.location) return routePath(route.location);
2383
+ }
2384
+ return "";
2385
+ }
2386
+ function emitRouteChange(api, framework, level, to, from, options) {
2387
+ const sanitize = options.sanitizeUrl;
2388
+ const toPath = sanitize ? sanitize(routePath(to)) : routePath(to);
2389
+ const fromPath = from === void 0 ? void 0 : sanitize ? sanitize(routePath(from)) : routePath(from);
2390
+ api.capture({
2391
+ level,
2392
+ message: `${framework} route ${toPath}`,
2393
+ props: { browser: {
2394
+ kind: "framework-route-change",
2395
+ framework,
2396
+ route: {
2397
+ to: toPath,
2398
+ from: fromPath,
2399
+ state: options.includeState ? normalizeValue(to, { maxDepth: 4 }) : void 0
2400
+ }
2401
+ } }
2402
+ });
2403
+ }
2404
+ function nextRouterIntegration(options) {
2405
+ const level = options.level ?? "info";
2406
+ return {
2407
+ name: "next-router",
2408
+ setup(api) {
2409
+ const router = options.router;
2410
+ if (!router.events?.on || !router.events.off) return;
2411
+ const onRoute = api.guard((url) => emitRouteChange(api, "next", level, url, router.asPath, options));
2412
+ router.events.on("routeChangeComplete", onRoute);
2413
+ router.events.on("hashChangeComplete", onRoute);
2414
+ return () => {
2415
+ router.events?.off?.("routeChangeComplete", onRoute);
2416
+ router.events?.off?.("hashChangeComplete", onRoute);
2417
+ };
2418
+ }
2419
+ };
2420
+ }
2421
+ function reactRouterIntegration(options) {
2422
+ const level = options.level ?? "info";
2423
+ return {
2424
+ name: "react-router",
2425
+ setup(api) {
2426
+ let previous = options.history.location;
2427
+ const dispose = options.history.listen?.(api.guard((update) => {
2428
+ const next = update?.location ?? update;
2429
+ emitRouteChange(api, "react-router", level, next, previous, options);
2430
+ previous = next;
2431
+ }));
2432
+ return typeof dispose === "function" ? dispose : void 0;
2433
+ }
2434
+ };
2435
+ }
2436
+ function vueRouterIntegration(options) {
2437
+ const level = options.level ?? "info";
2438
+ const framework = options.framework ?? "vue-router";
2439
+ return {
2440
+ name: framework,
2441
+ setup(api) {
2442
+ const dispose = options.router.afterEach?.(api.guard((to, from) => emitRouteChange(api, framework, level, to, from, options)));
2443
+ return typeof dispose === "function" ? dispose : void 0;
2444
+ }
2445
+ };
2446
+ }
2447
+ function nuxtRouterIntegration(options) {
2448
+ return vueRouterIntegration({
2449
+ ...options,
2450
+ framework: "nuxt"
2451
+ });
2452
+ }
2453
+ //#endregion
2101
2454
  //#region src/reporting-integration.ts
2102
2455
  const defaultReportTypes = [
2103
2456
  "csp-violation",
@@ -3114,6 +3467,6 @@ function pageLifecycleIntegration(options = {}) {
3114
3467
  };
3115
3468
  }
3116
3469
  //#endregion
3117
- export { browserBroadcastChannelTransport, browserHttpTransport, browserServiceWorkerTransport, browserWebSocketTransport, captureBrowserErrorsIntegration, captureConsoleIntegration, captureFetchIntegration, captureFrameworkErrorsIntegration, capturePerformanceIntegration, captureReportingIntegration, captureRouterIntegration, captureRuntimeHostIntegration, captureServiceWorkerIntegration, captureUserActionsIntegration, captureWebSocketIntegration, captureWebVitalsIntegration, captureXHRIntegration, createLogZipBlob, downloadBlob, exportLogsToZip, indexedDbBrowserHttpOfflineQueue, indexedDbTransport, memoryBrowserHttpOfflineQueue, normalizeBrowserPerformanceEntry, pageLifecycleIntegration };
3470
+ export { browserBroadcastChannelTransport, browserCompressionPayloadTransform, browserContextPropagationIntegration, browserHttpTransport, browserServiceWorkerTransport, browserWebSocketTransport, captureBrowserErrorsIntegration, captureConsoleIntegration, captureFetchIntegration, captureFrameworkErrorsIntegration, capturePerformanceIntegration, captureReportingIntegration, captureRouterIntegration, captureRuntimeHostIntegration, captureServiceWorkerIntegration, captureUserActionsIntegration, captureWebSocketIntegration, captureWebVitalsIntegration, captureXHRIntegration, createLogZipBlob, downloadBlob, exportLogsToZip, indexedDbBrowserHttpOfflineQueue, indexedDbTransport, memoryBrowserHttpOfflineQueue, nextRouterIntegration, normalizeBrowserPerformanceEntry, nuxtRouterIntegration, offlineFirstTransport, pageLifecycleIntegration, reactRouterIntegration, vueRouterIntegration };
3118
3471
 
3119
3472
  //# sourceMappingURL=index.js.map