@interfere/react 12.3.4 → 12.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.
Files changed (87) hide show
  1. package/README.md +6 -0
  2. package/dist/{api-DSUjs8zG.d.mts → api-BXjfYV5Z.d.mts} +1 -0
  3. package/dist/api-C8aG7li1.mjs +1 -0
  4. package/dist/{delivery-D9hzPDs9.mjs → delivery-D7hULClu.mjs} +1 -1
  5. package/dist/error-boundary.d.mts +1 -1
  6. package/dist/export-filter-CnyAaPct.mjs +1 -0
  7. package/dist/exporter-CCgTznZ0.mjs +1 -0
  8. package/dist/exporter-logs-BbzSiQJi.mjs +1 -0
  9. package/dist/{index-DpkTHU1a.d.mts → index-CPrYhbZR.d.mts} +1 -1
  10. package/dist/ingest-backoff-BdBT-jss.mjs +1 -0
  11. package/dist/internal/capture/capture-boundary.d.mts +1 -1
  12. package/dist/internal/capture/capture.d.mts +1 -1
  13. package/dist/internal/ingest-backoff/ingest-backoff.d.mts +3 -2
  14. package/dist/internal/ingest-backoff/ingest-backoff.mjs +1 -1
  15. package/dist/internal/kernel-registry.d.mts +1 -1
  16. package/dist/internal/kernel.d.mts +1 -1
  17. package/dist/internal/kernel.mjs +1 -1
  18. package/dist/internal/otel/export-filter.d.mts +2 -2
  19. package/dist/internal/otel/export-filter.mjs +1 -1
  20. package/dist/internal/otel/exporter-logs.mjs +1 -1
  21. package/dist/internal/otel/exporter.mjs +1 -1
  22. package/dist/internal/otel/index.d.mts +2 -2
  23. package/dist/internal/otel/index.mjs +1 -1
  24. package/dist/internal/otel/keepalive-chunks.d.mts +6 -0
  25. package/dist/internal/otel/keepalive-chunks.mjs +1 -0
  26. package/dist/internal/otel/page-scope-context-manager.d.mts +1 -1
  27. package/dist/internal/otel/page-scope-context-manager.mjs +1 -1
  28. package/dist/internal/otel/provider.d.mts +1 -1
  29. package/dist/internal/otel/provider.mjs +1 -1
  30. package/dist/internal/page-lifecycle/keepalive-budget.d.mts +2 -2
  31. package/dist/internal/page-lifecycle/keepalive-budget.mjs +1 -1
  32. package/dist/internal/plugins/plugin-runtime.d.mts +1 -1
  33. package/dist/internal/plugins/plugin-runtime.mjs +1 -1
  34. package/dist/internal/react-context.d.mts +1 -1
  35. package/dist/internal/react-dom-keys.d.mts +3 -0
  36. package/dist/internal/react-dom-keys.mjs +1 -0
  37. package/dist/internal/sw-queue-protocol.d.mts +2 -0
  38. package/dist/internal/sw-queue-protocol.mjs +1 -0
  39. package/dist/internal/sw-queue.mjs +1 -1
  40. package/dist/internal/version.mjs +1 -1
  41. package/dist/internal/wrapper-singleton.d.mts +1 -1
  42. package/dist/internal/wrapper-singleton.mjs +1 -1
  43. package/dist/keepalive-budget-BfoHXD04.mjs +1 -0
  44. package/dist/keepalive-chunks-BZv3PhHT.mjs +1 -0
  45. package/dist/kernel-zu11DwyQ.mjs +1 -0
  46. package/dist/msw-C0yLYJU2.mjs +255 -0
  47. package/dist/page-scope-context-manager-Bs-m4fv7.mjs +1 -0
  48. package/dist/{page-scope-context-manager-r92ZMJok.d.mts → page-scope-context-manager-DUhBvuAz.d.mts} +2 -2
  49. package/dist/{plugin-runtime-DSj0FM1Q.mjs → plugin-runtime-DgB1_Xc5.mjs} +1 -1
  50. package/dist/plugins/device.d.mts +1 -1
  51. package/dist/plugins/errors.d.mts +1 -1
  52. package/dist/plugins/lib/loader.d.mts +1 -1
  53. package/dist/plugins/lib/types.d.mts +1 -1
  54. package/dist/plugins/logs.d.mts +1 -1
  55. package/dist/plugins/page-events.d.mts +1 -1
  56. package/dist/plugins/rage-clicks.d.mts +1 -1
  57. package/dist/plugins/replay/index.d.mts +1 -1
  58. package/dist/plugins/replay/index.mjs +1 -1
  59. package/dist/plugins/replay/upload/delivery.d.mts +1 -1
  60. package/dist/plugins/replay/upload/delivery.mjs +1 -1
  61. package/dist/{provider-D4QjZp3L.d.mts → provider-BMMGZWyS.d.mts} +5 -4
  62. package/dist/provider-DwCQ_vj0.mjs +1 -0
  63. package/dist/{provider-cUByhzgv.d.mts → provider-Dy0mVCx5.d.mts} +4 -2
  64. package/dist/provider.d.mts +1 -1
  65. package/dist/react-dom-keys-BIJuLkQR.mjs +1 -0
  66. package/dist/react-error-handler.d.mts +1 -1
  67. package/dist/{session-retry-TrzzihIM.mjs → session-retry-Dgkk0yui.mjs} +1 -1
  68. package/dist/sw-queue-protocol-DnTSOWxy.mjs +1 -0
  69. package/dist/sw-queue-protocol-DqP1EQtQ.d.mts +22 -0
  70. package/dist/tracking/api.d.mts +1 -1
  71. package/dist/tracking/api.mjs +1 -1
  72. package/dist/tracking/lifecycle.fixture.d.mts +73 -0
  73. package/dist/tracking/lifecycle.fixture.mjs +1 -0
  74. package/dist/tracking/registration.fixture.d.mts +1 -1
  75. package/dist/tracking/registration.fixture.mjs +1 -255
  76. package/dist/tracking/session-retry.mjs +1 -1
  77. package/dist/{version-DusHm2Q4.mjs → version-CtEAnX65.mjs} +1 -1
  78. package/package.json +3 -4
  79. package/dist/api-DvHT4Dyw.mjs +0 -1
  80. package/dist/export-filter-Cixywxpu.mjs +0 -1
  81. package/dist/exporter-De0h9YP5.mjs +0 -1
  82. package/dist/exporter-logs-DS2AXWnV.mjs +0 -1
  83. package/dist/ingest-backoff-B1OeEV3h.mjs +0 -1
  84. package/dist/keepalive-budget-DeafGnVZ.mjs +0 -1
  85. package/dist/kernel-BVG-7Zau.mjs +0 -1
  86. package/dist/page-scope-context-manager-DhArvVJ_.mjs +0 -1
  87. package/dist/provider-CElaujE6.mjs +0 -1
@@ -0,0 +1 @@
1
+ import{ROOT_CONTEXT,trace}from"@opentelemetry/api";import{StackContextManager}from"@opentelemetry/sdk-trace-web";var PageScopeContextManager=class extends StackContextManager{pageScope=ROOT_CONTEXT;pageSpans=new WeakSet;pageScopeSetAtMs=0;rotator=null;maxAgeMs=1/0;rotating=!1;setPageScope(ctx){this.pageScope=ctx,this.pageScopeSetAtMs=Date.now();let span=trace.getSpan(ctx);span&&this.pageSpans.add(span)}setRotation(rotator,maxAgeMs){this.rotator=rotator,this.maxAgeMs=maxAgeMs}active(){let ctx=super.active(),span=trace.getSpan(ctx);if(span&&!this.pageSpans.has(span))return ctx;if(this.pageScope!==ROOT_CONTEXT&&this.rotator&&!this.rotating&&Date.now()-this.pageScopeSetAtMs>this.maxAgeMs){this.rotating=!0;try{this.setPageScope(this.rotator(this.pageScope))}finally{this.rotating=!1}}if(ctx===ROOT_CONTEXT)return this.pageScope;let pageSpan=trace.getSpan(this.pageScope);return pageSpan?trace.setSpan(ctx,pageSpan):ctx}};export{PageScopeContextManager as t};
@@ -1,8 +1,8 @@
1
1
  import { Context } from "@opentelemetry/api";
2
- import { ZoneContextManager } from "@opentelemetry/context-zone";
2
+ import { StackContextManager } from "@opentelemetry/sdk-trace-web";
3
3
  //#region src/internal/otel/page-scope-context-manager.d.ts
4
4
  type PageScopeRotator = (previous: Context) => Context;
5
- declare class PageScopeContextManager extends ZoneContextManager {
5
+ declare class PageScopeContextManager extends StackContextManager {
6
6
  private pageScope;
7
7
  private readonly pageSpans;
8
8
  private pageScopeSetAtMs;
@@ -1 +1 @@
1
- import{t as createLogger}from"./log-D6Ht--tv.mjs";import{t as devicePlugin}from"./device-6T3DYkLD.mjs";import{t as errorsPlugin}from"./errors-B8XYW4Q7.mjs";import{n as loadPlugin,r as resolveFeatures}from"./loader-CZ-5Z5A5.mjs";import{a as resolveGrantedConsent,i as isConsentAllowed,n as getPluginConsentCategory,r as hasConsentChanged}from"./consent-COUmLJLD.mjs";import{PLUGIN_MANIFEST}from"@interfere/types/sdk/plugins/manifest";const log=createLogger(`plugin-runtime`);var PluginRuntime=class{activeCleanups=new Map;activations=new Map;features=resolveFeatures();pluginConfigListeners=new Map;remoteConfig={};remoteConfigSettled=!1;consentState=null;configSettled=!1;replayConfig={};pageEventsConfig={};syncVersion=0;disposed=!1;context;hasInitialConsent;constructor(context,consent,remoteConfig={}){this.context=context,this.hasInitialConsent=consent!==void 0,this.consentState=consent===void 0?null:resolveGrantedConsent(consent),this.configSettled=this.hasInitialConsent,this.remoteConfig=remoteConfig}getConsent(){return this.consentState}getReplayConfig(){return this.replayConfig}isInteractionCaptureEnabled(){return this.pageEventsConfig.interactions!==!1}applyProviderConfig(overrides,consent){let pageEvents=overrides?.pageEvents,replay=overrides?.replay;this.features=resolveFeatures(overrides),this.pageEventsConfig=typeof pageEvents==`object`?pageEvents:{},this.replayConfig=typeof replay==`object`?replay:{},consent===void 0?this.hasInitialConsent||(this.consentState=null):this.consentState=resolveGrantedConsent(consent),this.configSettled=!0,this.sync()}setConsent(nextConsent){let nextState=resolveGrantedConsent(nextConsent);(!this.configSettled||hasConsentChanged(this.consentState,nextState))&&(this.consentState=nextState,this.configSettled=!0,this.sync())}resetConsent(){(!this.configSettled||hasConsentChanged(this.consentState,null))&&(this.consentState=null,this.configSettled=!0,this.sync())}applyRemoteConfig(config){this.remoteConfig=config,this.remoteConfigSettled=!0,this.emitPluginConfigState(),this.sync()}applyRemoteConfigDefaults(){this.remoteConfigSettled=!0,this.emitPluginConfigState(),this.sync()}start(){for(let[key,plugin]of[[`errors`,errorsPlugin],[`device`,devicePlugin]])if(this.shouldEnablePlugin(key)){let cleanup=plugin.setup(this.context);cleanup&&this.activeCleanups.set(key,cleanup)}this.sync()}async dispose(){this.disposed=!0,this.syncVersion+=1;for(let key of this.activeCleanups.keys())this.deactivate(key,`dispose`);await Promise.allSettled(this.activations.values())}shouldEnablePlugin(key){let category=getPluginConsentCategory(key);return category!==`necessary`&&!this.configSettled?!1:this.features[key]&&this.remoteConfig[key]!==!1&&isConsentAllowed(category,this.consentState)}getPluginConfigState(key){return this.remoteConfigSettled?this.remoteConfig[key]===!1?`disabled`:`enabled`:`pending`}subscribePluginConfigState(key,listener){let listeners=this.pluginConfigListeners.get(key)??new Set;return listeners.add(listener),this.pluginConfigListeners.set(key,listeners),(()=>{listeners.delete(listener),listeners.size===0&&this.pluginConfigListeners.delete(key)})}emitPluginConfigState(){for(let[key,listeners]of this.pluginConfigListeners){let state=this.getPluginConfigState(key);for(let listener of listeners)listener(state)}}teardownReason(key){let category=getPluginConsentCategory(key);return isConsentAllowed(category,this.consentState)?`disabled`:`consent-revoked`}deactivate(key,reason){let cleanup=this.activeCleanups.get(key);if(cleanup){try{cleanup(reason)}catch{log.warn(`cleanup failed for %s`,key)}this.activeCleanups.delete(key)}}async activate(key){if(this.activeCleanups.has(key)||!this.shouldEnablePlugin(key))return;let version=this.syncVersion,cleanup=await loadPlugin(key,this.context);if(cleanup){if(version!==this.syncVersion||!this.shouldEnablePlugin(key)){cleanup(this.teardownReason(key));return}this.activeCleanups.set(key,cleanup)}}sync(){if(!this.disposed){this.syncVersion+=1;for(let plugin of PLUGIN_MANIFEST){if(this.shouldEnablePlugin(plugin.name)){if(plugin.name===`errors`){if(!this.activeCleanups.has(`errors`)){let cleanup=errorsPlugin.setup(this.context);cleanup&&this.activeCleanups.set(`errors`,cleanup)}continue}let previous=this.activations.get(plugin.name);this.activations.set(plugin.name,(async()=>{await previous;try{await this.activate(plugin.name)}catch{log.warn(`non-critical plugin loading failed`)}})());continue}this.deactivate(plugin.name,this.teardownReason(plugin.name))}}}};export{PluginRuntime as t};
1
+ import{t as createLogger}from"./log-D6Ht--tv.mjs";import{t as devicePlugin}from"./device-6T3DYkLD.mjs";import{t as errorsPlugin}from"./errors-B8XYW4Q7.mjs";import{n as loadPlugin,r as resolveFeatures}from"./loader-CZ-5Z5A5.mjs";import{a as resolveGrantedConsent,i as isConsentAllowed,n as getPluginConsentCategory,r as hasConsentChanged}from"./consent-COUmLJLD.mjs";import{PLUGIN_MANIFEST}from"@interfere/types/sdk/plugins/manifest";const log=createLogger(`plugin-runtime`);var PluginRuntime=class{activeCleanups=new Map;activations=new Map;features=resolveFeatures();pluginConfigListeners=new Map;remoteConfig={};remoteConfigSettled=!1;consentState=null;configSettled=!1;replayConfig={};pageEventsConfig={};syncVersion=0;disposed=!1;context;hasInitialConsent;constructor(context,consent,remoteConfig={}){this.context=context,this.hasInitialConsent=consent!==void 0,this.consentState=consent===void 0?null:resolveGrantedConsent(consent),this.configSettled=this.hasInitialConsent,this.remoteConfig=remoteConfig}getConsent(){return this.consentState}getReplayConfig(){return this.replayConfig}isInteractionCaptureEnabled(){return this.pageEventsConfig.interactions!==!1}applyProviderConfig(overrides,consent){let pageEvents=overrides?.pageEvents,replay=overrides?.replay;this.features=resolveFeatures(overrides),this.pageEventsConfig=typeof pageEvents==`object`?pageEvents:{},this.replayConfig=typeof replay==`object`?replay:{},consent===void 0?this.hasInitialConsent||(this.consentState=null):this.consentState=resolveGrantedConsent(consent),this.configSettled=!0,this.sync()}setConsent(nextConsent){let nextState=resolveGrantedConsent(nextConsent);(!this.configSettled||hasConsentChanged(this.consentState,nextState))&&(this.consentState=nextState,this.configSettled=!0,this.sync())}resetConsent(){(!this.configSettled||hasConsentChanged(this.consentState,null))&&(this.consentState=null,this.configSettled=!0,this.sync())}applyRemoteConfig(config){this.remoteConfig=config,this.remoteConfigSettled=!0,this.emitPluginConfigState(),this.sync()}applyRemoteConfigDefaults(){this.remoteConfigSettled=!0,this.emitPluginConfigState(),this.sync()}start(){for(let[key,plugin]of[[`errors`,errorsPlugin],[`device`,devicePlugin]])if(this.shouldEnablePlugin(key)){let cleanup=plugin.setup(this.context);cleanup&&this.activeCleanups.set(key,cleanup)}this.sync()}async dispose(){this.disposed=!0,this.syncVersion+=1;for(let key of this.activeCleanups.keys())this.deactivate(key,`dispose`);await Promise.allSettled(this.activations.values())}shouldEnablePlugin(key){if(this.disposed)return!1;let category=getPluginConsentCategory(key);return category!==`necessary`&&!this.configSettled?!1:this.features[key]&&this.remoteConfig[key]!==!1&&isConsentAllowed(category,this.consentState)}getPluginConfigState(key){return this.remoteConfigSettled?this.remoteConfig[key]===!1?`disabled`:`enabled`:`pending`}subscribePluginConfigState(key,listener){let listeners=this.pluginConfigListeners.get(key)??new Set;return listeners.add(listener),this.pluginConfigListeners.set(key,listeners),(()=>{listeners.delete(listener),listeners.size===0&&this.pluginConfigListeners.delete(key)})}emitPluginConfigState(){for(let[key,listeners]of this.pluginConfigListeners){let state=this.getPluginConfigState(key);for(let listener of listeners)listener(state)}}teardownReason(key){let category=getPluginConsentCategory(key);return isConsentAllowed(category,this.consentState)?`disabled`:`consent-revoked`}deactivate(key,reason){let cleanup=this.activeCleanups.get(key);if(cleanup){try{cleanup(reason)}catch{log.warn(`cleanup failed for %s`,key)}this.activeCleanups.delete(key)}}async activate(key){if(this.activeCleanups.has(key)||!this.shouldEnablePlugin(key))return;let version=this.syncVersion,cleanup=await loadPlugin(key,this.context);if(cleanup){if(version!==this.syncVersion||!this.shouldEnablePlugin(key)){cleanup(this.teardownReason(key));return}this.activeCleanups.set(key,cleanup)}}sync(){if(!this.disposed){this.syncVersion+=1;for(let plugin of PLUGIN_MANIFEST){if(this.shouldEnablePlugin(plugin.name)){if(plugin.name===`errors`){if(!this.activeCleanups.has(`errors`)){let cleanup=errorsPlugin.setup(this.context);cleanup&&this.activeCleanups.set(`errors`,cleanup)}continue}let previous=this.activations.get(plugin.name);this.activations.set(plugin.name,(async()=>{await previous;try{await this.activate(plugin.name)}catch{log.warn(`non-critical plugin loading failed`)}})());continue}this.deactivate(plugin.name,this.teardownReason(plugin.name))}}}};export{PluginRuntime as t};
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/device.d.ts
3
3
  declare const devicePlugin: Plugin;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/errors.d.ts
3
3
  declare const errorsPlugin: Plugin;
4
4
  //#endregion
@@ -1,2 +1,2 @@
1
- import { S as resolveFeatures, b as PluginOverrides, x as loadPlugin, y as LOADERS } from "../../provider-D4QjZp3L.mjs";
1
+ import { S as resolveFeatures, b as PluginOverrides, x as loadPlugin, y as LOADERS } from "../../provider-BMMGZWyS.mjs";
2
2
  export { LOADERS, PluginOverrides, loadPlugin, resolveFeatures };
@@ -1,2 +1,2 @@
1
- import { C as Plugin, D as PluginTeardownReason, E as PluginContext, T as PluginConfigState, w as PluginCleanup } from "../../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin, D as PluginTeardownReason, E as PluginContext, T as PluginConfigState, w as PluginCleanup } from "../../provider-BMMGZWyS.mjs";
2
2
  export { Plugin, PluginCleanup, PluginConfigState, PluginContext, PluginTeardownReason };
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/logs.d.ts
3
3
  /**
4
4
  * Subscribes to the central console patch so string-only console calls
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/page-events.d.ts
3
3
  declare const pageEventsPlugin: Plugin;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/rage-clicks.d.ts
3
3
  declare const rageClicksPlugin: Plugin;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { C as Plugin } from "../../provider-D4QjZp3L.mjs";
1
+ import { C as Plugin } from "../../provider-BMMGZWyS.mjs";
2
2
  //#region src/plugins/replay/index.d.ts
3
3
  declare const replayPlugin: Plugin;
4
4
  //#endregion
@@ -1 +1 @@
1
- import{t as createLogger}from"../../log-D6Ht--tv.mjs";import{i as onPageUnloading}from"../../page-lifecycle-rJEJNdKj.mjs";import{r as resolveTargets}from"../../config-VOyDjqS7.mjs";import{i as toRecordOptions}from"../../config-DapTbKhs.mjs";import{n as splitReplayEvents,r as toReplayChunkPayload}from"../../chunking-qZffPbyY.mjs";import{t as createReplayBuffer}from"../../buffer-BRn_kSm-.mjs";import{t as createCompressor}from"../../compressor-host-CrKngamF.mjs";import{n as deliverChunk,t as REPLAY_TRACER_NAME}from"../../delivery-D9hzPDs9.mjs";import{t as startReplayRecorder}from"../../recorder-C36qxD3q.mjs";import{t as redactReplayEvent}from"../../redact-urls-CwFod9d4.mjs";import{t as createSegmentSequence}from"../../sequence-B4dYChb0.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{EventType}from"@rrweb/types";const log=createLogger(`replay`);function isBrowserApiRejection(error){return Object.prototype.toString.call(error)===`[object DOMException]`}const replayPlugin={name:`replay`,setup(ctx){let targets=resolveTargets(),recorder=null,flushTimer=null,unsubscribeConfig=null,unsubscribeUnloading=null,unsubscribePause=null,unsubscribeResume=null,unsubscribeException=null,isPaused=!1,startup=new AbortController,compressor=createCompressor(),windowId=ctx.getWindowId(),sequence=createSegmentSequence(windowId),consecutiveFailures=0,recorderFaults=0,halted=!1;function halt(reason,detail){halted||(halted=!0,ctx.getTracer(REPLAY_TRACER_NAME).startSpan(`replay.halt`,{attributes:omitUndefined({"replay.halt.reason":reason,"replay.halt.detail":detail,"replay.halt.recorder_faults":recorderFaults})}).end(),startup.abort(),clearFlushTimer(),recorder?.stop(),recorder=null)}function clearFlushTimer(){flushTimer&&=(clearInterval(flushTimer),null)}function armFlushTimer(){clearFlushTimer(),flushTimer=setInterval(()=>{clearFlushTimer(),flushTimer=setInterval(flush,1e4),flush()},2e3)}function handleResult(result){if(result===`ok`){consecutiveFailures=0;return}if(result===`skipped`){log.warn(`replay chunk rejected as a segment conflict; skipping it`),consecutiveFailures=0;return}if(result===`fatal`){log.warn(`replay halted: upload rejected`),halt(`upload-rejected`);return}consecutiveFailures+=1,consecutiveFailures>=3&&(log.warn(`replay halted after %d consecutive upload failures`,consecutiveFailures),halt(`upload-failed`))}function handleRecorderFault(error){if(isBrowserApiRejection(error)){log.debug(`recorder passed through a browser API rejection: %s`,error instanceof Error?error.name:`DOMException`);return}recorderFaults+=1,!(recorderFaults>10)&&(log.warn(`recorder fault: %s`,error instanceof Error?error.constructor.name:`UnknownError`),recorderFaults===10&&(log.warn(`replay halted after %d recorder faults`,10),flush(),halt(`recorder-faults`,error instanceof Error?error.constructor.name:`UnknownError`)))}let buffer=createReplayBuffer({onSoftLimit:flush,softLimitBytes:4194304});function flush(opts){if(halted||ctx.getPluginConfigState(`replay`)!==`enabled`)return;let drained=buffer.drain();if(drained.length===0)return;let{chunks,droppedEventBytes}=splitReplayEvents(drained);for(let bytes of droppedEventBytes)log.warn(`dropping replay event of ~%d bytes: too large to upload`,bytes);for(let group of chunks)sendChunk(toReplayChunkPayload(group),opts?.unload??!1,opts?.trigger)}async function sendChunk(payload,unload,trigger){try{handleResult(await deliverChunk({target:targets.ingest,chunk:{segmentId:sequence.take(),windowId},compressor,ctx,payload,trigger,unload}))}catch(error){log.warn(`replay chunk dropped: %s`,error instanceof Error?error.constructor.name:`UnknownError`),handleResult(`retryable`)}}let pauseRecording=reason=>{isPaused||(isPaused=!0,recorder?.stop(),flush(reason===`hidden`?{unload:!0}:void 0))},snapshotWhilePaused=reason=>{isPaused&&!halted&&recorder?.start()&&(recorder.addCustomEvent(`interfere.paused-exception-snapshot`,{reason}),recorder.stop(),flush({trigger:`exception`}))},resumeRecording=()=>{isPaused&&(isPaused=!1,recorder?.start(),armFlushTimer())},recordOptions=toRecordOptions(ctx.getReplayConfig(),ctx.privacyPolicy);return(async()=>{if(recorder=await startReplayRecorder({onEvent:(event,isCheckout)=>{startup.signal.aborted||(isCheckout&&event.type===EventType.Meta&&flush(),redactReplayEvent(event,ctx.redactUrl),buffer.push(event))},onFault:handleRecorderFault,recordOptions,signal:startup.signal}),startup.signal.aborted){recorder?.stop(),recorder=null;return}recorder&&(unsubscribeConfig=ctx.subscribePluginConfigState(`replay`,state=>{state===`enabled`&&flush()}),armFlushTimer(),unsubscribeUnloading=onPageUnloading(()=>{flush({unload:!0})}),unsubscribePause=ctx.onSessionPause(pauseRecording),unsubscribeResume=ctx.onSessionResume(resumeRecording),unsubscribeException=ctx.onSessionExceptionWhilePaused(snapshotWhilePaused),log.debug(`recording started`))})().catch(error=>{let detail=error instanceof Error?error.constructor.name:`UnknownError`;log.warn(`replay initialization failed: %s`,detail),halt(`init-failed`,detail)}),reason=>{reason===`consent-revoked`?(buffer.drain(),log.debug(`replay buffer discarded: consent revoked`)):flush(),startup.abort(),recorder?.stop(),clearFlushTimer(),unsubscribeConfig?.(),unsubscribeUnloading?.(),unsubscribePause?.(),unsubscribeResume?.(),unsubscribeException?.(),compressor.dispose()}}};export{replayPlugin as default};
1
+ import{t as createLogger}from"../../log-D6Ht--tv.mjs";import{i as onPageUnloading}from"../../page-lifecycle-rJEJNdKj.mjs";import{r as resolveTargets}from"../../config-VOyDjqS7.mjs";import{i as toRecordOptions}from"../../config-DapTbKhs.mjs";import{n as splitReplayEvents,r as toReplayChunkPayload}from"../../chunking-qZffPbyY.mjs";import{t as createReplayBuffer}from"../../buffer-BRn_kSm-.mjs";import{t as createCompressor}from"../../compressor-host-CrKngamF.mjs";import{n as deliverChunk,t as REPLAY_TRACER_NAME}from"../../delivery-D7hULClu.mjs";import{t as startReplayRecorder}from"../../recorder-C36qxD3q.mjs";import{t as redactReplayEvent}from"../../redact-urls-CwFod9d4.mjs";import{t as createSegmentSequence}from"../../sequence-B4dYChb0.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{EventType}from"@rrweb/types";const log=createLogger(`replay`);function isBrowserApiRejection(error){return Object.prototype.toString.call(error)===`[object DOMException]`}const replayPlugin={name:`replay`,setup(ctx){let targets=resolveTargets(),recorder=null,flushTimer=null,unsubscribeConfig=null,unsubscribeUnloading=null,unsubscribePause=null,unsubscribeResume=null,unsubscribeException=null,isPaused=!1,startup=new AbortController,compressor=createCompressor(),windowId=ctx.getWindowId(),sequence=createSegmentSequence(windowId),consecutiveFailures=0,recorderFaults=0,halted=!1;function halt(reason,detail){halted||(halted=!0,ctx.getTracer(REPLAY_TRACER_NAME).startSpan(`replay.halt`,{attributes:omitUndefined({"replay.halt.reason":reason,"replay.halt.detail":detail,"replay.halt.recorder_faults":recorderFaults})}).end(),startup.abort(),clearFlushTimer(),recorder?.stop(),recorder=null)}function clearFlushTimer(){flushTimer&&=(clearInterval(flushTimer),null)}function armFlushTimer(){clearFlushTimer(),flushTimer=setInterval(()=>{clearFlushTimer(),flushTimer=setInterval(flush,1e4),flush()},2e3)}function handleResult(result){if(result===`ok`){consecutiveFailures=0;return}if(result===`skipped`){log.warn(`replay chunk rejected as a segment conflict; skipping it`),consecutiveFailures=0;return}if(result===`fatal`){log.warn(`replay halted: upload rejected`),halt(`upload-rejected`);return}consecutiveFailures+=1,consecutiveFailures>=3&&(log.warn(`replay halted after %d consecutive upload failures`,consecutiveFailures),halt(`upload-failed`))}function handleRecorderFault(error){if(isBrowserApiRejection(error)){log.debug(`recorder passed through a browser API rejection: %s`,error instanceof Error?error.name:`DOMException`);return}recorderFaults+=1,!(recorderFaults>10)&&(log.warn(`recorder fault: %s`,error instanceof Error?error.constructor.name:`UnknownError`),recorderFaults===10&&(log.warn(`replay halted after %d recorder faults`,10),flush(),halt(`recorder-faults`,error instanceof Error?error.constructor.name:`UnknownError`)))}let buffer=createReplayBuffer({onSoftLimit:flush,softLimitBytes:4194304});function flush(opts){if(halted||ctx.getPluginConfigState(`replay`)!==`enabled`)return;let drained=buffer.drain();if(drained.length===0)return;let{chunks,droppedEventBytes}=splitReplayEvents(drained);for(let bytes of droppedEventBytes)log.warn(`dropping replay event of ~%d bytes: too large to upload`,bytes);for(let group of chunks)sendChunk(toReplayChunkPayload(group),opts?.unload??!1,opts?.trigger)}async function sendChunk(payload,unload,trigger){try{handleResult(await deliverChunk({target:targets.ingest,chunk:{segmentId:sequence.take(),windowId},compressor,ctx,payload,trigger,unload}))}catch(error){log.warn(`replay chunk dropped: %s`,error instanceof Error?error.constructor.name:`UnknownError`),handleResult(`retryable`)}}let pauseRecording=reason=>{isPaused||(isPaused=!0,recorder?.stop(),flush(reason===`hidden`?{unload:!0}:void 0))},snapshotWhilePaused=reason=>{isPaused&&!halted&&recorder?.start()&&(recorder.addCustomEvent(`interfere.paused-exception-snapshot`,{reason}),recorder.stop(),flush({trigger:`exception`}))},resumeRecording=()=>{isPaused&&(isPaused=!1,recorder?.start(),armFlushTimer())},recordOptions=toRecordOptions(ctx.getReplayConfig(),ctx.privacyPolicy);return(async()=>{if(recorder=await startReplayRecorder({onEvent:(event,isCheckout)=>{startup.signal.aborted||(isCheckout&&event.type===EventType.Meta&&flush(),redactReplayEvent(event,ctx.redactUrl),buffer.push(event))},onFault:handleRecorderFault,recordOptions,signal:startup.signal}),startup.signal.aborted){recorder?.stop(),recorder=null;return}recorder&&(unsubscribeConfig=ctx.subscribePluginConfigState(`replay`,state=>{state===`enabled`&&flush()}),armFlushTimer(),unsubscribeUnloading=onPageUnloading(()=>{flush({unload:!0})}),unsubscribePause=ctx.onSessionPause(pauseRecording),unsubscribeResume=ctx.onSessionResume(resumeRecording),unsubscribeException=ctx.onSessionExceptionWhilePaused(snapshotWhilePaused),log.debug(`recording started`))})().catch(error=>{let detail=error instanceof Error?error.constructor.name:`UnknownError`;log.warn(`replay initialization failed: %s`,detail),halt(`init-failed`,detail)}),reason=>{reason===`consent-revoked`?(buffer.drain(),log.debug(`replay buffer discarded: consent revoked`)):flush(),startup.abort(),recorder?.stop(),clearFlushTimer(),unsubscribeConfig?.(),unsubscribeUnloading?.(),unsubscribePause?.(),unsubscribeResume?.(),unsubscribeException?.(),compressor.dispose()}}};export{replayPlugin as default};
@@ -1,4 +1,4 @@
1
- import { E as PluginContext } from "../../../provider-D4QjZp3L.mjs";
1
+ import { E as PluginContext } from "../../../provider-BMMGZWyS.mjs";
2
2
  import { r as resolveTargets } from "../../../config-BTWtCcDP.mjs";
3
3
  import { n as ReplayChunkPayload } from "../../../chunking-OfmdRxfq.mjs";
4
4
  import { t as Compressor } from "../../../compressor-host-D3At2PKg.mjs";
@@ -1 +1 @@
1
- import{n as deliverChunk,t as REPLAY_TRACER_NAME}from"../../../delivery-D9hzPDs9.mjs";export{REPLAY_TRACER_NAME,deliverChunk};
1
+ import{n as deliverChunk,t as REPLAY_TRACER_NAME}from"../../../delivery-D7hULClu.mjs";export{REPLAY_TRACER_NAME,deliverChunk};
@@ -2,10 +2,10 @@ import { c as SessionResumeReason, s as SessionPauseReason } from "./activity-CS
2
2
  import { i as PrivacyPolicy, r as PrivacyOptions } from "./privacy-CPKosXDP.mjs";
3
3
  import { a as ReplayOption, i as ReplayConfig } from "./config-Dyc09HCZ.mjs";
4
4
  import { n as PageEventsOption } from "./page-events-config-CiJvdAaJ.mjs";
5
- import { t as SessionTracker } from "./api-DSUjs8zG.mjs";
5
+ import { t as SessionTracker } from "./api-BXjfYV5Z.mjs";
6
6
  import { n as CaptureFailedRequestsOption, t as BundledInstrumentations } from "./instrumentations-S-BCpguB.mjs";
7
- import { t as OtelProviderHandle } from "./provider-cUByhzgv.mjs";
8
- import "./index-DpkTHU1a.mjs";
7
+ import { t as OtelProviderHandle } from "./provider-Dy0mVCx5.mjs";
8
+ import "./index-CPrYhbZR.mjs";
9
9
  import { t as RecordExceptionOpts } from "./exception-span-zN1tvBdh.mjs";
10
10
  import { NonErrorException } from "@interfere/types/sdk/errors";
11
11
  import { Tracer } from "@opentelemetry/api";
@@ -15,9 +15,9 @@ import { UrlRedactionPolicy } from "@interfere/types/sdk/url-redaction";
15
15
  import { SessionId } from "@interfere/types/data/session";
16
16
  import { MetricReader } from "@opentelemetry/sdk-metrics";
17
17
  import { ConsentInput, ConsentState, PluginKey } from "@interfere/types/sdk/plugins/manifest";
18
+ import { IdentifyParams } from "@interfere/types/sdk/identify";
18
19
  import { LogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
19
20
  import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
20
- import { IdentifyParams } from "@interfere/types/sdk/identify";
21
21
  //#region src/plugins/lib/types.d.ts
22
22
  type PluginTeardownReason = "consent-revoked" | "disabled" | "dispose";
23
23
  type PluginCleanup = (reason?: PluginTeardownReason) => void;
@@ -272,6 +272,7 @@ declare class Kernel implements PluginContext {
272
272
  getWindowId(): string;
273
273
  onSessionPause(handler: (reason: SessionPauseReason) => void): () => void;
274
274
  onSessionExceptionWhilePaused(handler: (reason: SessionPauseReason) => void): () => void;
275
+ noteException(): void;
275
276
  onSessionResume(handler: (reason: SessionResumeReason) => void): () => void;
276
277
  getPluginConfigState(key: PluginKey): "disabled" | "enabled" | "pending";
277
278
  getReplayConfig(): ReplayConfig;
@@ -0,0 +1 @@
1
+ import{n as getStringGlobal}from"./global-DYq1Z4_H.mjs";import{n as SDK_NAME,r as SDK_VERSION}from"./version-CtEAnX65.mjs";import{i as createTraceExporter,n as createLogExporter,r as createMetricExporter}from"./exporter-CCgTznZ0.mjs";import{t as createExportFilterProcessor}from"./export-filter-CnyAaPct.mjs";import{t as PageScopeContextManager}from"./page-scope-context-manager-Bs-m4fv7.mjs";import{context,propagation}from"@opentelemetry/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{ENVIRONMENT_GLOBAL}from"@interfere/types/sdk/injected-globals";import{createUrlRedactionSpanProcessor,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{defaultServiceName,detectResources,resourceFromAttributes}from"@opentelemetry/resources";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{WebTracerProvider}from"@opentelemetry/sdk-trace-web";import{resolveEnvironment}from"@interfere/types/sdk/runtime";import{browserDetector}from"@opentelemetry/opentelemetry-browser-detector";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{createSessionLogRecordProcessor,createSessionSpanProcessor}from"@opentelemetry/web-common";const ATTR_DEVICE_ID=`device.id`,BROWSER_LOG_BATCH_OPTIONS={exportTimeoutMillis:7e4,maxExportBatchSize:200,maxQueueSize:2048,scheduledDelayMillis:5e3},BROWSER_TRACE_BATCH_OPTIONS={...BROWSER_LOG_BATCH_OPTIONS,scheduledDelayMillis:6e4};function withBaggageEntry(baggage,key,value){return value?baggage.setEntry(key,{value}):baggage.removeEntry(key)}function createSessionBaggagePropagator(opts){let propagator=new W3CBaggagePropagator;return{fields:()=>propagator.fields(),extract:(ctx,carrier,getter)=>propagator.extract(ctx,carrier,getter),inject:(ctx,carrier,setter)=>{let updated=withBaggageEntry(withBaggageEntry(propagation.getBaggage(ctx)??propagation.createBaggage(),`session.id`,opts.getSessionId()),ATTR_DEVICE_ID,opts.getDeviceId());propagator.inject(propagation.setBaggage(ctx,updated),carrier,setter)}}}function createDeviceSpanProcessor(opts){return{forceFlush:async()=>Promise.resolve(),onEnd(){},onStart(span){let id=opts.getDeviceId();id&&span.setAttribute(ATTR_DEVICE_ID,id)},shutdown:async()=>Promise.resolve()}}function createDeviceLogRecordProcessor(opts){return{forceFlush:async()=>Promise.resolve(),onEmit(logRecord){let id=opts.getDeviceId();id&&logRecord.setAttribute(ATTR_DEVICE_ID,id)},shutdown:async()=>Promise.resolve()}}function stampGatedAttributes(target,opts){if(opts.isEnabled())for(let[key,value]of Object.entries(opts.attributes))value!==void 0&&target.setAttribute(key,value)}function createDeviceInfoSpanProcessor(opts){return{forceFlush:async()=>Promise.resolve(),onEnd(){},onStart:span=>{stampGatedAttributes(span,opts)},shutdown:async()=>Promise.resolve()}}function createDeviceInfoLogRecordProcessor(opts){return{forceFlush:async()=>Promise.resolve(),onEmit:logRecord=>{stampGatedAttributes(logRecord,opts)},shutdown:async()=>Promise.resolve()}}function buildOtelProvider(input){let environment=resolveEnvironment({explicit:getStringGlobal(ENVIRONMENT_GLOBAL),env:typeof process>`u`?{}:{INTERFERE_ENVIRONMENT:process.env.INTERFERE_ENVIRONMENT,NODE_ENV:process.env.NODE_ENV,VERCEL_ENV:process.env.VERCEL_ENV}}),resource=resourceFromAttributes(omitUndefined({"service.name":input.serviceName||defaultServiceName(),"service.namespace":input.serviceNamespace,"deployment.environment.name":environment,"telemetry.sdk.language":`webjs`,"interfere.sdk.name":SDK_NAME,"interfere.sdk.version":SDK_VERSION,"interfere.sdk.stack":input.sdkStack.join(`, `),"release.slug":input.releaseSlug||void 0})),deviceInfoAttributes=detectResources({detectors:[browserDetector]}).attributes,isDeviceInfoEnabled=input.isDeviceInfoEnabled??(()=>!1),traceExporter=createTraceExporter({clientOptions:input.clientOptions}),{getSessionId}=input,{getDeviceId}=input,spanProcessors=[createUrlRedactionSpanProcessor(input.urlRedaction??resolveUrlRedaction()),createSessionSpanProcessor({getSessionId}),createDeviceSpanProcessor({getDeviceId}),createDeviceInfoSpanProcessor({attributes:deviceInfoAttributes,isEnabled:isDeviceInfoEnabled}),...input.additionalSpanProcessors??[],createExportFilterProcessor(new BatchSpanProcessor(traceExporter,BROWSER_TRACE_BATCH_OPTIONS),input.onExceptionSpan)],tracerProvider=new WebTracerProvider({resource,spanProcessors}),contextManager=new PageScopeContextManager;contextManager.enable(),context.setGlobalContextManager(contextManager)||contextManager.disable();let isShutdown=!1,getPropagationSessionId=input.getPropagationSessionId??getSessionId;propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,createSessionBaggagePropagator({getDeviceId:()=>isShutdown?null:getDeviceId(),getSessionId:()=>isShutdown?null:getPropagationSessionId()})]}));let metricExporter=createMetricExporter({clientOptions:input.clientOptions},{attributes:deviceInfoAttributes,isEnabled:isDeviceInfoEnabled}),metricReader=new PeriodicExportingMetricReader({exportIntervalMillis:75e3,exportTimeoutMillis:7e4,exporter:metricExporter}),meterProvider=new MeterProvider({readers:[metricReader,...input.additionalMetricReaders??[]],resource}),logExporter=createLogExporter({clientOptions:input.clientOptions}),loggerProvider=new LoggerProvider({processors:[createSessionLogRecordProcessor({getSessionId}),createDeviceLogRecordProcessor({getDeviceId}),createDeviceInfoLogRecordProcessor({attributes:deviceInfoAttributes,isEnabled:isDeviceInfoEnabled}),new BatchLogRecordProcessor({exporter:logExporter,...BROWSER_LOG_BATCH_OPTIONS}),...input.additionalLogRecordProcessors??[]],resource});return{contextManager,flush:async()=>{await Promise.allSettled([tracerProvider.forceFlush({timeoutMillis:75e3}),metricReader.forceFlush({timeoutMillis:75e3}),loggerProvider.forceFlush({timeoutMillis:75e3})])},loggerProvider,meterProvider,metricReader,shutdown:async()=>{isShutdown=!0,await Promise.allSettled([tracerProvider.shutdown(),meterProvider.shutdown(),loggerProvider.shutdown()])},tracerProvider}}export{buildOtelProvider as t};
@@ -1,4 +1,4 @@
1
- import { t as PageScopeContextManager } from "./page-scope-context-manager-r92ZMJok.mjs";
1
+ import { t as PageScopeContextManager } from "./page-scope-context-manager-DUhBvuAz.mjs";
2
2
  import { InterfereClient } from "@interfere/javascript";
3
3
  import { ReleaseSlug } from "@interfere/types/releases/slug";
4
4
  import { UrlRedactionPolicy } from "@interfere/types/sdk/url-redaction";
@@ -46,6 +46,8 @@ interface OtelProviderInput {
46
46
  * the kernel wires it to the `device` plugin's activation state.
47
47
  */
48
48
  isDeviceInfoEnabled?: () => boolean;
49
+ /** Called when a finished span carries an `exception` event, whichever instrumentation recorded it. */
50
+ onExceptionSpan?: () => void;
49
51
  /** Optional release slug — top-level `release.slug` attr (Phase 6 wire identity). */
50
52
  releaseSlug?: ReleaseSlug | null | undefined;
51
53
  /**
@@ -68,7 +70,7 @@ interface OtelProviderHandle {
68
70
  /**
69
71
  * Page-scope context manager. The kernel calls `setPageScope(ctx)` after
70
72
  * extracting the SSR `traceparent` meta tag so spans without a more
71
- * specific zone descend from the server-side parent.
73
+ * specific active span descend from the server-side parent.
72
74
  */
73
75
  contextManager: PageScopeContextManager;
74
76
  /** Force-flush all three providers — call from kernel.flush() / on visibility hidden. */
@@ -1,4 +1,4 @@
1
1
  import { a as ReplayOption, i as ReplayConfig } from "./config-Dyc09HCZ.mjs";
2
- import { a as InterfereContextValue, b as PluginOverrides, i as InterfereContext, n as useInterfere, r as useSession, t as InterfereProvider } from "./provider-D4QjZp3L.mjs";
2
+ import { a as InterfereContextValue, b as PluginOverrides, i as InterfereContext, n as useInterfere, r as useSession, t as InterfereProvider } from "./provider-BMMGZWyS.mjs";
3
3
  import { n as PageEventsOption, t as PageEventsConfig } from "./page-events-config-CiJvdAaJ.mjs";
4
4
  export { InterfereContext, type InterfereContextValue, InterfereProvider, type PageEventsConfig, type PageEventsOption, type PluginOverrides, type ReplayConfig, type ReplayOption, useInterfere, useSession };
@@ -0,0 +1 @@
1
+ import{createElement}from"react";import{flushSync}from"react-dom";import{createRoot}from"react-dom/client";let primed=!1;function primeReactDomKeys(){if(!(primed||typeof document>`u`)){primed=!0;try{let inert=document.implementation.createHTMLDocument(``),root=createRoot(inert.createElement(`div`));flushSync(()=>{root.render(createElement(`span`))}),root.unmount()}catch{return}}}export{primeReactDomKeys as t};
@@ -1,4 +1,4 @@
1
- import { s as Kernel } from "./provider-D4QjZp3L.mjs";
1
+ import { s as Kernel } from "./provider-BMMGZWyS.mjs";
2
2
  //#region src/react-error-handler.d.ts
3
3
  /** React root error-handler metadata; only componentStack is consumed. */
4
4
  interface ReactRootErrorInfo {
@@ -1 +1 @@
1
- import{t as IngestBackoffError}from"./ingest-backoff-B1OeEV3h.mjs";import{isRetryableStatus}from"@interfere/helpers/retry-request";const RETRY_DELAYS_MS=[5e3,15e3];var SessionRetry=class{timer=null;attempts=0;cancel(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.cancel(),this.attempts=0}schedule(error,retry){let status=error.statusCode,transient=!(error.cause instanceof TypeError||error.cause instanceof IngestBackoffError)&&(status===void 0||isRetryableStatus(status)),delay=RETRY_DELAYS_MS[this.attempts];transient&&delay!==void 0&&this.timer===null&&(this.attempts+=1,this.timer=setTimeout(()=>{this.timer=null,retry()},delay))}};export{SessionRetry as t};
1
+ import{t as IngestBackoffError}from"./ingest-backoff-BdBT-jss.mjs";import{isRetryableStatus}from"@interfere/helpers/retry-request";const RETRY_DELAYS_MS=[5e3,15e3];var SessionRetry=class{timer=null;attempts=0;cancel(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.cancel(),this.attempts=0}schedule(error,retry){let status=error.statusCode,transient=!(error.cause instanceof TypeError||error.cause instanceof IngestBackoffError)&&(status===void 0||isRetryableStatus(status)),delay=RETRY_DELAYS_MS[this.attempts];transient&&delay!==void 0&&this.timer===null&&(this.attempts+=1,this.timer=setTimeout(()=>{this.timer=null,retry()},delay))}};export{SessionRetry as t};
@@ -0,0 +1 @@
1
+ import{z}from"zod/mini";const INGEST_QUEUE_QUERY=`interfere.sw.accepts`,INGEST_QUEUE_ANSWER=`interfere.sw.accepted`,ingestQueueQuerySchema=z.object({type:z.literal(INGEST_QUEUE_QUERY),url:z.string()}),ingestQueueAnswerSchema=z.object({accepted:z.boolean(),type:z.literal(INGEST_QUEUE_ANSWER)});function answerIngestQueueQuery(query,port,matches){let accepted;try{let url=new URL(query.url);accepted=matches(url,new Request(url,{method:`POST`}))}catch{accepted=!1}let answer={accepted,type:INGEST_QUEUE_ANSWER};port.postMessage(answer)}export{ingestQueueQuerySchema as i,answerIngestQueueQuery as n,ingestQueueAnswerSchema as r,INGEST_QUEUE_QUERY as t};
@@ -0,0 +1,22 @@
1
+ import { z } from "zod/mini";
2
+ //#region src/internal/sw-queue-protocol.d.ts
3
+ declare const INGEST_QUEUE_QUERY = "interfere.sw.accepts";
4
+ /** Message a page posts to its controlling service worker to ask whether the ingest queue would durably queue a POST to `url`. */
5
+ declare const ingestQueueQuerySchema: z.ZodMiniObject<{
6
+ type: z.ZodMiniLiteral<"interfere.sw.accepts">;
7
+ url: z.ZodMiniString<string>;
8
+ }, z.core.$strip>;
9
+ /** Reply the ingest queue posts on the query's port. */
10
+ declare const ingestQueueAnswerSchema: z.ZodMiniObject<{
11
+ accepted: z.ZodMiniBoolean<boolean>;
12
+ type: z.ZodMiniLiteral<"interfere.sw.accepted">;
13
+ }, z.core.$strip>;
14
+ type IngestQueueQuery = z.infer<typeof ingestQueueQuerySchema>;
15
+ /** Page-side handle to the service worker that may run the ingest queue. */
16
+ interface IngestQueueController {
17
+ postMessage: (message: IngestQueueQuery, transfer: Transferable[]) => void;
18
+ }
19
+ /** Answers an ingest queue query on its port with whether `matches` accepts its URL. */
20
+ declare function answerIngestQueueQuery(query: IngestQueueQuery, port: MessagePort, matches: (url: URL, request: Request) => boolean): void;
21
+ //#endregion
22
+ export { ingestQueueAnswerSchema as a, answerIngestQueueQuery as i, IngestQueueController as n, ingestQueueQuerySchema as o, IngestQueueQuery as r, INGEST_QUEUE_QUERY as t };
@@ -1,2 +1,2 @@
1
- import { n as SessionTrackerOptions, t as SessionTracker } from "../api-DSUjs8zG.mjs";
1
+ import { n as SessionTrackerOptions, t as SessionTracker } from "../api-BXjfYV5Z.mjs";
2
2
  export { SessionTracker, SessionTrackerOptions };
@@ -1 +1 @@
1
- import{t as SessionTracker}from"../api-DvHT4Dyw.mjs";export{SessionTracker};
1
+ import{t as SessionTracker}from"../api-C8aG7li1.mjs";export{SessionTracker};
@@ -0,0 +1,73 @@
1
+ import { t as DeviceManager } from "../device-vFtWy12y.mjs";
2
+ import { t as SessionTracker } from "../api-BXjfYV5Z.mjs";
3
+ import { z } from "zod";
4
+ //#region src/tracking/lifecycle.fixture.d.ts
5
+ export declare const FP_HASH = "fp-hash-lifecycle";
6
+ export declare const SOURCE: {
7
+ readonly name: "Audit";
8
+ readonly type: "custom";
9
+ };
10
+ export declare const createSessionBody: z.ZodObject<{
11
+ deviceId: z.ZodNullable<z.ZodUUID>;
12
+ fpHash: z.ZodNullable<z.ZodString>;
13
+ sessionId: z.ZodIntersection<z.core.$ZodBranded<z.ZodString, "SessionId", "out">, z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`server_${string}`>]>>;
14
+ }, z.core.$strict>;
15
+ export declare const identifySessionBody: z.ZodObject<{
16
+ avatar: z.ZodOptional<z.ZodString>;
17
+ email: z.ZodOptional<z.ZodEmail>;
18
+ identifier: z.ZodString;
19
+ name: z.ZodOptional<z.ZodString>;
20
+ source: z.ZodDiscriminatedUnion<[z.ZodObject<{
21
+ name: z.ZodLiteral<"Clerk">;
22
+ type: z.ZodLiteral<"clerk">;
23
+ }, z.core.$strip>, z.ZodObject<{
24
+ name: z.ZodLiteral<"Auth0">;
25
+ type: z.ZodLiteral<"auth0">;
26
+ }, z.core.$strip>, z.ZodObject<{
27
+ name: z.ZodLiteral<"WorkOS">;
28
+ type: z.ZodLiteral<"workos">;
29
+ }, z.core.$strip>, z.ZodObject<{
30
+ name: z.ZodString;
31
+ type: z.ZodLiteral<"custom">;
32
+ }, z.core.$strip>], "type">;
33
+ traits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
+ deviceId: z.ZodNullable<z.ZodUUID>;
35
+ fpHash: z.ZodNullable<z.ZodString>;
36
+ sessionId: z.ZodIntersection<z.core.$ZodBranded<z.ZodString, "SessionId", "out">, z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`server_${string}`>]>>;
37
+ country: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strict>;
39
+ export declare function sessions(): {
40
+ [x: string]: unknown;
41
+ deviceId?: string | null | undefined;
42
+ fpHash?: string | null | undefined;
43
+ identifier?: string | undefined;
44
+ sessionId?: string | undefined;
45
+ }[];
46
+ export declare function identifies(): {
47
+ [x: string]: unknown;
48
+ deviceId?: string | null | undefined;
49
+ fpHash?: string | null | undefined;
50
+ identifier?: string | undefined;
51
+ sessionId?: string | undefined;
52
+ }[];
53
+ /** Resolves once the ingest has received `count` session requests. */
54
+ export declare function sessionsArrived(count: number): Promise<void>;
55
+ /** Resolves once the ingest has received `count` identify requests. */
56
+ export declare function identifiesArrived(count: number): Promise<void>;
57
+ export declare function inits(): RequestInit[];
58
+ export declare function failIdentify(status: number): void;
59
+ export declare function readyDevice(): DeviceManager;
60
+ export declare function pendingDevice(): {
61
+ device: DeviceManager;
62
+ release: (hash: string | null) => void;
63
+ };
64
+ export declare function makeTracker(device?: DeviceManager): SessionTracker;
65
+ export declare function started(device?: DeviceManager): Promise<SessionTracker>;
66
+ /** Waits for `arrival`, giving up after one second so a known gap fails fast. */
67
+ export declare function withinASecond(arrival: Promise<void>): Promise<void>;
68
+ export declare function settle(): Promise<void>;
69
+ export declare function setupLifecycle(): void;
70
+ /** Records session and identify requests sent to `baseUrl` and resets the recorder. */
71
+ export declare function recordIngest(baseUrl: string): void;
72
+ export declare function teardownLifecycle(): Promise<void>;
73
+ //#endregion
@@ -0,0 +1 @@
1
+ import{a as HttpResponse,i as http,n as vi,t as worker}from"../msw-C0yLYJU2.mjs";import{a as resetPageLifecycleForTests}from"../page-lifecycle-rJEJNdKj.mjs";import{t as DeviceManager}from"../device-DRK7hhLi.mjs";import{t as GeoDetector}from"../geo-D2wa9bGs.mjs";import{t as SessionTracker}from"../api-C8aG7li1.mjs";import{sessionIdSchema}from"@interfere/types/data/session";import{z}from"zod";import{identifyParamsSchema}from"@interfere/types/sdk/identify";const BASE_URL=`https://lifecycle.invalid`,FP_HASH=`fp-hash-lifecycle`,SOURCE={name:`Audit`,type:`custom`},createSessionBody=z.strictObject({deviceId:z.uuid().nullable(),fpHash:z.string().nullable(),sessionId:sessionIdSchema}),identifySessionBody=z.strictObject({...createSessionBody.shape,...identifyParamsSchema.shape,country:z.string().max(2).optional()}),recordedBody=z.looseObject({deviceId:z.string().nullable().optional(),fpHash:z.string().nullable().optional(),identifier:z.string().optional(),sessionId:z.string().optional()}),recorded=[],waiters=[],trackers=[],requestInits=[],identifyResponse={status:200};function bodies(path){return recorded.flatMap(r=>r.path===path?[r.body]:[])}function sessions(){return bodies(`/v3/session`)}function identifies(){return bodies(`/v3/session/identify`)}function release(){for(let waiter of waiters.splice(0))bodies(waiter.path).length>=waiter.count?waiter.resolve():waiters.push(waiter)}async function arrived(path,count){let{promise,resolve}=Promise.withResolvers();waiters.push({count,path,resolve:()=>{resolve(void 0)}}),release(),await promise}async function sessionsArrived(count){await arrived(`/v3/session`,count)}async function identifiesArrived(count){await arrived(`/v3/session/identify`,count)}function inits(){return requestInits}function failIdentify(status){identifyResponse.status=status}function readyDevice(){return new DeviceManager(async()=>FP_HASH)}function pendingDevice(){let fingerprint=Promise.withResolvers();return{device:new DeviceManager(async()=>fingerprint.promise),release:hash=>{fingerprint.resolve(hash)}}}function makeTracker(device=readyDevice()){let tracker=new SessionTracker({device,fetcher:async(input,init)=>(init&&requestInits.push(init),globalThis.fetch(input,init)),geo:new GeoDetector,target:{baseUrl:BASE_URL,publicKeyHeader:{apiKey:`test-key`}}});return trackers.push(tracker),tracker}async function started(device){let tracker=makeTracker(device);return tracker.start(),await sessionsArrived(1),tracker}async function withinASecond(arrival){let{promise,resolve}=Promise.withResolvers(),timer=setTimeout(()=>{resolve(void 0)},1e3);await Promise.race([arrival,promise]),clearTimeout(timer)}async function settle(){let{promise,resolve}=Promise.withResolvers();setTimeout(()=>{resolve(void 0)},50),await promise}function setupLifecycle(){recordIngest(BASE_URL)}function recordIngest(baseUrl){recorded.length=0,waiters.length=0,requestInits.length=0,identifyResponse.status=200,worker.use(...[`/v3/session`,`/v3/session/identify`].map(path=>http.post(`${baseUrl}${path}`,async({request})=>{recorded.push({path,body:recordedBody.parse(await request.json())}),release();let status=path===`/v3/session`?200:identifyResponse.status;return HttpResponse.json({ok:status===200},{status})})))}async function teardownLifecycle(){for(let tracker of trackers.splice(0))tracker.dispose();await settle(),resetPageLifecycleForTests(),vi.useRealTimers(),await cookieStore.delete(`interfere_did`)}export{FP_HASH,SOURCE,createSessionBody,failIdentify,identifies,identifiesArrived,identifySessionBody,inits,makeTracker,pendingDevice,readyDevice,recordIngest,sessions,sessionsArrived,settle,setupLifecycle,started,teardownLifecycle,withinASecond};
@@ -1,4 +1,4 @@
1
- import { t as SessionTracker } from "../api-DSUjs8zG.mjs";
1
+ import { t as SessionTracker } from "../api-BXjfYV5Z.mjs";
2
2
  import { InterfereClient } from "@interfere/javascript";
3
3
  //#region ../../../../node_modules/.bun/vitest@5.0.5+0658583d3f365267/node_modules/vitest/optional-runtime-types.d.ts
4
4
  /* oxlint-disable typescript/ban-ts-comment */