@interfere/react 12.3.4 → 12.4.2

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 (99) hide show
  1. package/README.md +7 -1
  2. package/dist/{api-DSUjs8zG.d.mts → api-BXjfYV5Z.d.mts} +1 -0
  3. package/dist/api-C8aG7li1.mjs +1 -0
  4. package/dist/cors-guard-CwkqEjzL.mjs +1 -0
  5. package/dist/{delivery-D9hzPDs9.mjs → delivery-D7hULClu.mjs} +1 -1
  6. package/dist/error-boundary.d.mts +1 -1
  7. package/dist/export-filter-CnyAaPct.mjs +1 -0
  8. package/dist/exporter-BtHqkV3R.mjs +1 -0
  9. package/dist/exporter-logs-BbzSiQJi.mjs +1 -0
  10. package/dist/index-C3K6oR4l.d.mts +4 -0
  11. package/dist/ingest-backoff-BdBT-jss.mjs +1 -0
  12. package/dist/instrumentations-qhx6Oc_F.mjs +1 -0
  13. package/dist/{instrumentations-S-BCpguB.d.mts → instrumentations-zBdPJHog.d.mts} +7 -1
  14. package/dist/internal/capture/capture-boundary.d.mts +1 -1
  15. package/dist/internal/capture/capture.d.mts +1 -1
  16. package/dist/internal/ingest-backoff/ingest-backoff.d.mts +3 -2
  17. package/dist/internal/ingest-backoff/ingest-backoff.mjs +1 -1
  18. package/dist/internal/kernel-registry.d.mts +1 -1
  19. package/dist/internal/kernel.d.mts +2 -2
  20. package/dist/internal/kernel.mjs +1 -1
  21. package/dist/internal/otel/export-filter.d.mts +2 -2
  22. package/dist/internal/otel/export-filter.mjs +1 -1
  23. package/dist/internal/otel/exporter-logs.mjs +1 -1
  24. package/dist/internal/otel/exporter.mjs +1 -1
  25. package/dist/internal/otel/index.d.mts +3 -3
  26. package/dist/internal/otel/index.mjs +1 -1
  27. package/dist/internal/otel/instrumentations/cors-guard.d.mts +26 -0
  28. package/dist/internal/otel/instrumentations/cors-guard.mjs +1 -0
  29. package/dist/internal/otel/instrumentations/instrumentations.d.mts +1 -1
  30. package/dist/internal/otel/instrumentations/instrumentations.mjs +1 -1
  31. package/dist/internal/otel/instrumentations/propagation-targets.d.mts +6 -0
  32. package/dist/internal/otel/instrumentations/propagation-targets.mjs +1 -0
  33. package/dist/internal/otel/keepalive-chunks.d.mts +6 -0
  34. package/dist/internal/otel/keepalive-chunks.mjs +1 -0
  35. package/dist/internal/otel/page-scope-context-manager.d.mts +1 -1
  36. package/dist/internal/otel/page-scope-context-manager.mjs +1 -1
  37. package/dist/internal/otel/provider.d.mts +1 -1
  38. package/dist/internal/otel/provider.mjs +1 -1
  39. package/dist/internal/page-lifecycle/keepalive-budget.d.mts +2 -2
  40. package/dist/internal/page-lifecycle/keepalive-budget.mjs +1 -1
  41. package/dist/internal/plugins/plugin-runtime.d.mts +1 -1
  42. package/dist/internal/plugins/plugin-runtime.mjs +1 -1
  43. package/dist/internal/react-context.d.mts +1 -1
  44. package/dist/internal/react-dom-keys.d.mts +3 -0
  45. package/dist/internal/react-dom-keys.mjs +1 -0
  46. package/dist/internal/sw-queue-protocol.d.mts +2 -0
  47. package/dist/internal/sw-queue-protocol.mjs +1 -0
  48. package/dist/internal/sw-queue.mjs +1 -1
  49. package/dist/internal/version.mjs +1 -1
  50. package/dist/internal/wrapper-singleton.d.mts +1 -1
  51. package/dist/internal/wrapper-singleton.mjs +1 -1
  52. package/dist/keepalive-budget-BfoHXD04.mjs +1 -0
  53. package/dist/keepalive-chunks-BZv3PhHT.mjs +1 -0
  54. package/dist/kernel-BZI0jyJI.mjs +1 -0
  55. package/dist/msw-C0yLYJU2.mjs +255 -0
  56. package/dist/page-scope-context-manager-Bs-m4fv7.mjs +1 -0
  57. package/dist/{page-scope-context-manager-r92ZMJok.d.mts → page-scope-context-manager-DUhBvuAz.d.mts} +2 -2
  58. package/dist/{plugin-runtime-DSj0FM1Q.mjs → plugin-runtime-DgB1_Xc5.mjs} +1 -1
  59. package/dist/plugins/device.d.mts +1 -1
  60. package/dist/plugins/errors.d.mts +1 -1
  61. package/dist/plugins/lib/loader.d.mts +1 -1
  62. package/dist/plugins/lib/types.d.mts +1 -1
  63. package/dist/plugins/logs.d.mts +1 -1
  64. package/dist/plugins/page-events.d.mts +1 -1
  65. package/dist/plugins/rage-clicks.d.mts +1 -1
  66. package/dist/plugins/replay/index.d.mts +1 -1
  67. package/dist/plugins/replay/index.mjs +1 -1
  68. package/dist/plugins/replay/upload/delivery.d.mts +1 -1
  69. package/dist/plugins/replay/upload/delivery.mjs +1 -1
  70. package/dist/propagation-targets-BXDetg0k.mjs +1 -0
  71. package/dist/provider-B8YtuhDX.mjs +1 -0
  72. package/dist/{provider-cUByhzgv.d.mts → provider-Dy0mVCx5.d.mts} +4 -2
  73. package/dist/{provider-D4QjZp3L.d.mts → provider-vp8Aao8Q.d.mts} +11 -8
  74. package/dist/provider.d.mts +1 -1
  75. package/dist/react-dom-keys-BIJuLkQR.mjs +1 -0
  76. package/dist/react-error-handler.d.mts +1 -1
  77. package/dist/{session-retry-TrzzihIM.mjs → session-retry-Dgkk0yui.mjs} +1 -1
  78. package/dist/sw-queue-protocol-DnTSOWxy.mjs +1 -0
  79. package/dist/sw-queue-protocol-DqP1EQtQ.d.mts +22 -0
  80. package/dist/tracking/api.d.mts +1 -1
  81. package/dist/tracking/api.mjs +1 -1
  82. package/dist/tracking/lifecycle.fixture.d.mts +73 -0
  83. package/dist/tracking/lifecycle.fixture.mjs +1 -0
  84. package/dist/tracking/registration.fixture.d.mts +1 -1
  85. package/dist/tracking/registration.fixture.mjs +1 -255
  86. package/dist/tracking/session-retry.mjs +1 -1
  87. package/dist/{version-DusHm2Q4.mjs → version-CPcWUmrA.mjs} +1 -1
  88. package/package.json +3 -4
  89. package/dist/api-DvHT4Dyw.mjs +0 -1
  90. package/dist/export-filter-Cixywxpu.mjs +0 -1
  91. package/dist/exporter-De0h9YP5.mjs +0 -1
  92. package/dist/exporter-logs-DS2AXWnV.mjs +0 -1
  93. package/dist/index-DpkTHU1a.d.mts +0 -4
  94. package/dist/ingest-backoff-B1OeEV3h.mjs +0 -1
  95. package/dist/instrumentations-NN81kslu.mjs +0 -1
  96. package/dist/keepalive-budget-DeafGnVZ.mjs +0 -1
  97. package/dist/kernel-BVG-7Zau.mjs +0 -1
  98. package/dist/page-scope-context-manager-DhArvVJ_.mjs +0 -1
  99. package/dist/provider-CElaujE6.mjs +0 -1
package/README.md CHANGED
@@ -89,7 +89,7 @@ function MyComponent() {
89
89
 
90
90
  ## Session correlation
91
91
 
92
- With the SDK's default browser propagator, instrumented fetch and XHR requests carry `session.id` in W3C baggage to the same origin and hosts in `tracing.apiHosts`. Cross-origin APIs must allow the `baggage` and `traceparent` request headers in their CORS configuration. Existing `tracing.propagateContextUrls` patterns also apply.
92
+ With the SDK's default browser propagator, instrumented fetch and XHR requests carry `session.id` in W3C baggage to the page's own site (same registrable domain, any subdomain or port), to backend hosts Interfere already knows for your organization, and to hosts in `tracing.apiHosts`. Cross-origin APIs must allow the `baggage` and `traceparent` request headers in their CORS configuration. Existing `tracing.propagateContextUrls` patterns also apply.
93
93
 
94
94
  Explicitly denying analytics consent stops session baggage propagation while retaining trace propagation. `tracing: false` disables SDK instrumentation. Existing application-owned propagators are not replaced.
95
95
 
@@ -194,6 +194,12 @@ Finish attribute mutations synchronously in `onEnd`, before it returns. OpenTele
194
194
 
195
195
  The SDK calls each processor's `forceFlush` during flush and `shutdown` during disposal. Use a fresh processor instance for each SDK initialization and do not share it with another provider. `tracing: false` skips tracing setup, including custom processors.
196
196
 
197
+ ## Trace export and context
198
+
199
+ The SDK batches ended spans and sends them every 60 seconds, or sooner when 200 spans are waiting. When the page is hidden or unloaded, it sends everything still queued at once with a keepalive request. Spans still queued when a tab is killed without a hide event, such as a crash, are lost. Logs are sent every 5 seconds.
200
+
201
+ The SDK tracks the active span without zone.js. A click or submit span ends when its synchronous event handler returns. Spans started after an `await` in that handler, including fetch and XHR requests, are children of the page span instead of the click span. If your app loads zone.js itself, as Angular does, the SDK does not use it.
202
+
197
203
  ## Documentation
198
204
 
199
205
  Visit [interfere.com/docs](https://interfere.com/docs) for the full documentation.
@@ -18,6 +18,7 @@ declare class SessionTracker {
18
18
  private readonly activity;
19
19
  private currentIdentity;
20
20
  private identifiedSessionId;
21
+ private identifiedDeviceId;
21
22
  private lastSyncedKey;
22
23
  private inflightSyncKey;
23
24
  private syncAttemptMs;
@@ -0,0 +1 @@
1
+ import{t as createLogger}from"./log-D6Ht--tv.mjs";import{t as ActivityMonitor}from"./activity-oYlZ5aa1.mjs";import{n as fetchIngest}from"./ingest-backoff-BdBT-jss.mjs";import{t as DeviceManager}from"./device-DRK7hhLi.mjs";import{t as GeoDetector}from"./geo-D2wa9bGs.mjs";import{t as SessionManager}from"./session-C30CtCVv.mjs";import{t as SessionRetry}from"./session-retry-Dgkk0yui.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{InterfereClient,InterfereError}from"@interfere/javascript";const log=createLogger(`tracking`);function syncKey(sessionId,deviceId,fpHash){return`${sessionId}|${deviceId??``}|${fpHash??``}`}var SessionTracker=class{client;device;geo;mgr=null;activity=new ActivityMonitor;currentIdentity=null;identifiedSessionId=null;identifiedDeviceId=null;lastSyncedKey=null;inflightSyncKey=null;syncAttemptMs=0;generation=0;syncRetry=new SessionRetry;syncRetryKey=null;identityStarted=!1;constructor(opts){this.client=new InterfereClient({...opts.target,maxRetries:0,timeoutInSeconds:10,fetch:Object.assign(async(input,init)=>fetchIngest(input,async()=>(opts.fetcher??globalThis.fetch)(input,{...init,credentials:`omit`,keepalive:!0})),opts.fetcher??globalThis.fetch)}),this.device=opts.device??new DeviceManager,this.geo=opts.geo??new GeoDetector}start(){this.mgr=new SessionManager(id=>{this.onRotate(id)}),this.activity.start({markActivity:()=>{this.markActivity()},reset:()=>{this.rotateSession()},startedAt:()=>this.getSessionStartedAt()})}startDeviceIdentity(){this.identityStarted||(this.invalidateSync(),this.identityStarted=!0,this.device.init(),this.geo.detect(),this.backfillIdentity())}discardDeviceIdentity(){this.invalidateSync(),this.identityStarted=!1,this.device.clear(),this.geo.clear()}async backfillIdentity(){let gen=this.generation;if(await Promise.resolve(),gen!==this.generation||!this.identityStarted)return;let initialSessionId=this.mgr?.getSessionId()??null,initialFpHash=this.device.getFpHash();initialSessionId&&await this.syncSession(initialSessionId,this.device.getDeviceId(),initialFpHash),this.currentIdentity&&this.identify(this.currentIdentity);let fpHash=await this.device.whenFingerprintReady(),sessionId=this.mgr?.getSessionId()??null;gen===this.generation&&this.identityStarted&&sessionId&&fpHash!==initialFpHash&&this.syncSession(sessionId,this.device.getDeviceId(),fpHash)}onSessionPause(handler){return this.activity.onPause(handler)}onSessionExceptionWhilePaused(handler){return this.activity.onExceptionWhilePaused(handler)}noteException(){this.activity.noteException()}onSessionResume(handler){return this.activity.onResume(handler)}sessionId(){let id=this.mgr?.getSessionId()??null;return id&&this.ensureSynced(id),id}windowId(){return this.mgr?.getWindowId()??null}markActivity(){this.mgr?.markActivity()}getSessionStartedAt(){return this.mgr?.getSessionStartedAt()??0}getDeviceId(){return this.device.getDeviceId()}getFpHash(){return this.device.getFpHash()}getIdentity(){return this.currentIdentity}async identify(params){if(!this.mgr)return;let sessionId=this.mgr.getSessionId();if(this.identifiedSessionId===sessionId&&this.identifiedDeviceId===this.device.getDeviceId()){log.debug(`skipped, already identified for session %s`,sessionId);return}this.currentIdentity=params,this.identifiedSessionId=sessionId,this.identifiedDeviceId=this.device.getDeviceId();let gen=this.generation,[fpHash,country]=await Promise.all([this.device.whenFingerprintReady(),this.geo.detect()]),deviceId=this.device.getDeviceId();if(gen!==this.generation){this.identifiedSessionId=null;return}log.info(`POST session %s → identify`,sessionId),this.postIdentify(sessionId,omitUndefined({deviceId,fpHash,sessionId,...params,country:country||void 0}))}async postIdentify(sessionId,body){try{await this.client.sessions.identifySession(body)}catch{this.identifiedSessionId=null,log.warn(`identify failed for session %s`,sessionId)}}clearIdentity(){this.currentIdentity=null,this.identifiedSessionId=null,this.identifiedDeviceId=null}reset(){this.invalidateSync(),this.clearIdentity(),this.identityStarted&&this.device.reset(),this.mgr?.reset()}rotateSession(){this.mgr?.reset()}dispose(){this.activity.stop(),this.invalidateSync(),this.clearIdentity(),this.mgr=null}invalidateSync(){this.generation+=1,this.syncRetry.reset(),this.syncRetryKey=null,this.lastSyncedKey=null,this.inflightSyncKey=null,this.syncAttemptMs=0}currentSyncKey(){let sessionId=this.mgr?.sessionId;return sessionId?syncKey(sessionId,this.device.getDeviceId(),this.device.getFpHash()):null}ensureSynced(sessionId){let deviceId=this.device.getDeviceId(),fpHash=this.device.getFpHash(),key=syncKey(sessionId,deviceId,fpHash);this.lastSyncedKey!==key&&this.inflightSyncKey!==key&&(Date.now()-this.syncAttemptMs<5e3||this.syncSession(sessionId,deviceId,fpHash))}async syncSession(sessionId,deviceId,fpHash){let key=syncKey(sessionId,deviceId,fpHash);if(this.lastSyncedKey===key||this.inflightSyncKey===key)return;this.syncRetryKey!==key&&(this.syncRetry.reset(),this.syncRetryKey=key),this.syncRetry.cancel();let{generation}=this;this.inflightSyncKey=key,this.syncAttemptMs=Date.now();try{await this.client.sessions.createSession({sessionId,deviceId,fpHash}),generation===this.generation&&key===this.currentSyncKey()&&(this.lastSyncedKey=key,this.syncRetry.reset())}catch(error){log.warn(`session sync failed`),error instanceof InterfereError&&generation===this.generation&&key===this.currentSyncKey()&&this.syncRetry.schedule(error,()=>{let current=this.mgr?.sessionId;generation===this.generation&&current&&this.ensureSynced(current)})}finally{generation===this.generation&&this.inflightSyncKey===key&&(this.inflightSyncKey=null)}}async onRotate(sessionId){this.syncAttemptMs=Date.now();let gen=this.generation;try{await Promise.resolve();let fpHash=this.device.getFpHash(),deviceId=this.device.getDeviceId();if(gen!==this.generation)return;log.debug(`POST session %s (device=%s fp=%s)`,sessionId,deviceId??`pending`,fpHash??`none`),this.syncSession(sessionId,deviceId,fpHash)}catch{}}};export{SessionTracker as t};
@@ -0,0 +1 @@
1
+ import{trace}from"@opentelemetry/api";const TRACE_HEADERS=[`traceparent`,`tracestate`,`baggage`],ATTR_TRACE_PROPAGATION=`interfere.trace_propagation`,ESCAPE_RE=/[.*+?^${}()|[\]\\]/gu;function pageOrigin(){return globalThis.location.origin}function originOf(url){try{return new URL(url,globalThis.location.href).origin}catch{return null}}function isRequestInput(input){return input instanceof Request}function stripTraceHeaders(headers){for(let name of TRACE_HEADERS)headers.delete(name);return headers}function corsWarning(origin){return`[interfere] ${origin} rejected the trace headers in its CORS preflight, so Interfere resent the request without them and stops adding them to that origin for this session. To link these requests to your backend traces, add "traceparent, tracestate, baggage" to Access-Control-Allow-Headers on ${origin}.`}var OriginGuardedPattern=class extends RegExp{#isDisabled;constructor(pattern,isDisabled){super(pattern.source,pattern.flags),this.#isDisabled=isDisabled}[Symbol.match](value){return this.#isDisabled(value)?null:super[Symbol.match](value)}};function installCorsGuard(){let nativeFetch=globalThis.fetch,disabled=new Set,verified=new Set;function isDisabled(url){let origin=originOf(url);return origin!==null&&disabled.has(origin)}function planRetry(input,init){let isRequest=isRequestInput(input);if(!(isRequest?input.headers:new Headers(init?.headers)).has(`traceparent`))return null;let origin=originOf(isRequest?input.url:String(input));return origin===null||origin===pageOrigin()||verified.has(origin)||disabled.has(origin)?null:isRequest?input.body===null?{origin,retry:async()=>nativeFetch(new Request(input,{headers:stripTraceHeaders(new Headers(input.headers))})),signal:input.signal}:null:init?.body instanceof ReadableStream?null:{origin,retry:async()=>nativeFetch(input,{...init,headers:stripTraceHeaders(new Headers(init?.headers))}),signal:init?.signal}}function disable(origin){disabled.has(origin)||(disabled.add(origin),console.warn(corsWarning(origin)))}async function guardedFetch(input,init){let plan=planRetry(input,init);if(!plan)return nativeFetch(input,init);let span=trace.getActiveSpan();try{let response=await nativeFetch(input,init);return verified.add(plan.origin),response}catch(error){if(!(error instanceof TypeError)||plan.signal?.aborted)throw error;let retried;try{retried=await plan.retry()}catch{throw error}return disable(plan.origin),span?.setAttribute(ATTR_TRACE_PROPAGATION,`disabled_cors`),retried}}return globalThis.fetch=Object.assign(guardedFetch,nativeFetch),{disabledHosts:()=>[...disabled].map(origin=>new URL(origin).host),dispose:()=>{globalThis.fetch===guardedFetch&&(globalThis.fetch=nativeFetch)},guardPatterns:patterns=>patterns.map(pattern=>new OriginGuardedPattern(pattern instanceof RegExp?pattern:RegExp(`^${pattern.replace(ESCAPE_RE,String.raw`\$&`)}$`,`u`),isDisabled))}}export{installCorsGuard as n,ATTR_TRACE_PROPAGATION as t};
@@ -1 +1 @@
1
- import{t as createLogger}from"./log-D6Ht--tv.mjs";import{t as reserveKeepaliveBody}from"./keepalive-budget-DeafGnVZ.mjs";import{t as gzipForUnload}from"./unload-gzip-WX9FyWPs.mjs";import{t as uploadReplayChunk}from"./upload-D55WVf_o.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";const log=createLogger(`replay`),REPLAY_TRACER_NAME=`@interfere/react/replay`,textEncoder=new TextEncoder,FATAL_STATUSES=new Set([401,403,413]);function classifyRejection(status){return status===409?`skipped`:FATAL_STATUSES.has(status)?`fatal`:`retryable`}async function prepareBody(compressor,rawBytes){if(!compressor.gzip)return{body:rawBytes,encoding:null,release:null};try{return{body:await compressor.gzip(rawBytes),encoding:`gzip`,release:null}}catch(error){return log.warn(`gzip failed for chunk; sending uncompressed: %o`,error),{body:rawBytes,encoding:null,release:null}}}function prepareUnloadBody(rawBytes){let rawRelease=reserveKeepaliveBody(rawBytes.byteLength);if(rawRelease)return{body:rawBytes,encoding:null,release:rawRelease};let compressed=gzipForUnload(rawBytes);return compressed?{body:compressed,encoding:`gzip`,release:reserveKeepaliveBody(compressed.byteLength)}:{body:rawBytes,encoding:null,release:null}}function encodeReplayMeta(chunk,payload){return btoa(JSON.stringify({activityCount:payload.activityCount,eventCount:payload.eventCount,firstTs:payload.firstTs,hasFullSnapshot:payload.hasFullSnapshot,lastTs:payload.lastTs,segmentId:chunk.segmentId,windowId:chunk.windowId}))}async function deliverChunk({ctx,chunk,target,compressor,payload,trigger,unload}){let sessionId=ctx.getSessionId();if(!sessionId)return`ok`;let rawBytes=textEncoder.encode(payload.bodyJson),uncompressedBytes=rawBytes.byteLength,prepared=unload?prepareUnloadBody(rawBytes):await prepareBody(compressor,rawBytes),headers={"x-replay-meta":encodeReplayMeta(chunk,payload)};prepared.encoding===`gzip`&&(headers[`content-encoding`]=`gzip`);let keepalive=prepared.release!==null,response;try{let upload=await uploadReplayChunk(target,sessionId,prepared.body,headers,{keepalive});if(!upload.ok)return await upload.body?.cancel(),classifyRejection(upload.status);response=await upload.json()}catch(error){return log.warn(`replay chunk upload failed: %o`,error),`retryable`}finally{prepared.release?.()}let objectKey=typeof response==`object`&&response&&`objectKey`in response&&typeof response.objectKey==`string`?response.objectKey:null;if(trigger===void 0&&!unload)return`ok`;let attributes=omitUndefined({"replay.chunk.size_bytes":uncompressedBytes,"replay.chunk.event_count":payload.eventCount,"replay.chunk.uri":objectKey||void 0,"replay.chunk.compressed_bytes":prepared.encoding===`gzip`?prepared.body.byteLength:void 0,"replay.chunk.first_event_ts":payload.firstTs??void 0,"replay.chunk.last_event_ts":payload.lastTs??void 0,"replay.chunk.trigger":trigger,"replay.chunk.unload":unload||void 0,"replay.chunk.keepalive":unload?keepalive:void 0});return ctx.getTracer(REPLAY_TRACER_NAME).startSpan(`replay.chunk`,{attributes}).end(),`ok`}export{deliverChunk as n,REPLAY_TRACER_NAME as t};
1
+ import{t as createLogger}from"./log-D6Ht--tv.mjs";import{t as reserveKeepaliveBody}from"./keepalive-budget-BfoHXD04.mjs";import{t as gzipForUnload}from"./unload-gzip-WX9FyWPs.mjs";import{t as uploadReplayChunk}from"./upload-D55WVf_o.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";const log=createLogger(`replay`),REPLAY_TRACER_NAME=`@interfere/react/replay`,textEncoder=new TextEncoder,FATAL_STATUSES=new Set([401,403,413]);function classifyRejection(status){return status===409?`skipped`:FATAL_STATUSES.has(status)?`fatal`:`retryable`}async function prepareBody(compressor,rawBytes){if(!compressor.gzip)return{body:rawBytes,encoding:null,release:null};try{return{body:await compressor.gzip(rawBytes),encoding:`gzip`,release:null}}catch(error){return log.warn(`gzip failed for chunk; sending uncompressed: %o`,error),{body:rawBytes,encoding:null,release:null}}}function prepareUnloadBody(rawBytes){let rawRelease=reserveKeepaliveBody(rawBytes.byteLength);if(rawRelease)return{body:rawBytes,encoding:null,release:rawRelease};let compressed=gzipForUnload(rawBytes);return compressed?{body:compressed,encoding:`gzip`,release:reserveKeepaliveBody(compressed.byteLength)}:{body:rawBytes,encoding:null,release:null}}function encodeReplayMeta(chunk,payload){return btoa(JSON.stringify({activityCount:payload.activityCount,eventCount:payload.eventCount,firstTs:payload.firstTs,hasFullSnapshot:payload.hasFullSnapshot,lastTs:payload.lastTs,segmentId:chunk.segmentId,windowId:chunk.windowId}))}async function deliverChunk({ctx,chunk,target,compressor,payload,trigger,unload}){let sessionId=ctx.getSessionId();if(!sessionId)return`ok`;let rawBytes=textEncoder.encode(payload.bodyJson),uncompressedBytes=rawBytes.byteLength,prepared=unload?prepareUnloadBody(rawBytes):await prepareBody(compressor,rawBytes),headers={"x-replay-meta":encodeReplayMeta(chunk,payload)};prepared.encoding===`gzip`&&(headers[`content-encoding`]=`gzip`);let keepalive=prepared.release!==null,response;try{let upload=await uploadReplayChunk(target,sessionId,prepared.body,headers,{keepalive});if(!upload.ok)return await upload.body?.cancel(),classifyRejection(upload.status);response=await upload.json()}catch(error){return log.warn(`replay chunk upload failed: %o`,error),`retryable`}finally{prepared.release?.()}let objectKey=typeof response==`object`&&response&&`objectKey`in response&&typeof response.objectKey==`string`?response.objectKey:null;if(trigger===void 0&&!unload)return`ok`;let attributes=omitUndefined({"replay.chunk.size_bytes":uncompressedBytes,"replay.chunk.event_count":payload.eventCount,"replay.chunk.uri":objectKey||void 0,"replay.chunk.compressed_bytes":prepared.encoding===`gzip`?prepared.body.byteLength:void 0,"replay.chunk.first_event_ts":payload.firstTs??void 0,"replay.chunk.last_event_ts":payload.lastTs??void 0,"replay.chunk.trigger":trigger,"replay.chunk.unload":unload||void 0,"replay.chunk.keepalive":unload?keepalive:void 0});return ctx.getTracer(REPLAY_TRACER_NAME).startSpan(`replay.chunk`,{attributes}).end(),`ok`}export{deliverChunk as n,REPLAY_TRACER_NAME as t};
@@ -1,4 +1,4 @@
1
- import { a as InterfereContextValue, i as InterfereContext } from "./provider-D4QjZp3L.mjs";
1
+ import { a as InterfereContextValue, i as InterfereContext } from "./provider-vp8Aao8Q.mjs";
2
2
  import { Component, ContextType, ErrorInfo, ReactNode } from "react";
3
3
  //#region src/error-boundary.d.ts
4
4
  export interface ErrorBoundaryProps {
@@ -0,0 +1 @@
1
+ import{hrTimeToMilliseconds}from"@opentelemetry/core";function shouldExportSpan(span){return!(span.instrumentationScope.name===`@opentelemetry/instrumentation-long-task`&&hrTimeToMilliseconds(span.duration)<500)}function carriesException(span){return span.events.some(event=>event.name===`exception`)}function createExportFilterProcessor(next,onExceptionSpan){let flushScheduled=!1,flushSoon=()=>{flushScheduled||(flushScheduled=!0,queueMicrotask(()=>{flushScheduled=!1,next.forceFlush().catch(()=>{})}))};return{onStart:(span,parentContext)=>{next.onStart(span,parentContext)},onEnd:span=>{shouldExportSpan(span)&&(next.onEnd(span),carriesException(span)&&(onExceptionSpan?.(),flushSoon()))},forceFlush:async()=>next.forceFlush(),shutdown:async()=>next.shutdown()}}export{shouldExportSpan as n,createExportFilterProcessor as t};
@@ -0,0 +1 @@
1
+ import{n as fetchIngest}from"./ingest-backoff-BdBT-jss.mjs";import{n as stampSentAt}from"./sent-at-CEM8UV3W.mjs";import{t as reserveKeepaliveBody}from"./keepalive-budget-BfoHXD04.mjs";import{t as sendInKeepaliveChunks}from"./keepalive-chunks-BZv3PhHT.mjs";import{t as PRODUCER_VERSION}from"./version-CPcWUmrA.mjs";import{t as IngestLogExporter}from"./exporter-logs-BbzSiQJi.mjs";import{t as IngestMetricExporter}from"./exporter-metrics-DZYqUo6_.mjs";import{toError}from"@interfere/types/sdk/errors";import{InterfereClient,InterfereError}from"@interfere/javascript";import{TELEMETRY_EXPORT_TIMEOUT_MS,retryTelemetry}from"@interfere/helpers/retry-telemetry";import{ExportResultCode}from"@opentelemetry/core";import{JsonTraceSerializer}from"@opentelemetry/otlp-transformer";import{z}from"zod";const INGEST_IGNORE_RE=/\/drain\/v1\/(?:traces|logs|metrics)(?:\?|$)/u,AUTH_INVALID_HALT_COOLDOWN_MS=3e5,HALT_MESSAGES={release_not_found:`ingest halted: the ingest endpoint does not recognize this build's release`,public_key_rejected:`ingest paused: the ingest endpoint rejected this page's public key`};let haltReason=null,authHaltExpiresAt=0,consecutiveAuthRejections=0;function resetIngestHalt(){haltReason=null,authHaltExpiresAt=0,consecutiveAuthRejections=0}function currentHaltReason(){return haltReason===`public_key_rejected`&&Date.now()>=authHaltExpiresAt&&(haltReason=null,consecutiveAuthRejections=2),haltReason}function isIngestHalted(){return currentHaltReason()!==null}const textEncoder=new TextEncoder;function detectUnacceptableExport(error){if(currentHaltReason()!==null||error.statusCode!==422&&error.statusCode!==401)return;let body=error.body;if(typeof body==`object`&&body&&`code`in body){if(error.statusCode===422&&body.code===`RELEASE_NOT_FOUND`){haltReason=`release_not_found`,console.warn(`[interfere] the ingest endpoint does not recognize this build's release. Telemetry export is disabled for this page load. Check that source-map upload and finalization succeeded and that build and runtime use the same surface key.`);return}if(error.statusCode===401&&body.code===`AUTH_PK_INVALID`){if(consecutiveAuthRejections+=1,consecutiveAuthRejections<3)return;haltReason=`public_key_rejected`,authHaltExpiresAt=Date.now()+AUTH_INVALID_HALT_COOLDOWN_MS,console.warn(`[interfere] the ingest endpoint rejected this page's public key ${consecutiveAuthRejections} times in a row — telemetry export is paused for ${AUTH_INVALID_HALT_COOLDOWN_MS/6e4} minutes, then retried once. Check that INTERFERE_PUBLIC_KEY matches an active surface; a deleted surface's key stays rejected until the page is rebuilt with the new key.`)}}}function makeSender(input,signal){let client=new InterfereClient({...input.clientOptions,maxRetries:0,timeoutInSeconds:TELEMETRY_EXPORT_TIMEOUT_MS/1e3,fetch:Object.assign(async(url,init)=>fetchIngest(url,async()=>{let body=init?.body,bytes=typeof body==`string`?textEncoder.encode(body).byteLength:0,dispatch=async(abortSignal,keepalive)=>globalThis.fetch(url,{...init,headers:stampSentAt(new Headers(init?.headers)),credentials:`omit`,keepalive,signal:abortSignal});return retryTelemetry(async abortSignal=>{let release=reserveKeepaliveBody(bytes,32e3);if(release===null)return dispatch(abortSignal,!1);try{return await dispatch(abortSignal,!0)}catch(error){if(!(error instanceof TypeError)||abortSignal.aborted)throw error}finally{release()}return dispatch(abortSignal,!1)},init?.signal)}),globalThis.fetch)});return((payload,resultCallback)=>{if(!payload||payload.byteLength===0){resultCallback({code:ExportResultCode.SUCCESS});return}let reason=currentHaltReason();if(reason!==null){resultCallback({code:ExportResultCode.FAILED,error:Error(HALT_MESSAGES[reason])});return}(async()=>{try{let body=z.record(z.string(),z.unknown()).parse(JSON.parse(new TextDecoder().decode(payload)));await client.drain.otlpExport({signal,body},{headers:{"x-interfere-producer-version":PRODUCER_VERSION}}),consecutiveAuthRejections=0,resultCallback({code:ExportResultCode.SUCCESS})}catch(error){error instanceof InterfereError&&detectUnacceptableExport(error),resultCallback({code:ExportResultCode.FAILED,error:toError(error)})}})()})}var IngestTraceExporter=class{send;constructor(send){this.send=send}export(spans,resultCallback){if(spans.length===0){resultCallback({code:ExportResultCode.SUCCESS});return}sendInKeepaliveChunks(spans,chunk=>JsonTraceSerializer.serializeRequest(chunk),this.send,resultCallback)}async shutdown(){return Promise.resolve()}async forceFlush(){return Promise.resolve()}};function createTraceExporter(input){return new IngestTraceExporter(makeSender(input,`traces`))}function createMetricExporter(input,gatedResourceAttributes){return new IngestMetricExporter(makeSender(input,`metrics`),gatedResourceAttributes)}function createLogExporter(input){return new IngestLogExporter(makeSender(input,`logs`))}export{isIngestHalted as a,createTraceExporter as i,createLogExporter as n,resetIngestHalt as o,createMetricExporter as r,INGEST_IGNORE_RE as t};
@@ -0,0 +1 @@
1
+ import{t as sendInKeepaliveChunks}from"./keepalive-chunks-BZv3PhHT.mjs";import{ExportResultCode}from"@opentelemetry/core";import{JsonLogsSerializer}from"@opentelemetry/otlp-transformer";var IngestLogExporter=class{send;constructor(send){this.send=send}export(logs,resultCallback){if(logs.length===0){resultCallback({code:ExportResultCode.SUCCESS});return}sendInKeepaliveChunks(logs,chunk=>JsonLogsSerializer.serializeRequest(chunk),this.send,resultCallback)}async shutdown(){return Promise.resolve()}async forceFlush(){return Promise.resolve()}};export{IngestLogExporter as t};
@@ -0,0 +1,4 @@
1
+ import "./instrumentations-zBdPJHog.mjs";
2
+ import "./navigation-CkiV6lJY.mjs";
3
+ import "./provider-Dy0mVCx5.mjs";
4
+ import "./web-vitals-x8y70B5x.mjs";
@@ -0,0 +1 @@
1
+ import{r as ingestQueueAnswerSchema,t as INGEST_QUEUE_QUERY}from"./sw-queue-protocol-DnTSOWxy.mjs";let consecutiveFailures=0,blockedUntil=0,queueState=null;function resetIngestBackoff(){consecutiveFailures=0,blockedUntil=0,queueState=null}var IngestBackoffError=class extends Error{constructor(){super(`Interfere ingest is backing off after a network failure; request not sent`),this.name=`IngestBackoffError`}};function noteNetworkFailure(){Date.now()<blockedUntil||(consecutiveFailures+=1,blockedUntil=Date.now()+Math.min(5e3*2**(consecutiveFailures-1),6e5))}function absoluteUrl(input){try{return new URL(input instanceof Request?input.url:String(input),globalThis.location.href).href}catch{return null}}function currentController(){try{return`serviceWorker`in navigator?navigator.serviceWorker.controller:null}catch{return null}}async function askIngestQueue(state,url){let{promise,resolve}=Promise.withResolvers(),channel=new MessageChannel;channel.port1.addEventListener(`message`,event=>{let answer=ingestQueueAnswerSchema.safeParse(event.data);state.responsive=!0,resolve(answer.success&&answer.data.accepted),channel.port1.close()}),channel.port1.start();let query={type:INGEST_QUEUE_QUERY,url};try{state.controller.postMessage(query,[channel.port2])}catch{channel.port1.close(),resolve(!1)}return promise}function queryIngestQueue(input,controller){let url=absoluteUrl(input);if(!controller||url===null)return null;queueState?.controller!==controller&&(queueState={answers:new Map,controller,responsive:!1});let state=queueState,answer=state.answers.get(url);return!answer&&state.answers.size<32&&(answer=askIngestQueue(state,url),state.answers.set(url,answer)),answer?{answer,state}:null}async function ingestQueueAccepts(query){if(!query?.state.responsive)return!1;let timer,timeout=new Promise(resolve=>{timer=setTimeout(()=>{resolve(!1)},1e3)});try{return await Promise.race([query.answer,timeout])}finally{clearTimeout(timer)}}async function fetchIngest(url,send,controller=currentController()){let query=queryIngestQueue(url,controller),viaQueue=!1;if(Date.now()<blockedUntil&&(viaQueue=await ingestQueueAccepts(query),!viaQueue))throw new IngestBackoffError;let response;try{response=await send()}catch(error){throw error instanceof TypeError&&noteNetworkFailure(),error}return viaQueue||(consecutiveFailures=0,blockedUntil=0),response}export{fetchIngest as n,resetIngestBackoff as r,IngestBackoffError as t};
@@ -0,0 +1 @@
1
+ import{t as DEFAULT_PRIVACY_POLICY}from"./privacy-CRuL0X8r.mjs";import{t as THIRD_PARTY_IGNORE}from"./third-party-hosts-CYOuLL_s.mjs";import{n as describeActionable,r as isActionable}from"./actionable-DOmVf_ib.mjs";import{i as stampUrlAttrs,n as ATTR_URL_FULL,r as ATTR_URL_PATH}from"./url-attrs-BdcyE2n6.mjs";import{t as stampHttpSpanRoute}from"./http-span-route-t2gig-KI.mjs";import{t as createClickSpanGate}from"./click-span-gate-6dNMhjc7.mjs";import{n as installCorsGuard}from"./cors-guard-CwkqEjzL.mjs";import{i as sameSiteMatcher,n as knownBackendMatchers,t as hostMatcher}from"./propagation-targets-BXDetg0k.mjs";import{n as settleFetchFailure,r as settleXhrFailure,t as createPageExitWatch}from"./network-failure-GVLV_sUF.mjs";import{MECHANISM_TYPE}from"@interfere/types/sdk/errors";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{BrowserNavigationInstrumentation,defaultSanitizeUrl}from"@opentelemetry/instrumentation-browser-navigation";import{DocumentLoadInstrumentation}from"@opentelemetry/instrumentation-document-load";import{FetchInstrumentation}from"@opentelemetry/instrumentation-fetch";import{LongTaskInstrumentation}from"@opentelemetry/instrumentation-long-task";import{UserInteractionInstrumentation}from"@opentelemetry/instrumentation-user-interaction";import{XMLHttpRequestInstrumentation}from"@opentelemetry/instrumentation-xml-http-request";import{getElementXPath}from"@opentelemetry/sdk-trace-web";const DEFAULT_FAILURE_RANGES=[[400,599]];function resolveFailureRanges(opt){if(opt===!1)return null;if(opt===void 0||opt===!0)return DEFAULT_FAILURE_RANGES;let codes=opt.statusCodes;return codes&&codes.length>0?codes:DEFAULT_FAILURE_RANGES}function createFailureGate(){let seen=new Set,windowStart=0,windowCount=0;return(key=>{if(seen.has(key))return!1;let now=Date.now();return now-windowStart>6e4&&(windowStart=now,windowCount=0),windowCount>=20?!1:(seen.size>=100&&seen.clear(),seen.add(key),windowCount+=1,!0)})}function failureKey(method,discriminator,url){let path;try{path=new URL(url).pathname}catch{path=url}return`${method} ${discriminator} ${path}`}function statusMatches(status,ranges){for(let range of ranges)if(typeof range==`number`){if(status===range)return!0}else if(status>=range[0]&&status<=range[1])return!0;return!1}function recordHttpFailure(span,status,method,url,mechanism){span.addEvent(`exception`,{"exception.message":`HTTP ${status} ${method} ${url}`,"exception.type":`HttpResponseError`,"interfere.exception.handled":!1,"interfere.exception.kind":`error`,"interfere.exception.mechanism":mechanism})}function maybeCaptureFetchFailure(span,result,failureRanges,method,url,gate){if(!failureRanges)return;let status=result?.status;typeof status!=`number`||status<=0||!statusMatches(status,failureRanges)||(!gate||gate(failureKey(method,status,url)))&&recordHttpFailure(span,status,method,url,MECHANISM_TYPE.browser.fetchFailedResponse)}function applyFetchSpanAttrs(span,request,result,failureRanges,pageExit,isTrackedUrl,resolveRoute,gate){let url=resolveFetchUrl(span,request,result);if(!url)return;let parsed;try{parsed=new URL(url)}catch{return}span.setAttribute(ATTR_URL_PATH,parsed.pathname);let tracked=isTrackedUrl(url),method=resolveFetchMethod(request);if(tracked){if(stampHttpSpanRoute(span,method,parsed.pathname,resolveRoute),isPrefetchRequest(request))return;result instanceof Response?maybeCaptureFetchFailure(span,result,failureRanges,method,url,gate):failureRanges&&settleFetchFailure(span,request,result,pageExit,method,url,()=>!gate||gate(failureKey(method,`network`,url)))}}function applyXhrSpanAttrs(span,xhr,failureRanges,pageExit,isTrackedUrl,gate,resolveRoute){let url=xhr.responseURL||spanUrlFull(span);if(!(url&&isTrackedUrl(url)))return;let parsed;try{parsed=new URL(url)}catch{return}let method=isReadableSpan(span)?String(span.attributes[`http.request.method`]??span.attributes[`http.method`]??`XHR`):`XHR`;if(span.setAttribute(ATTR_URL_PATH,parsed.pathname),stampHttpSpanRoute(span,method,parsed.pathname,resolveRoute),!failureRanges)return;let{status}=xhr;if(typeof status==`number`){if(status===0){settleXhrFailure(span,pageExit,url,()=>!gate||gate(failureKey(`XHR`,`network`,url)));return}statusMatches(status,failureRanges)&&(!gate||gate(failureKey(`XHR`,status,url)))&&recordHttpFailure(span,status,`XHR`,url,MECHANISM_TYPE.browser.xhrFailedResponse)}}function resolveFetchUrl(span,request,result){return responseUrl(result)??requestUrl(request)??spanUrlFull(span)}function isReadableSpan(span){return`attributes`in span}function spanUrlFull(span){if(!isReadableSpan(span))return null;let url=span.attributes[`url.full`]??span.attributes[`http.url`];return typeof url==`string`?url:null}function responseUrl(result){return result instanceof Response&&result.url?result.url:null}function requestUrl(request){return typeof request==`string`?request:readStringProp(request,`url`)??readStringProp(request,`href`)}function resolveFetchMethod(request){return readStringProp(request,`method`)??`GET`}function readStringProp(value,key){if(!(typeof value==`object`&&value&&key in value))return null;let prop=Reflect.get(value,key);return typeof prop==`string`?prop:null}const testOnlyApplyFetchSpanAttrs=applyFetchSpanAttrs,testOnlyApplyXhrSpanAttrs=applyXhrSpanAttrs,testOnlyResolveFailureRanges=resolveFailureRanges,testOnlyCreateFailureGate=createFailureGate,NEVER_MATCH=/^$/u,ESCAPE_RE=/[.*+?^${}()|[\]\\]/gu;function sameOriginPattern(){if(typeof window>`u`)return NEVER_MATCH;let{protocol,host}=globalThis.location;return RegExp(`^${protocol}//${host.replace(ESCAPE_RE,String.raw`\$&`)}`,`u`)}function pageSameSiteMatcher(){return typeof window>`u`?null:sameSiteMatcher(globalThis.location.hostname)}function stampInteractionAttrs(eventType,element,span,policy){let desc=describeActionable(element,policy);span.setAttribute(`ui.event_type`,eventType),span.setAttribute(`ui.target.tag`,desc.tag),desc.privacy&&(span.setAttribute(`ui.target.privacy`,desc.privacy),span.setAttribute(`target_xpath`,getElementXPath(element,!1))),desc.label&&span.setAttribute(`ui.target.label`,desc.label),desc.id&&span.setAttribute(`ui.target.id`,desc.id),desc.name&&span.setAttribute(`ui.target.name`,desc.name),desc.role&&span.setAttribute(`ui.target.role`,desc.role),desc.ariaLabel&&span.setAttribute(`ui.target.aria_label`,desc.ariaLabel),desc.text&&span.setAttribute(`ui.target.text`,desc.text)}const PREFETCH_HEADER_NAMES=[`next-router-prefetch`,`next-router-segment-prefetch`];function isPrefetchRequest(request){if(typeof request==`string`||request instanceof URL)return!1;let headers;try{headers=typeof Request<`u`&&request instanceof Request?request.headers:new Headers(request.headers)}catch{return!1}return PREFETCH_HEADER_NAMES.some(name=>headers.has(name))||headers.get(`purpose`)===`prefetch`||headers.get(`sec-purpose`)?.includes(`prefetch`)===!0}function registerBundledInstrumentations(input){let{tracerProvider,loggerProvider,ignoreUrls,apiHosts=[],backendHosts=[],propagateContextUrls=[],privacyPolicy=DEFAULT_PRIVACY_POLICY,isInteractionCaptureEnabled=()=>!0,redactUrl=url=>url}=input,{resolveRoute}=input,origin=sameOriginPattern(),sameSite=pageSameSiteMatcher(),propagateMatchers=[...sameSite?[sameSite]:[],...knownBackendMatchers(backendHosts),...apiHosts.map(host=>hostMatcher(host)),...propagateContextUrls],fetchIgnore=[...ignoreUrls,...THIRD_PARTY_IGNORE],failureRanges=resolveFailureRanges(input.captureFailedRequests),failureGate=createFailureGate(),pageExit=createPageExitWatch();function isTrackedUrl(url){return origin.test(url)||propagateMatchers.some(re=>re instanceof RegExp?re.test(url):url.includes(re))}let corsGuard=typeof window>`u`?null:installCorsGuard(),propagateTraceHeaderCorsUrls=[origin,...corsGuard?.guardPatterns(propagateMatchers)??propagateMatchers],pageEventsEnabled=!1,admitClick=createClickSpanGate(),coreInstrumentations=[new FetchInstrumentation({applyCustomAttributesOnSpan:(span,request,result)=>{applyFetchSpanAttrs(span,request,result,failureRanges,pageExit,isTrackedUrl,resolveRoute,failureGate)},ignoreUrls:fetchIgnore,measureRequestSize:!0,propagateTraceHeaderCorsUrls,requestHook:(span,request)=>{isPrefetchRequest(request)&&span.setAttribute(`http.request.prefetch`,!0)}}),new XMLHttpRequestInstrumentation({applyCustomAttributesOnSpan:(span,xhr)=>{applyXhrSpanAttrs(span,xhr,failureRanges,pageExit,isTrackedUrl,failureGate,resolveRoute)},ignoreUrls:fetchIgnore,propagateTraceHeaderCorsUrls}),new LongTaskInstrumentation({observerCallback:(span,info)=>{stampUrlAttrs(span,resolveRoute);let containerType=info.longtaskEntry.attribution[0]?.containerType;containerType&&span.setAttribute(`longtask.container_type`,containerType)}}),new UserInteractionInstrumentation({eventNames:[`click`,`submit`],shouldPreventSpanCreation:(eventType,element,span)=>!(pageEventsEnabled&&isInteractionCaptureEnabled())||eventType===`click`&&!(isActionable(element)&&admitClick(element))||(stampInteractionAttrs(eventType,element,span,privacyPolicy),stampUrlAttrs(span,resolveRoute),!1)})],pageEventsInstrumentations=[new DocumentLoadInstrumentation({applyCustomAttributesOnSpan:{resourceFetch:(span,entry)=>{let name=entry?.name;if(typeof name!=`string`)return;let url;try{url=new URL(name)}catch{return}let isCrossOrigin=typeof window<`u`&&url.origin!==globalThis.location.origin;span.updateName(isCrossOrigin?`resource: ${url.host}${url.pathname}`:`resource: ${url.pathname}`),span.setAttribute(ATTR_URL_FULL,name),span.setAttribute(ATTR_URL_PATH,url.pathname),span.setAttribute(`server.address`,url.host)}},enabled:!1}),new BrowserNavigationInstrumentation({enabled:!1,sanitizeUrl:url=>redactUrl(defaultSanitizeUrl(url))})],unregisterCore=registerInstrumentations(omitUndefined({tracerProvider,loggerProvider,instrumentations:coreInstrumentations})),unregisterPageEvents=null,setPageEventsEnabled=enabled=>{if(pageEventsEnabled=enabled,enabled){unregisterPageEvents??=registerInstrumentations(omitUndefined({tracerProvider,loggerProvider,instrumentations:pageEventsInstrumentations}));return}unregisterPageEvents?.(),unregisterPageEvents=null};return{dispose:()=>{setPageEventsEnabled(!1),unregisterCore(),corsGuard?.dispose(),pageExit.dispose()},propagationDisabledHosts:()=>corsGuard?.disabledHosts()??[],setPageEventsEnabled}}export{testOnlyResolveFailureRanges as a,testOnlyCreateFailureGate as i,testOnlyApplyFetchSpanAttrs as n,testOnlyApplyXhrSpanAttrs as r,registerBundledInstrumentations as t};
@@ -33,9 +33,12 @@ declare const testOnlyCreateFailureGate: typeof createFailureGate;
33
33
  interface InstrumentationsInput {
34
34
  /**
35
35
  * Hostnames the fetch + XHR instrumentations inject `traceparent` onto,
36
- * matched by host (any path/port/scheme). Same-origin always propagates.
36
+ * matched by host (any path/port/scheme), in addition to the page's own
37
+ * site and {@link backendHosts}.
37
38
  */
38
39
  apiHosts?: string[];
40
+ /** The organization's backend hostnames from Interfere remote config. */
41
+ backendHosts?: string[];
39
42
  /** See {@link CaptureFailedRequestsOption}. On by default. */
40
43
  captureFailedRequests?: CaptureFailedRequestsOption;
41
44
  /**
@@ -72,6 +75,8 @@ interface InstrumentationsInput {
72
75
  }
73
76
  interface BundledInstrumentations {
74
77
  dispose: () => void;
78
+ /** Hosts whose CORS preflight rejected the trace headers, in the shape of remote config `backendHosts`. */
79
+ propagationDisabledHosts: () => string[];
75
80
  /** Idempotent toggle for the analytics-consent-gated pageEvents signals. */
76
81
  setPageEventsEnabled: (enabled: boolean) => void;
77
82
  }
@@ -84,6 +89,7 @@ interface BundledInstrumentations {
84
89
  */
85
90
  declare function registerBundledInstrumentations(input: InstrumentationsInput): {
86
91
  dispose: () => void;
92
+ propagationDisabledHosts: () => string[];
87
93
  setPageEventsEnabled: (enabled: boolean) => void;
88
94
  };
89
95
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as InterfereContextValue, i as InterfereContext } from "../../provider-D4QjZp3L.mjs";
1
+ import { a as InterfereContextValue, i as InterfereContext } from "../../provider-vp8Aao8Q.mjs";
2
2
  import { Component, ContextType, ReactNode } from "react";
3
3
  //#region src/internal/capture/capture-boundary.d.ts
4
4
  interface CaptureBoundaryProps {
@@ -1,4 +1,4 @@
1
- import { s as Kernel } from "../../provider-D4QjZp3L.mjs";
1
+ import { s as Kernel } from "../../provider-vp8Aao8Q.mjs";
2
2
  import { ErrorMechanism } from "@interfere/types/sdk/plugins/payload/errors";
3
3
  //#region src/internal/capture/capture.d.ts
4
4
  /**
@@ -1,3 +1,4 @@
1
+ import { n as IngestQueueController } from "../../sw-queue-protocol-DqP1EQtQ.mjs";
1
2
  //#region src/internal/ingest-backoff/ingest-backoff.d.ts
2
3
  /** Test-only reset of the ingest network backoff. */
3
4
  export declare function resetIngestBackoff(): void;
@@ -6,7 +7,7 @@ export declare class IngestBackoffError extends Error {
6
7
  constructor();
7
8
  }
8
9
  /**
9
- * Sends one ingest request unless an earlier network failure is still backing off. A fetch rejection with a `TypeError` (no HTTP response: blocked, offline or unreachable) pauses every ingest request on the page for 5 s, doubling per consecutive failure up to 10 minutes. Any HTTP response clears the backoff.
10
+ * Sends one ingest request to `url` unless an earlier network failure is still backing off. A fetch rejection with a `TypeError` (no HTTP response: blocked, offline or unreachable) pauses every ingest request on the page for 5 s, doubling per consecutive failure up to 10 minutes. Any HTTP response clears the backoff. During a pause, a request still goes out when the page's controlling service worker runs `installIngestQueue` and confirms it queues `url`, because that worker answers a network failure with a queued 202 instead of a page-visible error. `controller` defaults to the page's controlling service worker.
10
11
  */
11
- export declare function fetchIngest(send: () => Promise<Response>): Promise<Response>;
12
+ export declare function fetchIngest(url: RequestInfo | URL, send: () => Promise<Response>, controller?: IngestQueueController | null): Promise<Response>;
12
13
  //#endregion
@@ -1 +1 @@
1
- import{n as fetchIngest,r as resetIngestBackoff,t as IngestBackoffError}from"../../ingest-backoff-B1OeEV3h.mjs";export{IngestBackoffError,fetchIngest,resetIngestBackoff};
1
+ import{n as fetchIngest,r as resetIngestBackoff,t as IngestBackoffError}from"../../ingest-backoff-BdBT-jss.mjs";export{IngestBackoffError,fetchIngest,resetIngestBackoff};
@@ -1,4 +1,4 @@
1
- import { s as Kernel } from "../provider-D4QjZp3L.mjs";
1
+ import { s as Kernel } from "../provider-vp8Aao8Q.mjs";
2
2
  //#region src/internal/kernel-registry.d.ts
3
3
  export declare function registerKernel(kernel: Kernel): void;
4
4
  export declare function unregisterKernel(kernel: Kernel): void;
@@ -1,6 +1,6 @@
1
1
  import { r as PrivacyOptions } from "../privacy-CPKosXDP.mjs";
2
- import { _ as readReleaseSlugFromGlobals, c as KernelConsent, d as KernelInternalOptions, f as KernelOptions, g as createKernel, h as buildSdkStack, l as KernelDevice, m as TracingOptions, p as KernelSession, s as Kernel, u as KernelIdentity } from "../provider-D4QjZp3L.mjs";
3
- import { i as HttpStatusCodeRange, n as CaptureFailedRequestsOption, r as CaptureFailedRequestsOptions } from "../instrumentations-S-BCpguB.mjs";
2
+ import { _ as readReleaseSlugFromGlobals, c as KernelConsent, d as KernelInternalOptions, f as KernelOptions, g as createKernel, h as buildSdkStack, l as KernelDevice, m as TracingOptions, p as KernelSession, s as Kernel, u as KernelIdentity } from "../provider-vp8Aao8Q.mjs";
3
+ import { i as HttpStatusCodeRange, n as CaptureFailedRequestsOption, r as CaptureFailedRequestsOptions } from "../instrumentations-zBdPJHog.mjs";
4
4
  import { t as RecordExceptionOpts } from "../exception-span-zN1tvBdh.mjs";
5
5
  import { t as isEnabledByEnvironment } from "../environment-CtCFKD2N.mjs";
6
6
  export { type CaptureFailedRequestsOption, type CaptureFailedRequestsOptions, type HttpStatusCodeRange, Kernel, KernelConsent, KernelDevice, KernelIdentity, KernelInternalOptions, KernelOptions, KernelSession, type PrivacyOptions, type RecordExceptionOpts, TracingOptions, buildSdkStack, createKernel, isEnabledByEnvironment, readReleaseSlugFromGlobals };
@@ -1 +1 @@
1
- import{t as isEnabledByEnvironment}from"../environment-CoEXhF1a.mjs";import{i as readReleaseSlugFromGlobals,n as buildSdkStack,r as createKernel,t as Kernel}from"../kernel-BVG-7Zau.mjs";export{Kernel,buildSdkStack,createKernel,isEnabledByEnvironment,readReleaseSlugFromGlobals};
1
+ import{t as isEnabledByEnvironment}from"../environment-CoEXhF1a.mjs";import{i as readReleaseSlugFromGlobals,n as buildSdkStack,r as createKernel,t as Kernel}from"../kernel-BZI0jyJI.mjs";export{Kernel,buildSdkStack,createKernel,isEnabledByEnvironment,readReleaseSlugFromGlobals};
@@ -2,8 +2,8 @@ import { ReadableSpan, SpanProcessor } from "@opentelemetry/sdk-trace-base";
2
2
  //#region src/internal/otel/export-filter.d.ts
3
3
  /** Whether a finished span is worth exporting. Long tasks under 500 ms are dropped. */
4
4
  export declare function shouldExportSpan(span: ReadableSpan): boolean;
5
- /** Forwards only exportable spans to the wrapped export processor, and flushes it as soon as a span carrying an exception is queued. */
6
- export declare function createExportFilterProcessor(next: SpanProcessor): {
5
+ /** Forwards only exportable spans to the wrapped export processor, flushes it as soon as a span carrying an exception is queued, and reports that span to `onExceptionSpan`. */
6
+ export declare function createExportFilterProcessor(next: SpanProcessor, onExceptionSpan?: () => void): {
7
7
  onStart: (span: import("@opentelemetry/sdk-trace-base").Span, parentContext: import("@opentelemetry/api").Context) => void;
8
8
  onEnd: (span: ReadableSpan) => void;
9
9
  forceFlush: () => Promise<void>;
@@ -1 +1 @@
1
- import{n as shouldExportSpan,t as createExportFilterProcessor}from"../../export-filter-Cixywxpu.mjs";export{createExportFilterProcessor,shouldExportSpan};
1
+ import{n as shouldExportSpan,t as createExportFilterProcessor}from"../../export-filter-CnyAaPct.mjs";export{createExportFilterProcessor,shouldExportSpan};
@@ -1 +1 @@
1
- import{t as IngestLogExporter}from"../../exporter-logs-DS2AXWnV.mjs";export{IngestLogExporter};
1
+ import{t as IngestLogExporter}from"../../exporter-logs-BbzSiQJi.mjs";export{IngestLogExporter};
@@ -1 +1 @@
1
- import{a as isIngestHalted,i as createTraceExporter,n as createLogExporter,o as resetIngestHalt,r as createMetricExporter,t as INGEST_IGNORE_RE}from"../../exporter-De0h9YP5.mjs";export{INGEST_IGNORE_RE,createLogExporter,createMetricExporter,createTraceExporter,isIngestHalted,resetIngestHalt};
1
+ import{a as isIngestHalted,i as createTraceExporter,n as createLogExporter,o as resetIngestHalt,r as createMetricExporter,t as INGEST_IGNORE_RE}from"../../exporter-BtHqkV3R.mjs";export{INGEST_IGNORE_RE,createLogExporter,createMetricExporter,createTraceExporter,isIngestHalted,resetIngestHalt};
@@ -1,7 +1,7 @@
1
- import { a as InstrumentationsInput, i as HttpStatusCodeRange, n as CaptureFailedRequestsOption, o as registerBundledInstrumentations, r as CaptureFailedRequestsOptions, t as BundledInstrumentations } from "../../instrumentations-S-BCpguB.mjs";
1
+ import { a as InstrumentationsInput, i as HttpStatusCodeRange, n as CaptureFailedRequestsOption, o as registerBundledInstrumentations, r as CaptureFailedRequestsOptions, t as BundledInstrumentations } from "../../instrumentations-zBdPJHog.mjs";
2
2
  import { a as seedPageScope, i as installNavigationScope, n as PAGE_SCOPE_MAX_AGE_MS, r as createPageScopeRotator, t as NavigationScopeInput } from "../../navigation-CkiV6lJY.mjs";
3
3
  import { t as readPropagationFromDocument } from "../../propagation-CssinKCy.mjs";
4
- import { n as OtelProviderInput, r as buildOtelProvider, t as OtelProviderHandle } from "../../provider-cUByhzgv.mjs";
4
+ import { n as OtelProviderInput, r as buildOtelProvider, t as OtelProviderHandle } from "../../provider-Dy0mVCx5.mjs";
5
5
  import { n as captureWebVitals } from "../../web-vitals-x8y70B5x.mjs";
6
- import "../../index-DpkTHU1a.mjs";
6
+ import "../../index-C3K6oR4l.mjs";
7
7
  export { type BundledInstrumentations, type CaptureFailedRequestsOption, type CaptureFailedRequestsOptions, type HttpStatusCodeRange, type InstrumentationsInput, type NavigationScopeInput, type OtelProviderHandle, type OtelProviderInput, PAGE_SCOPE_MAX_AGE_MS, buildOtelProvider, captureWebVitals, createPageScopeRotator, installNavigationScope, readPropagationFromDocument, registerBundledInstrumentations, seedPageScope };
@@ -1 +1 @@
1
- import{t as registerBundledInstrumentations}from"../../instrumentations-NN81kslu.mjs";import{i as seedPageScope,n as createPageScopeRotator,r as installNavigationScope,t as PAGE_SCOPE_MAX_AGE_MS}from"../../navigation-DwkvuhFR.mjs";import{t as readPropagationFromDocument}from"../../propagation-DVcqCu_E.mjs";import{t as buildOtelProvider}from"../../provider-CElaujE6.mjs";import{t as captureWebVitals}from"../../web-vitals-CxXDUgpl.mjs";export{PAGE_SCOPE_MAX_AGE_MS,buildOtelProvider,captureWebVitals,createPageScopeRotator,installNavigationScope,readPropagationFromDocument,registerBundledInstrumentations,seedPageScope};
1
+ import{t as registerBundledInstrumentations}from"../../instrumentations-qhx6Oc_F.mjs";import{i as seedPageScope,n as createPageScopeRotator,r as installNavigationScope,t as PAGE_SCOPE_MAX_AGE_MS}from"../../navigation-DwkvuhFR.mjs";import{t as readPropagationFromDocument}from"../../propagation-DVcqCu_E.mjs";import{t as buildOtelProvider}from"../../provider-B8YtuhDX.mjs";import{t as captureWebVitals}from"../../web-vitals-CxXDUgpl.mjs";export{PAGE_SCOPE_MAX_AGE_MS,buildOtelProvider,captureWebVitals,createPageScopeRotator,installNavigationScope,readPropagationFromDocument,registerBundledInstrumentations,seedPageScope};
@@ -0,0 +1,26 @@
1
+ //#region src/internal/otel/instrumentations/cors-guard.d.ts
2
+ export declare const ATTR_TRACE_PROPAGATION: "interfere.trace_propagation";
3
+ export interface CorsGuard {
4
+ /** Origins whose CORS preflight rejected the trace headers this session. */
5
+ disabledHosts: () => string[];
6
+ dispose: () => void;
7
+ /** Wraps propagation patterns so they never match a disabled origin. */
8
+ guardPatterns: (patterns: readonly (string | RegExp)[]) => RegExp[];
9
+ }
10
+ declare class OriginGuardedPattern extends RegExp {
11
+ #private;
12
+ constructor(pattern: RegExp, isDisabled: (url: string) => boolean);
13
+ [Symbol.match](value: string): RegExpMatchArray | null;
14
+ }
15
+ /**
16
+ * Wraps `fetch` beneath the OTel fetch instrumentation. A cross-origin request
17
+ * carrying trace headers to an origin not yet seen to accept them is retried
18
+ * once without them when it fails at the network layer; a successful retry
19
+ * disables propagation to that origin for the session and warns once.
20
+ */
21
+ export declare function installCorsGuard(): {
22
+ disabledHosts: () => string[];
23
+ dispose: () => void;
24
+ guardPatterns: (patterns: readonly (string | RegExp)[]) => OriginGuardedPattern[];
25
+ };
26
+ //#endregion
@@ -0,0 +1 @@
1
+ import{n as installCorsGuard,t as ATTR_TRACE_PROPAGATION}from"../../../cors-guard-CwkqEjzL.mjs";export{ATTR_TRACE_PROPAGATION,installCorsGuard};
@@ -1,2 +1,2 @@
1
- import { a as InstrumentationsInput, c as testOnlyApplyXhrSpanAttrs, i as HttpStatusCodeRange, l as testOnlyCreateFailureGate, n as CaptureFailedRequestsOption, o as registerBundledInstrumentations, r as CaptureFailedRequestsOptions, s as testOnlyApplyFetchSpanAttrs, t as BundledInstrumentations, u as testOnlyResolveFailureRanges } from "../../../instrumentations-S-BCpguB.mjs";
1
+ import { a as InstrumentationsInput, c as testOnlyApplyXhrSpanAttrs, i as HttpStatusCodeRange, l as testOnlyCreateFailureGate, n as CaptureFailedRequestsOption, o as registerBundledInstrumentations, r as CaptureFailedRequestsOptions, s as testOnlyApplyFetchSpanAttrs, t as BundledInstrumentations, u as testOnlyResolveFailureRanges } from "../../../instrumentations-zBdPJHog.mjs";
2
2
  export { BundledInstrumentations, CaptureFailedRequestsOption, CaptureFailedRequestsOptions, HttpStatusCodeRange, InstrumentationsInput, registerBundledInstrumentations, testOnlyApplyFetchSpanAttrs, testOnlyApplyXhrSpanAttrs, testOnlyCreateFailureGate, testOnlyResolveFailureRanges };
@@ -1 +1 @@
1
- import{a as testOnlyResolveFailureRanges,i as testOnlyCreateFailureGate,n as testOnlyApplyFetchSpanAttrs,r as testOnlyApplyXhrSpanAttrs,t as registerBundledInstrumentations}from"../../../instrumentations-NN81kslu.mjs";export{registerBundledInstrumentations,testOnlyApplyFetchSpanAttrs,testOnlyApplyXhrSpanAttrs,testOnlyCreateFailureGate,testOnlyResolveFailureRanges};
1
+ import{a as testOnlyResolveFailureRanges,i as testOnlyCreateFailureGate,n as testOnlyApplyFetchSpanAttrs,r as testOnlyApplyXhrSpanAttrs,t as registerBundledInstrumentations}from"../../../instrumentations-qhx6Oc_F.mjs";export{registerBundledInstrumentations,testOnlyApplyFetchSpanAttrs,testOnlyApplyXhrSpanAttrs,testOnlyCreateFailureGate,testOnlyResolveFailureRanges};
@@ -0,0 +1,6 @@
1
+ //#region src/internal/otel/instrumentations/propagation-targets.d.ts
2
+ export declare function registrableDomain(host: string): string | null;
3
+ export declare function hostMatcher(host: string): RegExp;
4
+ export declare function sameSiteMatcher(pageHostname: string): RegExp | null;
5
+ export declare function knownBackendMatchers(hosts: readonly string[]): RegExp[];
6
+ //#endregion
@@ -0,0 +1 @@
1
+ import{i as sameSiteMatcher,n as knownBackendMatchers,r as registrableDomain,t as hostMatcher}from"../../../propagation-targets-BXDetg0k.mjs";export{hostMatcher,knownBackendMatchers,registrableDomain,sameSiteMatcher};
@@ -0,0 +1,6 @@
1
+ import { r as SignalSender } from "../../exporter-logs-DMr5-1Yi.mjs";
2
+ import { ExportResult } from "@opentelemetry/core";
3
+ //#region src/internal/otel/keepalive-chunks.d.ts
4
+ /** Sends `items` as one request, or as keepalive-sized requests while the page is hidden, and reports one result: the first failure, else success. */
5
+ export declare function sendInKeepaliveChunks<T>(items: T[], serialize: (items: T[]) => Uint8Array | undefined, send: SignalSender, resultCallback: (result: ExportResult) => void): void;
6
+ //#endregion
@@ -0,0 +1 @@
1
+ import{t as sendInKeepaliveChunks}from"../../keepalive-chunks-BZv3PhHT.mjs";export{sendInKeepaliveChunks};
@@ -1,2 +1,2 @@
1
- import { n as PageScopeRotator, t as PageScopeContextManager } from "../../page-scope-context-manager-r92ZMJok.mjs";
1
+ import { n as PageScopeRotator, t as PageScopeContextManager } from "../../page-scope-context-manager-DUhBvuAz.mjs";
2
2
  export { PageScopeContextManager, PageScopeRotator };
@@ -1 +1 @@
1
- import{t as PageScopeContextManager}from"../../page-scope-context-manager-DhArvVJ_.mjs";export{PageScopeContextManager};
1
+ import{t as PageScopeContextManager}from"../../page-scope-context-manager-Bs-m4fv7.mjs";export{PageScopeContextManager};
@@ -1,2 +1,2 @@
1
- import { n as OtelProviderInput, r as buildOtelProvider, t as OtelProviderHandle } from "../../provider-cUByhzgv.mjs";
1
+ import { n as OtelProviderInput, r as buildOtelProvider, t as OtelProviderHandle } from "../../provider-Dy0mVCx5.mjs";
2
2
  export { OtelProviderHandle, OtelProviderInput, buildOtelProvider };
@@ -1 +1 @@
1
- import{t as buildOtelProvider}from"../../provider-CElaujE6.mjs";export{buildOtelProvider};
1
+ import{t as buildOtelProvider}from"../../provider-B8YtuhDX.mjs";export{buildOtelProvider};
@@ -1,6 +1,6 @@
1
1
  //#region src/internal/page-lifecycle/keepalive-budget.d.ts
2
2
  /**
3
- * Reserves keepalive budget for one request body. Returns the release callback when the body fits, or null when the request must go out without keepalive.
3
+ * Reserves keepalive budget for one request body. Returns the release callback when the page's in-flight keepalive bodies stay within `limit` (the shared budget by default), or null when the request must go out without keepalive.
4
4
  */
5
- export declare function reserveKeepaliveBody(bytes: number): (() => void) | null;
5
+ export declare function reserveKeepaliveBody(bytes: number, limit?: number): (() => void) | null;
6
6
  //#endregion
@@ -1 +1 @@
1
- import{t as reserveKeepaliveBody}from"../../keepalive-budget-DeafGnVZ.mjs";export{reserveKeepaliveBody};
1
+ import{t as reserveKeepaliveBody}from"../../keepalive-budget-BfoHXD04.mjs";export{reserveKeepaliveBody};
@@ -1,2 +1,2 @@
1
- import { v as PluginRuntime } from "../../provider-D4QjZp3L.mjs";
1
+ import { v as PluginRuntime } from "../../provider-vp8Aao8Q.mjs";
2
2
  export { PluginRuntime };
@@ -1 +1 @@
1
- import{t as PluginRuntime}from"../../plugin-runtime-DSj0FM1Q.mjs";export{PluginRuntime};
1
+ import{t as PluginRuntime}from"../../plugin-runtime-DgB1_Xc5.mjs";export{PluginRuntime};
@@ -1,2 +1,2 @@
1
- import { a as InterfereContextValue, i as InterfereContext, o as NULL_CONTEXT_VALUE } from "../provider-D4QjZp3L.mjs";
1
+ import { a as InterfereContextValue, i as InterfereContext, o as NULL_CONTEXT_VALUE } from "../provider-vp8Aao8Q.mjs";
2
2
  export { InterfereContext, InterfereContextValue, NULL_CONTEXT_VALUE };
@@ -0,0 +1,3 @@
1
+ //#region src/internal/react-dom-keys.d.ts
2
+ export declare function primeReactDomKeys(): void;
3
+ //#endregion
@@ -0,0 +1 @@
1
+ import{t as primeReactDomKeys}from"../react-dom-keys-BIJuLkQR.mjs";export{primeReactDomKeys};
@@ -0,0 +1,2 @@
1
+ import { a as ingestQueueAnswerSchema, i as answerIngestQueueQuery, n as IngestQueueController, o as ingestQueueQuerySchema, r as IngestQueueQuery, t as INGEST_QUEUE_QUERY } from "../sw-queue-protocol-DqP1EQtQ.mjs";
2
+ export { INGEST_QUEUE_QUERY, IngestQueueController, IngestQueueQuery, answerIngestQueueQuery, ingestQueueAnswerSchema, ingestQueueQuerySchema };
@@ -0,0 +1 @@
1
+ import{i as ingestQueueQuerySchema,n as answerIngestQueueQuery,r as ingestQueueAnswerSchema,t as INGEST_QUEUE_QUERY}from"../sw-queue-protocol-DnTSOWxy.mjs";export{INGEST_QUEUE_QUERY,answerIngestQueueQuery,ingestQueueAnswerSchema,ingestQueueQuerySchema};
@@ -1 +1 @@
1
- import{isRetryableStatus}from"@interfere/helpers/retry-request";import{Queue}from"workbox-background-sync";const SYNTHETIC_QUEUED_RESPONSE={status:202,statusText:`Queued`};async function postToClients(message){let clients=await self.clients.matchAll({includeUncontrolled:!1});for(let client of clients)client.postMessage(message)}async function totalQueueBytes(queue){let entries=await queue.getAll(),total=0;for(let entry of entries){let meta=entry.metadata;meta&&`bytes`in meta&&typeof meta.bytes==`number`&&(total+=meta.bytes)}return total}async function pruneOldest(queue,neededBytes){let total=await totalQueueBytes(queue);for(;total+neededBytes>10485760;){let dropped=await queue.shiftRequest();if(!dropped)break;let meta=dropped.metadata;meta&&`bytes`in meta&&typeof meta.bytes==`number`&&(total-=meta.bytes),await postToClients({reason:`queue_size_cap`,type:`interfere.sw.dropped`,url:dropped.request.url})}}async function enqueue(queue,request){let cloned=request.clone(),bytes=(await cloned.clone().arrayBuffer()).byteLength;await pruneOldest(queue,bytes),await queue.pushRequest({metadata:{bytes},request:cloned}),await postToClients({type:`interfere.sw.queued`,url:request.url})}function installIngestQueue(options={}){let matches=options.match??(url=>url.pathname.startsWith(`/api/interfere/`)),replayInFlight,replay=async q=>{replayInFlight??=(async()=>{try{let entry=await q.shiftRequest();for(;entry;){try{let res=await self.fetch(entry.request.clone());if(!res.ok&&isRetryableStatus(res.status))throw Error(`retry status ${res.status}`);await postToClients({type:`interfere.sw.replayed`,url:entry.request.url})}catch(error){throw await q.unshiftRequest(entry),error}entry=await q.shiftRequest()}}finally{replayInFlight=void 0}})(),await replayInFlight},queue=new Queue(options.queueName??`interfere-ingest`,{maxRetentionTime:1440,onSync:async({queue:q})=>{await replay(q)}});self.addEventListener(`activate`,event=>{event.waitUntil(replay(queue).catch(()=>{}))}),self.addEventListener(`fetch`,event=>{let{request}=event;if(request.method!==`POST`)return;let url;try{url=new URL(request.url)}catch{return}matches(url,request)&&event.respondWith((async()=>{try{let res=await self.fetch(request.clone());return res.ok?res:isRetryableStatus(res.status)?(await enqueue(queue,request),new Response(null,SYNTHETIC_QUEUED_RESPONSE)):res}catch{return await enqueue(queue,request),new Response(null,SYNTHETIC_QUEUED_RESPONSE)}})())})}export{installIngestQueue};
1
+ import{i as ingestQueueQuerySchema,n as answerIngestQueueQuery}from"../sw-queue-protocol-DnTSOWxy.mjs";import{isRetryableStatus}from"@interfere/helpers/retry-request";import{Queue}from"workbox-background-sync";const SYNTHETIC_QUEUED_RESPONSE={status:202,statusText:`Queued`};async function postToClients(message){let clients=await self.clients.matchAll({includeUncontrolled:!1});for(let client of clients)client.postMessage(message)}async function totalQueueBytes(queue){let entries=await queue.getAll(),total=0;for(let entry of entries){let meta=entry.metadata;meta&&`bytes`in meta&&typeof meta.bytes==`number`&&(total+=meta.bytes)}return total}async function pruneOldest(queue,neededBytes){let total=await totalQueueBytes(queue);for(;total+neededBytes>10485760;){let dropped=await queue.shiftRequest();if(!dropped)break;let meta=dropped.metadata;meta&&`bytes`in meta&&typeof meta.bytes==`number`&&(total-=meta.bytes),await postToClients({reason:`queue_size_cap`,type:`interfere.sw.dropped`,url:dropped.request.url})}}async function enqueue(queue,request){let cloned=request.clone(),bytes=(await cloned.clone().arrayBuffer()).byteLength;await pruneOldest(queue,bytes),await queue.pushRequest({metadata:{bytes},request:cloned}),await postToClients({type:`interfere.sw.queued`,url:request.url})}function installIngestQueue(options={}){let matches=options.match??(url=>url.pathname.startsWith(`/api/interfere/`)),replayInFlight,replay=async q=>{replayInFlight??=(async()=>{try{let entry=await q.shiftRequest();for(;entry;){try{let res=await self.fetch(entry.request.clone());if(!res.ok&&isRetryableStatus(res.status))throw Error(`retry status ${res.status}`);await postToClients({type:`interfere.sw.replayed`,url:entry.request.url})}catch(error){throw await q.unshiftRequest(entry),error}entry=await q.shiftRequest()}}finally{replayInFlight=void 0}})(),await replayInFlight},queue=new Queue(options.queueName??`interfere-ingest`,{maxRetentionTime:1440,onSync:async({queue:q})=>{await replay(q)}});self.addEventListener(`activate`,event=>{event.waitUntil(replay(queue).catch(()=>{}))}),self.addEventListener(`message`,event=>{let[port]=event.ports,query=ingestQueueQuerySchema.safeParse(event.data);port&&query.success&&answerIngestQueueQuery(query.data,port,matches)}),self.addEventListener(`fetch`,event=>{let{request}=event;if(request.method!==`POST`)return;let url;try{url=new URL(request.url)}catch{return}matches(url,request)&&event.respondWith((async()=>{try{let res=await self.fetch(request.clone());return res.ok?res:isRetryableStatus(res.status)?(await enqueue(queue,request),new Response(null,SYNTHETIC_QUEUED_RESPONSE)):res}catch{return await enqueue(queue,request),new Response(null,SYNTHETIC_QUEUED_RESPONSE)}})())})}export{installIngestQueue};
@@ -1 +1 @@
1
- import{n as SDK_NAME,r as SDK_VERSION,t as PRODUCER_VERSION}from"../version-DusHm2Q4.mjs";export{PRODUCER_VERSION,SDK_NAME,SDK_VERSION};
1
+ import{n as SDK_NAME,r as SDK_VERSION,t as PRODUCER_VERSION}from"../version-CPcWUmrA.mjs";export{PRODUCER_VERSION,SDK_NAME,SDK_VERSION};
@@ -1,4 +1,4 @@
1
- import { f as KernelOptions, s as Kernel } from "../provider-D4QjZp3L.mjs";
1
+ import { f as KernelOptions, s as Kernel } from "../provider-vp8Aao8Q.mjs";
2
2
  import { ConsentInput, ConsentState } from "@interfere/types/sdk/plugins/manifest";
3
3
  import { IdentifyParams } from "@interfere/types/sdk/identify";
4
4
  //#region src/internal/wrapper-singleton.d.ts
@@ -1 +1 @@
1
- import{t as createLogger}from"../log-D6Ht--tv.mjs";import{n as registerKernel,r as unregisterKernel}from"../kernel-registry-6f-3VCIy.mjs";import{n as isForceEnableActive,t as hasPublicKey}from"../config-VOyDjqS7.mjs";import{t as isEnabledByEnvironment}from"../environment-CoEXhF1a.mjs";import{r as createKernel}from"../kernel-BVG-7Zau.mjs";import{n as isBotUserAgent}from"../bot-YLSbnCeg.mjs";const log=createLogger(`init`);function createWrapperSingleton(input){let kernel=null,pending=null,listeners=new Set;function emit(){for(let listener of listeners)listener()}async function initKernel(internalOpts){try{let k=await createKernel({opts:internalOpts});return kernel=k,registerKernel(k),emit(),k}finally{pending=null}}return{async close(){if(!kernel)return;let previous=kernel;await previous.dispose(),kernel=null,unregisterKernel(previous),emit()},consent:{get:()=>kernel?.consent.get()??null,set:value=>kernel?.consent.set(value)},getKernel(){if(!kernel)throw Error(`Interfere SDK not initialized. Call init() from your ${input.initEntryName} entrypoint.`);return kernel},getKernelOrNull(){return kernel},identity:{clear:()=>kernel?.identity.clear(),get:()=>kernel?.identity.get()??null,set:async params=>kernel?.identity.set(params)??Promise.resolve()},async init(opts={}){return kernel||pending||(!(opts.enabled??isEnabledByEnvironment())||!isForceEnableActive()&&isBotUserAgent()?null:hasPublicKey()?(pending=initKernel({...opts,_wrapperVersions:[input.producerVersion]}),pending):(log.warn(`No public key is configured, so the SDK is disabled. Set INTERFERE_PUBLIC_KEY (VITE_INTERFERE_PUBLIC_KEY for Vite) on builds that should send telemetry.`),null))},subscribeToKernel(listener){return listeners.add(listener),(()=>{listeners.delete(listener)})}}}export{createWrapperSingleton};
1
+ import{t as createLogger}from"../log-D6Ht--tv.mjs";import{n as registerKernel,r as unregisterKernel}from"../kernel-registry-6f-3VCIy.mjs";import{n as isForceEnableActive,t as hasPublicKey}from"../config-VOyDjqS7.mjs";import{t as isEnabledByEnvironment}from"../environment-CoEXhF1a.mjs";import{r as createKernel}from"../kernel-BZI0jyJI.mjs";import{t as primeReactDomKeys}from"../react-dom-keys-BIJuLkQR.mjs";import{n as isBotUserAgent}from"../bot-YLSbnCeg.mjs";const log=createLogger(`init`);function createWrapperSingleton(input){let kernel=null,pending=null,queuedConsent=null,queuedIdentity=null,listeners=new Set;function emit(){for(let listener of listeners)listener()}async function initKernel(internalOpts){try{let k=await createKernel({opts:internalOpts});return kernel=k,registerKernel(k),queuedConsent&&=(k.consent.set(queuedConsent.value),null),queuedIdentity&&=(k.identity.set(queuedIdentity),null),emit(),k}finally{pending=null}}return{async close(){if(!kernel)return;let previous=kernel;await previous.dispose(),kernel=null,unregisterKernel(previous),emit()},consent:{get:()=>kernel?.consent.get()??null,set:value=>{kernel?kernel.consent.set(value):queuedConsent={value}}},getKernel(){if(!kernel)throw Error(`Interfere SDK not initialized. Call init() from your ${input.initEntryName} entrypoint.`);return kernel},getKernelOrNull(){return kernel},identity:{clear:()=>{queuedIdentity=null,kernel?.identity.clear()},get:()=>kernel?.identity.get()??queuedIdentity,set:async params=>{if(kernel)return kernel.identity.set(params);queuedIdentity=params}},async init(opts={}){if(kernel)return kernel;if(pending)return pending;if(!(opts.enabled??isEnabledByEnvironment())||!isForceEnableActive()&&isBotUserAgent())return null;if(!hasPublicKey())return log.warn(`No public key is configured, so the SDK is disabled. Set INTERFERE_PUBLIC_KEY (VITE_INTERFERE_PUBLIC_KEY for Vite) on builds that should send telemetry.`),null;let internalOpts={...opts,_wrapperVersions:[input.producerVersion]};return primeReactDomKeys(),pending=initKernel(internalOpts),pending},subscribeToKernel(listener){return listeners.add(listener),(()=>{listeners.delete(listener)})}}}export{createWrapperSingleton};
@@ -0,0 +1 @@
1
+ const KEEPALIVE_BODY_BUDGET_BYTES=6e4;let keepaliveBodyBytes=0;function reserveKeepaliveBody(bytes,limit=KEEPALIVE_BODY_BUDGET_BYTES){if(keepaliveBodyBytes+bytes>Math.min(limit,KEEPALIVE_BODY_BUDGET_BYTES))return null;keepaliveBodyBytes+=bytes;let released=!1;return(()=>{released||(released=!0,keepaliveBodyBytes-=bytes)})}export{reserveKeepaliveBody as t};
@@ -0,0 +1 @@
1
+ import{t as isPageHidden}from"./page-lifecycle-rJEJNdKj.mjs";import{ExportResultCode}from"@opentelemetry/core";function splitForKeepalive(items,serialize){let chunks=[],pending=[items];for(let next=pending.pop();next;next=pending.pop()){if(next.length<=1||(serialize(next)?.byteLength??0)<=16e3){chunks.push(next);continue}let middle=Math.ceil(next.length/2);pending.push(next.slice(middle),next.slice(0,middle))}return chunks}function sendInKeepaliveChunks(items,serialize,send,resultCallback){let chunks=isPageHidden()?splitForKeepalive(items,serialize):[items];if(chunks.length===1){send(serialize(items),resultCallback);return}let pending=chunks.length,failure,settle=result=>{result.code!==ExportResultCode.SUCCESS&&(failure??=result),--pending,pending===0&&resultCallback(failure??{code:ExportResultCode.SUCCESS})};for(let chunk of chunks)send(serialize(chunk),settle)}export{sendInKeepaliveChunks as t};
@@ -0,0 +1 @@
1
+ import{t as createLogger}from"./log-D6Ht--tv.mjs";import{i as onPageUnloading,n as onPageHidden}from"./page-lifecycle-rJEJNdKj.mjs";import{t as SessionTracker}from"./api-C8aG7li1.mjs";import{n as getStringGlobal,t as getGlobal}from"./global-DYq1Z4_H.mjs";import{i as setIngestHost,r as resolveTargets}from"./config-VOyDjqS7.mjs";import{a as resolvePrivacyPolicy}from"./privacy-CRuL0X8r.mjs";import{t as PRODUCER_VERSION}from"./version-CPcWUmrA.mjs";import{t as INGEST_IGNORE_RE}from"./exporter-BtHqkV3R.mjs";import{t as recordInitialNavigation}from"./initial-navigation-YeK6UUHX.mjs";import{n as recordExceptionOnSpan,r as startExceptionSpan,t as buildExceptionEventAttrs}from"./exception-span-B74fhBQb.mjs";import{t as PluginRuntime}from"./plugin-runtime-DgB1_Xc5.mjs";import{isNonErrorException,shouldDropBrowserExtensionNoise,shouldDropUnresolvableStack}from"@interfere/types/sdk/errors";import{trace}from"@opentelemetry/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{InterfereClient}from"@interfere/javascript";import{releaseSlugSchema}from"@interfere/types/releases/slug";import{FORCE_ENABLE_GLOBAL,RELEASE_SLUG_GLOBAL,SDK_STACK_GLOBAL}from"@interfere/types/sdk/injected-globals";import{readBakedPlugins,remoteConfigInputSchema}from"@interfere/types/sdk/remote-config";import{SERVICE_NAME_GLOBAL}from"@interfere/types/sdk/service-name";import{redactUrl,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";const log=createLogger(`kernel`),REPLAY_UPLOAD_RE=/\/v3\/replay\/upload\//u;function buildSdkStack(wrapperVersions){return[...wrapperVersions??[],PRODUCER_VERSION]}var Kernel=class{consent;identity;device;session;privacyPolicy;urlRedaction;redactUrl=url=>redactUrl(url,this.urlRedaction);seen=new WeakSet;initialNavigationSeen=new Set;runtime=null;otel=null;otelDispose=null;otelControls=null;deviceInfoCaptureEnabled=!1;unsubscribePageHidden=null;unsubscribePageUnloading=null;tracker;constructor(tracker,privacy={}){this.tracker=tracker,this.privacyPolicy=resolvePrivacyPolicy(privacy),this.urlRedaction=resolveUrlRedaction(privacy.urls),this.consent={get:()=>this.requireRuntime().getConsent(),set:value=>{let runtime=this.requireRuntime();value===void 0?runtime.resetConsent():runtime.setConsent(value)}},this.identity={clear:()=>{this.tracker.reset()},get:()=>this.tracker.getIdentity(),set:async params=>this.tracker.identify(params)},this.device={getDeviceId:()=>this.tracker.getDeviceId(),getFpHash:()=>this.tracker.getFpHash()},this.session={getId:()=>this.tracker.sessionId(),getWindowId:()=>this.tracker.windowId()},this.unsubscribePageHidden=onPageHidden(()=>{this.flush().catch(()=>{})}),this.unsubscribePageUnloading=onPageUnloading(()=>{this.flush().catch(()=>{})})}attachRuntime(runtime){this.runtime=runtime}requireRuntime(){if(!this.runtime)throw Error(`Kernel runtime not attached. createKernel must call attachRuntime before any consent/dispose path runs.`);return this.runtime}getSessionId(){return this.tracker.sessionId()??``}getWindowId(){return this.tracker.windowId()??``}onSessionPause(handler){return this.tracker.onSessionPause(handler)}onSessionExceptionWhilePaused(handler){return this.tracker.onSessionExceptionWhilePaused(handler)}noteException(){this.tracker.noteException()}onSessionResume(handler){return this.tracker.onSessionResume(handler)}getPluginConfigState(key){return this.requireRuntime().getPluginConfigState(key)}getReplayConfig(){return this.requireRuntime().getReplayConfig()}isInteractionCaptureEnabled(){return this.requireRuntime().isInteractionCaptureEnabled()}subscribePluginConfigState(key,listener){return this.requireRuntime().subscribePluginConfigState(key,listener)}getTracer(name){return this.otel?.tracerProvider.getTracer(name)??trace.getTracer(name)}startPageEventsCapture(){let{otelControls:controls,otel}=this;return!controls||!otel?null:(controls.setPageEventsEnabled(!0),this.recordInitialNavigation(otel.loggerProvider),(()=>{controls.setPageEventsEnabled(!1)}))}startDeviceInfoCapture(){return this.tracker.startDeviceIdentity(),this.deviceInfoCaptureEnabled=!0,(reason=>{this.deviceInfoCaptureEnabled=!1,reason===`consent-revoked`&&this.tracker.discardDeviceIdentity()})}isDeviceInfoCaptureEnabled(){return this.deviceInfoCaptureEnabled}recordException(value,opts){if(!isNonErrorException(value)){if(this.seen.has(value))return;this.seen.add(value)}if(!isNonErrorException(value)){let stacks=[],current=value;for(let depth=0;current&&depth<5;depth+=1)current.stack&&stacks.push(current.stack),current=current.cause instanceof Error?current.cause:void 0;if(shouldDropBrowserExtensionNoise(stacks)||shouldDropUnresolvableStack(stacks))return}this.tracker.noteException();let attrs=buildExceptionEventAttrs(value,opts),active=trace.getActiveSpan();if(active?.isRecording()){recordExceptionOnSpan(active,value,attrs,opts.mechanism.handled);return}let tracer=this.otel?.tracerProvider.getTracer(`@interfere/react/exception`);if(!tracer)return;let span=startExceptionSpan(tracer,value);recordExceptionOnSpan(span,value,attrs,opts.mechanism.handled),span.end()}recordLog(input){this.otel&&this.otel.loggerProvider.getLogger(`@interfere/react`).emit(omitUndefined({body:input.body,severityNumber:input.severityNumber,severityText:input.severityText,attributes:input.attributes}))}recordInitialNavigation(loggerProvider){recordInitialNavigation({getSessionId:()=>this.session.getId(),getWindowId:()=>this.session.getWindowId(),loggerProvider,redactUrl:this.redactUrl,seen:this.initialNavigationSeen})}async flush(){this.otel&&await this.otel.flush()}attachOtel(handle,dispose,controls){this.otel=handle,this.otelDispose=dispose,this.otelControls=controls??null}syncProviderConfig(config){this.requireRuntime().applyProviderConfig(config.plugins,config.consent)}async dispose(){this.unsubscribePageHidden?.(),this.unsubscribePageHidden=null,this.unsubscribePageUnloading?.(),this.unsubscribePageUnloading=null,this.runtime&&await this.runtime.dispose(),this.tracker.dispose(),this.otelDispose?.(),this.otelDispose=null,this.otel&&=(await this.otel.shutdown(),null)}};async function createKernel(input={}){let{opts={}}=input,fetcher=opts.fetch??globalThis.fetch.bind(globalThis),{plugins:remotePlugins,backendHosts}=await resolveRemoteConfig(opts,fetcher),targets=resolveTargets(opts.apiHost);log.info(`ingest: %s`,targets.ingest.baseUrl),getGlobal(FORCE_ENABLE_GLOBAL)&&log.warn(`FORCE_ENABLE is active. Events will be dropped by production ingest. This should only be set during local development.`);let tracker=new SessionTracker({fetcher,target:targets.ingest});opts._wrapperVersions?.length&&Object.assign(globalThis,{[SDK_STACK_GLOBAL]:opts._wrapperVersions});let kernel=new Kernel(tracker,opts.privacy),runtime=new PluginRuntime(kernel,opts.consent,remotePlugins??{});if(kernel.attachRuntime(runtime),tracker.start(),runtime.start(),opts.tracing!==!1){let resolvedTracing={...typeof opts.tracing==`object`?opts.tracing:void 0},serviceName=opts.serviceName||getStringGlobal(SERVICE_NAME_GLOBAL);serviceName&&(resolvedTracing.serviceName=serviceName),opts.serviceNamespace!==void 0&&(resolvedTracing.serviceNamespace=opts.serviceNamespace),opts._internalAdditionalSpanProcessors&&(resolvedTracing.additionalSpanProcessors=opts._internalAdditionalSpanProcessors),opts._internalAdditionalLogRecordProcessors&&(resolvedTracing.additionalLogRecordProcessors=opts._internalAdditionalLogRecordProcessors),opts._internalAdditionalMetricReaders&&(resolvedTracing.additionalMetricReaders=opts._internalAdditionalMetricReaders),backendHosts&&(resolvedTracing.backendHosts=backendHosts),await wireOtel(kernel,targets,opts._wrapperVersions,resolvedTracing)}return remotePlugins?runtime.applyRemoteConfig(remotePlugins):runtime.applyRemoteConfigDefaults(),kernel}async function resolveRemoteConfig(opts,fetcher){let baked=readBakedPlugins();if(baked)return{plugins:baked,backendHosts:void 0};let remoteConfig=await fetchRemoteConfig(resolveTargets(opts.apiHost).config,fetcher);return remoteConfig?.ingestUrl&&setIngestHost(remoteConfig.ingestUrl),{plugins:remoteConfig?.plugins??null,backendHosts:remoteConfig?.backendHosts}}async function wireOtel(kernel,targets,wrapperVersions,tracing){let{buildOtelProvider,captureWebVitals,createPageScopeRotator,installNavigationScope,PAGE_SCOPE_MAX_AGE_MS,readPropagationFromDocument,registerBundledInstrumentations,seedPageScope}=await import(`./internal/otel/index.mjs`),releaseSlug=readReleaseSlugFromGlobals(),handle=buildOtelProvider(omitUndefined({clientOptions:targets.ingest,getDeviceId:()=>kernel.device.getDeviceId(),getSessionId:()=>kernel.session.getId(),getPropagationSessionId:()=>kernel.consent.get()?.analytics===!1?null:kernel.session.getId(),isDeviceInfoEnabled:()=>kernel.isDeviceInfoCaptureEnabled(),onExceptionSpan:()=>{kernel.noteException()},releaseSlug,sdkStack:buildSdkStack(wrapperVersions),serviceName:tracing.serviceName||void 0,serviceNamespace:tracing.serviceNamespace,additionalSpanProcessors:[...tracing.spanProcessors??[],...tracing.additionalSpanProcessors??[]],additionalLogRecordProcessors:tracing.additionalLogRecordProcessors,additionalMetricReaders:tracing.additionalMetricReaders,urlRedaction:kernel.urlRedaction})),scopeSpanInput=omitUndefined({tracer:handle.tracerProvider.getTracer(`@interfere/react/navigation`),resolveRoute:tracing.resolveRoute}),extracted=readPropagationFromDocument();handle.contextManager.setPageScope(extracted??seedPageScope(scopeSpanInput)),handle.contextManager.setRotation(createPageScopeRotator(scopeSpanInput),PAGE_SCOPE_MAX_AGE_MS);let disposeNavigationScope=installNavigationScope({...scopeSpanInput,setPageScope:ctx=>{handle.contextManager.setPageScope(ctx)}}),instrumentations=registerBundledInstrumentations(omitUndefined({tracerProvider:handle.tracerProvider,loggerProvider:handle.loggerProvider,ignoreUrls:[INGEST_IGNORE_RE,`${targets.config.baseUrl}/v3/config`,`${targets.ingest.baseUrl}/v3/session`,REPLAY_UPLOAD_RE,...tracing.ignoreUrls??[]],apiHosts:tracing.apiHosts,backendHosts:tracing.backendHosts,propagateContextUrls:tracing.propagateContextUrls,resolveRoute:tracing.resolveRoute,captureFailedRequests:tracing.captureFailedRequests,redactUrl:kernel.redactUrl,privacyPolicy:kernel.privacyPolicy,isInteractionCaptureEnabled:()=>kernel.isInteractionCaptureEnabled()}));tracing.webVitals!==!1&&captureWebVitals(omitUndefined({flush:async()=>handle.flush(),meter:handle.meterProvider.getMeter(`@interfere/react/web-vitals`),resolveRoute:tracing.resolveRoute})),kernel.attachOtel(handle,()=>{disposeNavigationScope(),instrumentations.dispose()},{setPageEventsEnabled:instrumentations.setPageEventsEnabled})}async function fetchRemoteConfig(configTarget,fetcher){try{let client=new InterfereClient({...configTarget,fetch:Object.assign(async(url,init)=>fetcher(url,{...init,credentials:`omit`}),fetcher)});return remoteConfigInputSchema.parse(await client.config.getSdkConfig())}catch{return log.warn(`remote config fetch failed, using local defaults`),null}}function readReleaseSlugFromGlobals(){let value=getGlobal(RELEASE_SLUG_GLOBAL);return typeof value==`string`?releaseSlugSchema.parse(value):null}export{readReleaseSlugFromGlobals as i,buildSdkStack as n,createKernel as r,Kernel as t};