@interfere/react 11.0.1 → 11.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.mts +0 -1
- package/dist/error-boundary.d.mts +1 -1
- package/dist/internal/browser-context.d.mts +0 -1
- package/dist/internal/capture-boundary.d.mts +0 -1
- package/dist/internal/capture.d.mts +0 -1
- package/dist/internal/config.mjs +1 -1
- package/dist/internal/consent.d.mts +0 -1
- package/dist/internal/kernel-registry.d.mts +0 -1
- package/dist/internal/kernel.d.mts +5 -19
- package/dist/internal/kernel.mjs +1 -1
- package/dist/internal/otel/exporter.d.mts +0 -1
- package/dist/internal/otel/initial-navigation.d.mts +0 -1
- package/dist/internal/otel/instrumentations.d.mts +0 -1
- package/dist/internal/otel/page-scope-context-manager.d.mts +0 -1
- package/dist/internal/otel/propagation.d.mts +0 -1
- package/dist/internal/otel/provider.d.mts +3 -27
- package/dist/internal/otel/provider.mjs +1 -1
- package/dist/internal/otel/web-vitals.d.mts +0 -1
- package/dist/internal/plugin-runtime.d.mts +0 -1
- package/dist/internal/react-context.d.mts +0 -1
- package/dist/internal/wrapper-singleton.d.mts +0 -1
- package/dist/package.mjs +1 -1
- package/dist/plugins/errors.d.mts +0 -1
- package/dist/plugins/errors.mjs +1 -1
- package/dist/plugins/lib/loader.d.mts +0 -1
- package/dist/plugins/lib/types.d.mts +1 -1
- package/dist/plugins/logs.d.mts +0 -1
- package/dist/plugins/rage-clicks.d.mts +0 -1
- package/dist/plugins/replay/buffer.d.mts +0 -1
- package/dist/plugins/replay/buffer.mjs +1 -1
- package/dist/plugins/replay/chunking.d.mts +9 -1
- package/dist/plugins/replay/chunking.mjs +2 -1
- package/dist/plugins/replay/config.d.mts +0 -1
- package/dist/plugins/replay/delivery.d.mts +8 -10
- package/dist/plugins/replay/delivery.mjs +1 -1
- package/dist/plugins/replay/index.d.mts +0 -1
- package/dist/plugins/replay/index.mjs +1 -1
- package/dist/plugins/replay/recorder.d.mts +0 -1
- package/dist/plugins/replay/recorder.mjs +1 -1
- package/dist/plugins/replay/sequence.d.mts +7 -0
- package/dist/plugins/replay/sequence.mjs +1 -0
- package/dist/provider.d.mts +1 -8
- package/dist/react-error-handler.d.mts +0 -1
- package/dist/tracking/api.d.mts +0 -1
- package/dist/tracking/session.d.mts +0 -1
- package/dist/tracking/session.mjs +1 -1
- package/package.json +6 -5
package/dist/api.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { InterfereContext, InterfereContextValue } from "./internal/react-context.mjs";
|
|
2
|
+
import "./provider.mjs";
|
|
2
3
|
import { Component, ContextType, ErrorInfo, ReactNode } from "react";
|
|
3
|
-
|
|
4
4
|
//#region src/error-boundary.d.ts
|
|
5
5
|
interface ErrorBoundaryProps {
|
|
6
6
|
children: ReactNode;
|
package/dist/internal/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getGlobal,setGlobal}from"../util/global.mjs";import{API_PATHS,API_URL}from"@interfere/constants/api";const
|
|
1
|
+
import{getGlobal,setGlobal}from"../util/global.mjs";import{API_PATHS,API_URL}from"@interfere/constants/api";import{API_URL_GLOBAL,FORCE_ENABLE_GLOBAL,INGEST_URL_GLOBAL,PUBLIC_KEY_GLOBAL}from"@interfere/types/sdk/injected-globals";const TRAILING_SLASH_RE=/\/$/,RELATIVE_URL_BASE=`https://interfere.local`;function resolvePublicKey(){let injected=getGlobal(PUBLIC_KEY_GLOBAL);if(injected)return injected;if(typeof process<`u`)return process.env.INTERFERE_PUBLIC_KEY??void 0}function isForceEnableActive(){return!!getGlobal(FORCE_ENABLE_GLOBAL)}function resolveApiHost(explicit){return explicit??getGlobal(API_URL_GLOBAL)}function resolveIngestHost(explicit){return explicit??getGlobal(INGEST_URL_GLOBAL)}function setIngestHost(host){setGlobal(INGEST_URL_GLOBAL,host)}function normalizeOrigin(host){try{return new URL(host).origin}catch{return API_URL}}function serializeUrl(input,url){return input.startsWith(`/`)?`${url.pathname}${url.search}`:url.toString()}function withQueryParam(url,key,value){let next=new URL(url,RELATIVE_URL_BASE);return next.searchParams.set(key,value),serializeUrl(url,next)}function appendPublicKey(url,publicKey){return publicKey?withQueryParam(url,`pk`,publicKey):url}function appendPathBeforeQuery(url,path){let next=new URL(url,RELATIVE_URL_BASE),suffix=path.startsWith(`/`)?path:`/${path}`;return next.pathname=`${next.pathname.replace(TRAILING_SLASH_RE,``)}${suffix}`,serializeUrl(url,next)}function resolveTargets(apiHost,ingestHost){let publicKey=resolvePublicKey(),headers=new Headers({"content-type":`application/json`});isForceEnableActive()&&headers.set(`x-interfere-force-enable`,`1`);let configHost=resolveApiHost(apiHost),configBaseUrl=configHost?normalizeOrigin(configHost):API_URL,resolvedIngestHost=resolveIngestHost(ingestHost),ingestBaseUrl=resolvedIngestHost?normalizeOrigin(resolvedIngestHost):configBaseUrl;return{collectorBaseUrl:appendPublicKey(ingestBaseUrl,publicKey),config:{url:appendPublicKey(`${configBaseUrl}${API_PATHS.CONFIG}`,publicKey),headers},ingest:{headers},session:{url:appendPublicKey(`${ingestBaseUrl}${API_PATHS.SESSION}`,publicKey),headers}}}export{appendPathBeforeQuery,resolveTargets,setIngestHost,withQueryParam};
|
|
@@ -5,6 +5,7 @@ import { PluginOverrides } from "../plugins/lib/loader.mjs";
|
|
|
5
5
|
import { SessionTracker } from "../tracking/api.mjs";
|
|
6
6
|
import { CaptureFailedRequestsOption, CaptureFailedRequestsOptions, HttpStatusCodeRange } from "./otel/instrumentations.mjs";
|
|
7
7
|
import { OtelProviderHandle } from "./otel/provider.mjs";
|
|
8
|
+
import "./otel/index.mjs";
|
|
8
9
|
import { PluginRuntime } from "./plugin-runtime.mjs";
|
|
9
10
|
import { NonErrorException } from "@interfere/types/sdk/errors";
|
|
10
11
|
import { ConsentState, PluginKey } from "@interfere/types/sdk/plugins/manifest";
|
|
@@ -16,7 +17,6 @@ import { IngestedFrame } from "@interfere/types/data/frame";
|
|
|
16
17
|
import { SessionId } from "@interfere/types/data/session";
|
|
17
18
|
import { IdentifyParams } from "@interfere/types/sdk/identify";
|
|
18
19
|
import { ErrorMechanism } from "@interfere/types/sdk/plugins/payload/errors";
|
|
19
|
-
|
|
20
20
|
//#region src/internal/kernel.d.ts
|
|
21
21
|
declare function buildSdkStack(wrapperVersions?: string[]): string[];
|
|
22
22
|
interface KernelOptions {
|
|
@@ -116,26 +116,11 @@ interface TracingOptions {
|
|
|
116
116
|
* clean.
|
|
117
117
|
*/
|
|
118
118
|
interface KernelInternalOptions extends KernelOptions {
|
|
119
|
-
/**
|
|
120
|
-
* Extra log-record processors fanned into the LoggerProvider's
|
|
121
|
-
* processor list. Used by `@interfere/observability` for internal-only
|
|
122
|
-
* dual-write to BetterStack from `interfere/homepage` +
|
|
123
|
-
* `interfere/dashboard`. **Not part of the customer surface** — the
|
|
124
|
-
* SDK doesn't expose a way to fan-out to other observability vendors.
|
|
125
|
-
*/
|
|
119
|
+
/** @internal */
|
|
126
120
|
_internalAdditionalLogRecordProcessors?: LogRecordProcessor[];
|
|
127
|
-
/**
|
|
128
|
-
* Extra metric readers fanned into the MeterProvider's reader list.
|
|
129
|
-
* See `_internalAdditionalLogRecordProcessors`. Used to keep web
|
|
130
|
-
* vitals histograms landing on the BetterStack-fronting OTel
|
|
131
|
-
* collector after the rum.ts → SDK migration moved the primary path
|
|
132
|
-
* to `/v2/sink` (Tinybird-only).
|
|
133
|
-
*/
|
|
121
|
+
/** @internal */
|
|
134
122
|
_internalAdditionalMetricReaders?: MetricReader[];
|
|
135
|
-
/**
|
|
136
|
-
* Extra span processors fanned into the WebTracerProvider's processor
|
|
137
|
-
* list. See `_internalAdditionalLogRecordProcessors`.
|
|
138
|
-
*/
|
|
123
|
+
/** @internal */
|
|
139
124
|
_internalAdditionalSpanProcessors?: SpanProcessor[];
|
|
140
125
|
/** Wrapper SDK versions (e.g. `@interfere/next@10.0.0`). */
|
|
141
126
|
_wrapperVersions?: string[];
|
|
@@ -217,6 +202,7 @@ declare class Kernel implements PluginContext {
|
|
|
217
202
|
private requireRuntime;
|
|
218
203
|
/** PluginContext shim: plugins expect a non-null string. */
|
|
219
204
|
getSessionId(): string;
|
|
205
|
+
getWindowId(): string;
|
|
220
206
|
onSessionPause(handler: () => void): () => void;
|
|
221
207
|
onSessionResume(handler: (reason: SessionResumeReason) => void): () => void;
|
|
222
208
|
getPluginConfigState(key: PluginKey): PluginConfigState;
|
package/dist/internal/kernel.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"../util/log.mjs";import{onPageHidden}from"./page-lifecycle.mjs";import{getGlobal}from"../util/global.mjs";import{resolveTargets,setIngestHost}from"./config.mjs";import{SessionTracker}from"../tracking/api.mjs";import{safeStringify}from"../util/stringify.mjs";import{recordInitialNavigation}from"./otel/initial-navigation.mjs";import{PluginRuntime}from"./plugin-runtime.mjs";import{PRODUCER_VERSION}from"./version.mjs";import{isNonErrorException,shouldDropBrowserExtensionNoise,shouldDropUnresolvableStack,toExceptions}from"@interfere/types/sdk/errors";import{trace}from"@opentelemetry/api";import{releaseSlugSchema}from"@interfere/types/releases/slug";const log=createLogger(`kernel`),TRAILING_SLASH_RE=/\/$/,REPLAY_UPLOAD_RE=/\/v2\/replay\/upload\//;function buildSdkStack(wrapperVersions){return[...wrapperVersions??[],PRODUCER_VERSION]}function buildExceptionEventAttrs(value,opts){let attrs={"interfere.exception.mechanism":opts.mechanism.type,"interfere.exception.handled":opts.mechanism.handled};if(opts.errorDigest&&(attrs[`interfere.error.digest`]=opts.errorDigest),opts.subtype&&(attrs[`interfere.exception.subtype`]=opts.subtype),isNonErrorException(value))return attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`,attrs[`interfere.exception.serialized`]=safeStringify(value.serialized),attrs;attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack),attrs[`interfere.exception.chain`]=safeStringify(toExceptions(value,opts.mechanism));let debugIds=globalThis._debugIds;return debugIds&&typeof debugIds==`object`&&Object.keys(debugIds).length>0&&(attrs[`interfere.exception.debug_ids`]=safeStringify(debugIds)),opts.appendFrames&&opts.appendFrames.length>0&&(attrs[`interfere.exception.appended_frames`]=safeStringify(opts.appendFrames)),opts.fallbackFrames&&opts.fallbackFrames.length>0&&(attrs[`interfere.exception.fallback_frames`]=safeStringify(opts.fallbackFrames)),attrs}var Kernel=class{consent;identity;device;session;tracker;seen=new WeakSet;initialNavigationSeen=new Set;runtime=null;otel=null;otelDispose=null;unsubscribePageHidden=null;constructor(tracker){this.tracker=tracker,this.consent={get:()=>this.requireRuntime().getConsent(),set:value=>{let runtime=this.requireRuntime();value?runtime.setConsent(value):runtime.resetConsent()}},this.identity={clear:()=>this.tracker.reset(),get:()=>this.tracker.getIdentity(),set: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(()=>void 0)})}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()??``}onSessionPause(handler){return this.tracker.onSessionPause(handler)}onSessionResume(handler){return this.tracker.onSessionResume(handler)}getPluginConfigState(key){return this.requireRuntime().getPluginConfigState(key)}getReplayConfig(){return this.requireRuntime().getReplayConfig()}subscribePluginConfigState(key,listener){return this.requireRuntime().subscribePluginConfigState(key,listener)}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}let attrs=buildExceptionEventAttrs(value,opts),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs);return}let span=this.otel?.tracerProvider.getTracer(`@interfere/react/exception`).startSpan(`interfere.exception.capture`);span&&(span.addEvent(`exception`,attrs),span.end())}recordLog(input){this.otel&&this.otel.loggerProvider.getLogger(`@interfere/react`).emit({severityText:input.severityText,severityNumber:input.severityNumber,body:input.body,...input.attributes?{attributes:input.attributes}:{}})}recordInitialNavigation(loggerProvider){recordInitialNavigation({getSessionId:()=>this.session.getId(),getWindowId:()=>this.session.getWindowId(),loggerProvider,seen:this.initialNavigationSeen})}async flush(){this.otel&&await this.otel.flush()}attachOtel(handle,dispose){this.otel=handle,this.otelDispose=dispose}syncProviderConfig(config){this.requireRuntime().applyProviderConfig(config.plugins,config.consent)}async dispose(){this.unsubscribePageHidden?.(),this.unsubscribePageHidden=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),
|
|
1
|
+
import{createLogger}from"../util/log.mjs";import{onPageHidden}from"./page-lifecycle.mjs";import{getGlobal}from"../util/global.mjs";import{resolveTargets,setIngestHost}from"./config.mjs";import{SessionTracker}from"../tracking/api.mjs";import{safeStringify}from"../util/stringify.mjs";import{recordInitialNavigation}from"./otel/initial-navigation.mjs";import{PluginRuntime}from"./plugin-runtime.mjs";import{PRODUCER_VERSION}from"./version.mjs";import{isNonErrorException,shouldDropBrowserExtensionNoise,shouldDropUnresolvableStack,toExceptions}from"@interfere/types/sdk/errors";import{trace}from"@opentelemetry/api";import{FORCE_ENABLE_GLOBAL,RELEASE_SLUG_GLOBAL,SDK_STACK_GLOBAL}from"@interfere/types/sdk/injected-globals";import{releaseSlugSchema}from"@interfere/types/releases/slug";import{readBakedPlugins}from"@interfere/types/sdk/remote-config";const log=createLogger(`kernel`),TRAILING_SLASH_RE=/\/$/,REPLAY_UPLOAD_RE=/\/v2\/replay\/upload\//;function buildSdkStack(wrapperVersions){return[...wrapperVersions??[],PRODUCER_VERSION]}function buildExceptionEventAttrs(value,opts){let attrs={"interfere.exception.mechanism":opts.mechanism.type,"interfere.exception.handled":opts.mechanism.handled};if(opts.errorDigest&&(attrs[`interfere.error.digest`]=opts.errorDigest),opts.subtype&&(attrs[`interfere.exception.subtype`]=opts.subtype),isNonErrorException(value))return attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`,attrs[`interfere.exception.serialized`]=safeStringify(value.serialized),attrs;attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack),attrs[`interfere.exception.chain`]=safeStringify(toExceptions(value,opts.mechanism));let debugIds=globalThis._debugIds;return debugIds&&typeof debugIds==`object`&&Object.keys(debugIds).length>0&&(attrs[`interfere.exception.debug_ids`]=safeStringify(debugIds)),opts.appendFrames&&opts.appendFrames.length>0&&(attrs[`interfere.exception.appended_frames`]=safeStringify(opts.appendFrames)),opts.fallbackFrames&&opts.fallbackFrames.length>0&&(attrs[`interfere.exception.fallback_frames`]=safeStringify(opts.fallbackFrames)),attrs}var Kernel=class{consent;identity;device;session;tracker;seen=new WeakSet;initialNavigationSeen=new Set;runtime=null;otel=null;otelDispose=null;unsubscribePageHidden=null;constructor(tracker){this.tracker=tracker,this.consent={get:()=>this.requireRuntime().getConsent(),set:value=>{let runtime=this.requireRuntime();value?runtime.setConsent(value):runtime.resetConsent()}},this.identity={clear:()=>this.tracker.reset(),get:()=>this.tracker.getIdentity(),set: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(()=>void 0)})}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)}onSessionResume(handler){return this.tracker.onSessionResume(handler)}getPluginConfigState(key){return this.requireRuntime().getPluginConfigState(key)}getReplayConfig(){return this.requireRuntime().getReplayConfig()}subscribePluginConfigState(key,listener){return this.requireRuntime().subscribePluginConfigState(key,listener)}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}let attrs=buildExceptionEventAttrs(value,opts),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs);return}let span=this.otel?.tracerProvider.getTracer(`@interfere/react/exception`).startSpan(`interfere.exception.capture`);span&&(span.addEvent(`exception`,attrs),span.end())}recordLog(input){this.otel&&this.otel.loggerProvider.getLogger(`@interfere/react`).emit({severityText:input.severityText,severityNumber:input.severityNumber,body:input.body,...input.attributes?{attributes:input.attributes}:{}})}recordInitialNavigation(loggerProvider){recordInitialNavigation({getSessionId:()=>this.session.getId(),getWindowId:()=>this.session.getWindowId(),loggerProvider,seen:this.initialNavigationSeen})}async flush(){this.otel&&await this.otel.flush()}attachOtel(handle,dispose){this.otel=handle,this.otelDispose=dispose}syncProviderConfig(config){this.requireRuntime().applyProviderConfig(config.plugins,config.consent)}async dispose(){this.unsubscribePageHidden?.(),this.unsubscribePageHidden=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),remotePlugins=await resolveRemotePlugins(opts,fetcher),targets=resolveTargets(opts.apiHost);log.info(`collector: %s`,targets.collectorBaseUrl),getGlobal(FORCE_ENABLE_GLOBAL)&&log.warn(`FORCE_ENABLE is active. Events will be dropped by production collectors. This should only be set during local development.`);let tracker=new SessionTracker({target:targets.session,fetcher});opts._wrapperVersions?.length&&(globalThis[SDK_STACK_GLOBAL]=opts._wrapperVersions);let kernel=new Kernel(tracker),runtime=new PluginRuntime(kernel);if(kernel.attachRuntime(runtime),tracker.start(),runtime.start(),opts.tracing!==!1){let tracingOpts=typeof opts.tracing==`object`?opts.tracing:void 0;await wireOtel(kernel,targets,opts._wrapperVersions,{...tracingOpts??{},...opts.serviceName?{serviceName:opts.serviceName}:{},...opts._internalAdditionalSpanProcessors?{additionalSpanProcessors:opts._internalAdditionalSpanProcessors}:{},...opts._internalAdditionalLogRecordProcessors?{additionalLogRecordProcessors:opts._internalAdditionalLogRecordProcessors}:{},...opts._internalAdditionalMetricReaders?{additionalMetricReaders:opts._internalAdditionalMetricReaders}:{}})}return remotePlugins?runtime.applyRemoteConfig(remotePlugins):runtime.applyRemoteConfigDefaults(),kernel}async function resolveRemotePlugins(opts,fetcher){let baked=readBakedPlugins();if(baked)return baked;let remoteConfig=await fetchRemoteConfig(resolveTargets(opts.apiHost).config,fetcher);return remoteConfig?.ingestUrl&&setIngestHost(remoteConfig.ingestUrl),remoteConfig?.plugins??null}async function wireOtel(kernel,targets,wrapperVersions,tracing){let{buildOtelProvider,captureWebVitals,readPropagationFromDocument,registerBundledInstrumentations}=await import(`./otel/index.mjs`),collectorUrl=targets.collectorBaseUrl.replace(TRAILING_SLASH_RE,``),releaseSlug=readReleaseSlugFromGlobals(),handle=buildOtelProvider({collectorUrl,authHeaders:targets.ingest.headers,sdkStack:buildSdkStack(wrapperVersions),getSessionId:()=>kernel.session.getId(),getDeviceId:()=>kernel.device.getDeviceId(),releaseSlug,...tracing.serviceName?{serviceName:tracing.serviceName}:{},...tracing.additionalSpanProcessors?{additionalSpanProcessors:tracing.additionalSpanProcessors}:{},...tracing.additionalLogRecordProcessors?{additionalLogRecordProcessors:tracing.additionalLogRecordProcessors}:{},...tracing.additionalMetricReaders?{additionalMetricReaders:tracing.additionalMetricReaders}:{}}),extracted=readPropagationFromDocument();extracted&&handle.contextManager.setPageScope(extracted);let dispose=registerBundledInstrumentations({tracerProvider:handle.tracerProvider,loggerProvider:handle.loggerProvider,ignoreUrls:[`${collectorUrl}/v2/sink`,targets.config.url,targets.session.url,REPLAY_UPLOAD_RE],...tracing.apiHosts?{apiHosts:tracing.apiHosts}:{},...tracing.propagateContextUrls?{propagateContextUrls:tracing.propagateContextUrls}:{},...tracing.resolveRoute?{resolveRoute:tracing.resolveRoute}:{},...tracing.captureFailedRequests===void 0?{}:{captureFailedRequests:tracing.captureFailedRequests}});tracing.webVitals!==!1&&captureWebVitals({meter:handle.meterProvider.getMeter(`@interfere/react/web-vitals`),flush:()=>handle.flush(),...tracing.resolveRoute?{resolveRoute:tracing.resolveRoute}:{}}),kernel.attachOtel(handle,dispose),kernel.recordInitialNavigation(handle.loggerProvider)}async function fetchRemoteConfig(configTarget,fetcher){try{let headers=Object.fromEntries(configTarget.headers.entries()),res=await fetcher(configTarget.url,{method:`GET`,headers,credentials:`omit`,signal:AbortSignal.timeout(1e4)});return res.ok?await res.json():null}catch{return log.warn(`remote config fetch failed, using local defaults`),null}}function isEnabledByEnvironment(){if(typeof process>`u`||!process.env)return!0;let nodeEnv=process.env.NODE_ENV;return nodeEnv===`production`||nodeEnv===void 0||!!(getGlobal(FORCE_ENABLE_GLOBAL)||process.env.INTERFERE_FORCE_ENABLE)}function readReleaseSlugFromGlobals(){let value=getGlobal(RELEASE_SLUG_GLOBAL);return typeof value==`string`?releaseSlugSchema.parse(value):null}export{Kernel,buildSdkStack,createKernel,isEnabledByEnvironment,readReleaseSlugFromGlobals};
|
|
@@ -2,7 +2,6 @@ import { ExportResult } from "@opentelemetry/core";
|
|
|
2
2
|
import { AggregationTemporality, PushMetricExporter, ResourceMetrics } from "@opentelemetry/sdk-metrics";
|
|
3
3
|
import { ReadableLogRecord } from "@opentelemetry/sdk-logs";
|
|
4
4
|
import { SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
5
|
-
|
|
6
5
|
//#region src/internal/otel/exporter.d.ts
|
|
7
6
|
type SignalSender = (payload: Uint8Array | undefined, resultCallback: (result: ExportResult) => void) => void;
|
|
8
7
|
interface ExporterCommon {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Span } from "@opentelemetry/api";
|
|
2
2
|
import { LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
3
3
|
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
|
|
4
|
-
|
|
5
4
|
//#region src/internal/otel/instrumentations.d.ts
|
|
6
5
|
interface FetchErrorShape {
|
|
7
6
|
message: string;
|
|
@@ -5,37 +5,13 @@ import { LogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
|
5
5
|
import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
6
6
|
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
|
|
7
7
|
import { SessionId } from "@interfere/types/data/session";
|
|
8
|
-
|
|
9
8
|
//#region src/internal/otel/provider.d.ts
|
|
10
9
|
interface OtelProviderInput {
|
|
11
|
-
/**
|
|
12
|
-
* @internal
|
|
13
|
-
*
|
|
14
|
-
* Extra log-record processors fanned into the LoggerProvider's
|
|
15
|
-
* processor list at construction. Used by `@interfere/observability`
|
|
16
|
-
* for internal-only dual-write to BetterStack — keeps a parallel
|
|
17
|
-
* destination's queue/exporter independent of the SDK's own.
|
|
18
|
-
* Customers don't get a fan-out hook on the SDK surface; this is a
|
|
19
|
-
* private bridge for our own dogfood apps.
|
|
20
|
-
*/
|
|
10
|
+
/** @internal */
|
|
21
11
|
additionalLogRecordProcessors?: LogRecordProcessor[];
|
|
22
|
-
/**
|
|
23
|
-
* @internal
|
|
24
|
-
*
|
|
25
|
-
* Extra metric readers fanned into the MeterProvider's reader list
|
|
26
|
-
* at construction. Used by `@interfere/observability` for internal-
|
|
27
|
-
* only dual-write of web vitals histograms (`web_vitals.{ttfb,fcp,
|
|
28
|
-
* lcp,inp,cls}`) to the BetterStack-fronting OTel collector. Each
|
|
29
|
-
* reader owns its own queue + exporter so a 5xx / network outage on
|
|
30
|
-
* the parallel destination backs off only its own batch.
|
|
31
|
-
*/
|
|
12
|
+
/** @internal */
|
|
32
13
|
additionalMetricReaders?: MetricReader[];
|
|
33
|
-
/**
|
|
34
|
-
* @internal
|
|
35
|
-
*
|
|
36
|
-
* Extra span processors fanned into the WebTracerProvider's processor
|
|
37
|
-
* list at construction. See `additionalLogRecordProcessors`.
|
|
38
|
-
*/
|
|
14
|
+
/** @internal */
|
|
39
15
|
additionalSpanProcessors?: SpanProcessor[];
|
|
40
16
|
/**
|
|
41
17
|
* Auth + content headers for OTLP exports. Sourced from the kernel's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getGlobal}from"../../util/global.mjs";import{SDK_NAME,SDK_VERSION}from"../version.mjs";import{createLogExporter,createMetricExporter,createTraceExporter}from"./exporter.mjs";import{PageScopeContextManager}from"./page-scope-context-manager.mjs";import{context,propagation}from"@opentelemetry/api";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{resolveEnvironment}from"@interfere/types/sdk/runtime";import{browserDetector}from"@opentelemetry/opentelemetry-browser-detector";import{detectResources,resourceFromAttributes}from"@opentelemetry/resources";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{WebTracerProvider}from"@opentelemetry/sdk-trace-web";import{createSessionLogRecordProcessor,createSessionSpanProcessor}from"@opentelemetry/web-common";const ATTR_DEVICE_ID=`device.id`,BROWSER_BATCH_OPTIONS={maxQueueSize:50,maxExportBatchSize:10,scheduledDelayMillis:2e3,exportTimeoutMillis:1e4};function createDeviceSpanProcessor(opts){return{onStart(span){let id=opts.getDeviceId();id&&span.setAttribute(ATTR_DEVICE_ID,id)},onEnd(){},forceFlush:()=>Promise.resolve(),shutdown:()=>Promise.resolve()}}function createDeviceLogRecordProcessor(opts){return{onEmit(logRecord){let id=opts.getDeviceId();id&&logRecord.setAttribute(ATTR_DEVICE_ID,id)},forceFlush:()=>Promise.resolve(),shutdown:()=>Promise.resolve()}}function buildOtelProvider(input){let environment=resolveEnvironment({explicit:getGlobal(
|
|
1
|
+
import{getGlobal}from"../../util/global.mjs";import{SDK_NAME,SDK_VERSION}from"../version.mjs";import{createLogExporter,createMetricExporter,createTraceExporter}from"./exporter.mjs";import{PageScopeContextManager}from"./page-scope-context-manager.mjs";import{context,propagation}from"@opentelemetry/api";import{ENVIRONMENT_GLOBAL}from"@interfere/types/sdk/injected-globals";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{resolveEnvironment}from"@interfere/types/sdk/runtime";import{browserDetector}from"@opentelemetry/opentelemetry-browser-detector";import{detectResources,resourceFromAttributes}from"@opentelemetry/resources";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{WebTracerProvider}from"@opentelemetry/sdk-trace-web";import{createSessionLogRecordProcessor,createSessionSpanProcessor}from"@opentelemetry/web-common";const ATTR_DEVICE_ID=`device.id`,BROWSER_BATCH_OPTIONS={maxQueueSize:50,maxExportBatchSize:10,scheduledDelayMillis:2e3,exportTimeoutMillis:1e4};function createDeviceSpanProcessor(opts){return{onStart(span){let id=opts.getDeviceId();id&&span.setAttribute(ATTR_DEVICE_ID,id)},onEnd(){},forceFlush:()=>Promise.resolve(),shutdown:()=>Promise.resolve()}}function createDeviceLogRecordProcessor(opts){return{onEmit(logRecord){let id=opts.getDeviceId();id&&logRecord.setAttribute(ATTR_DEVICE_ID,id)},forceFlush:()=>Promise.resolve(),shutdown:()=>Promise.resolve()}}function buildOtelProvider(input){let environment=resolveEnvironment({explicit:getGlobal(ENVIRONMENT_GLOBAL),env:typeof process>`u`?{}:{INTERFERE_ENVIRONMENT:process.env.INTERFERE_ENVIRONMENT,VERCEL_ENV:process.env.VERCEL_ENV,NODE_ENV:process.env.NODE_ENV}}),baseResource=resourceFromAttributes({"service.name":input.serviceName??`interfere-sdk`,"service.namespace":`interfere`,"deployment.environment.name":environment,"telemetry.sdk.language":`webjs`,"interfere.sdk.name":SDK_NAME,"interfere.sdk.version":SDK_VERSION,"interfere.sdk.stack":input.sdkStack.join(`, `),...input.releaseSlug?{"release.slug":input.releaseSlug}:{}}),detected=detectResources({detectors:[browserDetector]}),resource=baseResource.merge(detected),traceExporter=createTraceExporter({collectorUrl:input.collectorUrl,authHeaders:input.authHeaders}),getSessionId=input.getSessionId,getDeviceId=input.getDeviceId,tracerProvider=new WebTracerProvider({resource,spanProcessors:[createSessionSpanProcessor({getSessionId}),createDeviceSpanProcessor({getDeviceId}),new BatchSpanProcessor(traceExporter,BROWSER_BATCH_OPTIONS),...input.additionalSpanProcessors??[]]}),contextManager=new PageScopeContextManager;contextManager.enable(),context.setGlobalContextManager(contextManager)||contextManager.disable(),propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,new W3CBaggagePropagator]}));let metricReader=new PeriodicExportingMetricReader({exporter:createMetricExporter({collectorUrl:input.collectorUrl,authHeaders:input.authHeaders}),exportIntervalMillis:3e4}),meterProvider=new MeterProvider({resource,readers:[metricReader,...input.additionalMetricReaders??[]]}),logExporter=createLogExporter({collectorUrl:input.collectorUrl,authHeaders:input.authHeaders}),loggerProvider=new LoggerProvider({resource,processors:[createSessionLogRecordProcessor({getSessionId}),createDeviceLogRecordProcessor({getDeviceId}),new BatchLogRecordProcessor(logExporter,BROWSER_BATCH_OPTIONS),...input.additionalLogRecordProcessors??[]]});return{contextManager,tracerProvider,meterProvider,metricReader,loggerProvider,flush:async()=>{await Promise.all([tracerProvider.forceFlush(),metricReader.forceFlush(),loggerProvider.forceFlush()])},shutdown:async()=>{await Promise.all([tracerProvider.shutdown(),meterProvider.shutdown(),loggerProvider.shutdown()])}}}export{buildOtelProvider};
|
|
@@ -3,7 +3,6 @@ import { PluginConfigState, PluginContext } from "../plugins/lib/types.mjs";
|
|
|
3
3
|
import { PluginOverrides } from "../plugins/lib/loader.mjs";
|
|
4
4
|
import { ConsentState, PluginKey } from "@interfere/types/sdk/plugins/manifest";
|
|
5
5
|
import { RemotePluginConfig } from "@interfere/types/sdk/remote-config";
|
|
6
|
-
|
|
7
6
|
//#region src/internal/plugin-runtime.d.ts
|
|
8
7
|
declare class PluginRuntime {
|
|
9
8
|
private readonly activeCleanups;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Kernel } from "./kernel.mjs";
|
|
2
2
|
import { ConsentState } from "@interfere/types/sdk/plugins/manifest";
|
|
3
3
|
import { IdentifyParams } from "@interfere/types/sdk/identify";
|
|
4
|
-
|
|
5
4
|
//#region src/internal/react-context.d.ts
|
|
6
5
|
interface InterfereContextValue {
|
|
7
6
|
consent: {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Kernel, KernelOptions } from "./kernel.mjs";
|
|
2
2
|
import { ConsentState } from "@interfere/types/sdk/plugins/manifest";
|
|
3
3
|
import { IdentifyParams } from "@interfere/types/sdk/identify";
|
|
4
|
-
|
|
5
4
|
//#region src/internal/wrapper-singleton.d.ts
|
|
6
5
|
interface WrapperSingleton {
|
|
7
6
|
close(): Promise<void>;
|
package/dist/package.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var name=`@interfere/react`,version=`11.0.
|
|
1
|
+
var name=`@interfere/react`,version=`11.0.4`;export{name,version};
|
package/dist/plugins/errors.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{hasServerDigest}from"../internal/server-digest.mjs";import{onConsoleCall}from"../internal/console-patch.mjs";import{THIRD_PARTY_IGNORE}from"../internal/third-party-hosts.mjs";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";function capture(ctx,opts){ctx.recordException(opts.error,{mechanism:opts.mechanism,...opts.fallbackFrame&&!isNonErrorException(opts.error)?{fallbackFrames:[opts.fallbackFrame]}:{}})}function findErrorArg(args){return args.find(arg=>arg instanceof Error)??null}function resourceError(target){return target instanceof HTMLImageElement||target instanceof HTMLScriptElement?target.src?{tag:target.localName,url:target.src}:null:target instanceof HTMLLinkElement&&target.href?{tag:target.localName,url:target.href}:null}function isIgnoredResourceUrl(url){return THIRD_PARTY_IGNORE.some(pattern=>pattern.test(url))}function createResourceGate(){let seen=new Set,windowStart=0,windowCount=0;return url=>{if(seen.has(url))return!1;let now=Date.now();return now-windowStart>6e4&&(windowStart=now,windowCount=0),windowCount>=20?!1:(seen.size>=100&&seen.clear(),seen.add(url),windowCount+=1,!0)}}const errorsPlugin={name:`errors`,setup(ctx){let originalOnError=globalThis.onerror,originalStackTraceLimit=Error.stackTraceLimit;Error.stackTraceLimit<50&&(Error.stackTraceLimit=50),globalThis.onerror=(msg,source,line,col,error)=>{if(error instanceof Error&&!hasServerDigest(error)){let fallbackFrame=typeof source==`string`?{id:`fallback-0`,file:source,...typeof line==`number`?{line}:{},...typeof col==`number`?{column:col}:{}}:null;capture(ctx,{error,mechanism:{type:MECHANISM_TYPE.browser.onerror,handled:!1},...fallbackFrame?{fallbackFrame}:{}})}return typeof originalOnError==`function
|
|
1
|
+
import{hasServerDigest}from"../internal/server-digest.mjs";import{onConsoleCall}from"../internal/console-patch.mjs";import{THIRD_PARTY_IGNORE}from"../internal/third-party-hosts.mjs";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";function capture(ctx,opts){ctx.recordException(opts.error,{mechanism:opts.mechanism,...opts.fallbackFrame&&!isNonErrorException(opts.error)?{fallbackFrames:[opts.fallbackFrame]}:{}})}function findErrorArg(args){return args.find(arg=>arg instanceof Error)??null}function resourceError(target){return target instanceof HTMLImageElement||target instanceof HTMLScriptElement?target.src?{tag:target.localName,url:target.src}:null:target instanceof HTMLLinkElement&&target.href?{tag:target.localName,url:target.href}:null}function isIgnoredResourceUrl(url){return THIRD_PARTY_IGNORE.some(pattern=>pattern.test(url))}function createResourceGate(){let seen=new Set,windowStart=0,windowCount=0;return url=>{if(seen.has(url))return!1;let now=Date.now();return now-windowStart>6e4&&(windowStart=now,windowCount=0),windowCount>=20?!1:(seen.size>=100&&seen.clear(),seen.add(url),windowCount+=1,!0)}}const errorsPlugin={name:`errors`,setup(ctx){let originalOnError=globalThis.onerror,originalStackTraceLimit=Error.stackTraceLimit;Error.stackTraceLimit<50&&(Error.stackTraceLimit=50),globalThis.onerror=(msg,source,line,col,error)=>{if(error instanceof Error&&!hasServerDigest(error)){let fallbackFrame=typeof source==`string`?{id:`fallback-0`,file:source,...typeof line==`number`?{line}:{},...typeof col==`number`?{column:col}:{}}:null;capture(ctx,{error,mechanism:{type:MECHANISM_TYPE.browser.onerror,handled:!1},...fallbackFrame?{fallbackFrame}:{}})}return typeof originalOnError==`function`&&originalOnError.call(globalThis,msg,source,line,col,error)};let onUnhandledRejection=event=>{hasServerDigest(event.reason)||capture(ctx,{error:toException(event.reason),mechanism:{type:MECHANISM_TYPE.browser.onunhandledrejection,handled:!1,...event.reason instanceof Error?{}:{synthetic:!0}}})},seenCspReports=new Set,onSecurityPolicyViolation=event=>{let key=`${event.violatedDirective}|${event.blockedURI}`;seenCspReports.has(key)||seenCspReports.size>=5||(seenCspReports.add(key),capture(ctx,{error:{kind:`non-error`,type:`SecurityPolicyViolation`,value:`CSP ${event.violatedDirective} blocked ${event.blockedURI||`inline`}`,serialized:{violatedDirective:event.violatedDirective,blockedURI:event.blockedURI,sourceFile:event.sourceFile,lineNumber:event.lineNumber,columnNumber:event.columnNumber,disposition:event.disposition}},mechanism:{type:MECHANISM_TYPE.browser.securityPolicyViolation,handled:!1}}))},resourceGate=createResourceGate(),onResourceError=event=>{let resource=resourceError(event.target);!resource||isIgnoredResourceUrl(resource.url)||!resourceGate(resource.url)||capture(ctx,{error:{kind:`non-error`,type:`ResourceLoadError`,value:`Failed to load ${resource.tag}: ${resource.url}`,serialized:{url:resource.url}},mechanism:{type:MECHANISM_TYPE.browser.resourceError,handled:!1}})},supportsEventTarget=typeof globalThis.addEventListener==`function`&&typeof globalThis.removeEventListener==`function`;supportsEventTarget&&(globalThis.addEventListener(`unhandledrejection`,onUnhandledRejection),globalThis.addEventListener(`securitypolicyviolation`,onSecurityPolicyViolation),globalThis.addEventListener(`error`,onResourceError,!0));let unsubscribeConsole=onConsoleCall((level,args)=>{if(level!==`error`)return;let error=findErrorArg(args);error&&!hasServerDigest(error)&&capture(ctx,{error,mechanism:{type:MECHANISM_TYPE.browser.consoleError,handled:!0}})});return()=>{Error.stackTraceLimit=originalStackTraceLimit,globalThis.onerror=originalOnError,supportsEventTarget&&(globalThis.removeEventListener(`unhandledrejection`,onUnhandledRejection),globalThis.removeEventListener(`securitypolicyviolation`,onSecurityPolicyViolation),globalThis.removeEventListener(`error`,onResourceError,!0)),unsubscribeConsole()}}};export{errorsPlugin as default};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ReplayOption } from "../replay/config.mjs";
|
|
2
2
|
import { PluginCleanup, PluginContext } from "./types.mjs";
|
|
3
3
|
import { PluginKey } from "@interfere/types/sdk/plugins/manifest";
|
|
4
|
-
|
|
5
4
|
//#region src/plugins/lib/loader.d.ts
|
|
6
5
|
type PluginOverrides = Partial<Record<Exclude<PluginKey, "replay">, boolean>> & {
|
|
7
6
|
replay?: ReplayOption;
|
|
@@ -3,7 +3,6 @@ import { SessionResumeReason } from "../../internal/activity.mjs";
|
|
|
3
3
|
import { RecordExceptionOpts } from "../../internal/kernel.mjs";
|
|
4
4
|
import { NonErrorException } from "@interfere/types/sdk/errors";
|
|
5
5
|
import { PluginKey } from "@interfere/types/sdk/plugins/manifest";
|
|
6
|
-
|
|
7
6
|
//#region src/plugins/lib/types.d.ts
|
|
8
7
|
type PluginCleanup = () => void;
|
|
9
8
|
type PluginConfigState = "disabled" | "enabled" | "pending";
|
|
@@ -11,6 +10,7 @@ interface PluginContext {
|
|
|
11
10
|
getPluginConfigState(key: PluginKey): PluginConfigState;
|
|
12
11
|
getReplayConfig(): ReplayConfig;
|
|
13
12
|
getSessionId(): string;
|
|
13
|
+
getWindowId(): string;
|
|
14
14
|
onSessionPause(handler: () => void): () => void;
|
|
15
15
|
onSessionResume(handler: (reason: SessionResumeReason) => void): () => void;
|
|
16
16
|
recordException(value: Error | NonErrorException, opts: RecordExceptionOpts): void;
|
package/dist/plugins/logs.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{utf8ByteLength}from"./chunking.mjs";function createReplayBuffer(opts){let entries=[],totalBytes=0;return{push(event){let json=JSON.stringify(event),bytes=utf8ByteLength(json);entries.push({json,ts:Date.now(),bytes}),totalBytes+=bytes,totalBytes>=opts.softLimitBytes&&opts.onSoftLimit()},drain(){let drained=entries;return entries=[],totalBytes=0,drained}}}export{createReplayBuffer};
|
|
1
|
+
import{classifyReplayEvent,utf8ByteLength}from"./chunking.mjs";function createReplayBuffer(opts){let entries=[],totalBytes=0;return{push(event){let json=JSON.stringify(event),bytes=utf8ByteLength(json),{isActivity,isFullSnapshot}=classifyReplayEvent(event);entries.push({json,ts:Date.now(),bytes,isActivity,isFullSnapshot}),totalBytes+=bytes,totalBytes>=opts.softLimitBytes&&opts.onSoftLimit()},drain(){let drained=entries;return entries=[],totalBytes=0,drained}}}export{createReplayBuffer};
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
//#region src/plugins/replay/chunking.d.ts
|
|
2
2
|
interface BufferedReplayEvent {
|
|
3
3
|
bytes: number;
|
|
4
|
+
isActivity: boolean;
|
|
5
|
+
isFullSnapshot: boolean;
|
|
4
6
|
json: string;
|
|
5
7
|
ts: number;
|
|
6
8
|
}
|
|
7
9
|
interface ReplayChunkPayload {
|
|
10
|
+
activityCount: number;
|
|
8
11
|
bodyJson: string;
|
|
9
12
|
eventCount: number;
|
|
10
13
|
firstTs: number | null;
|
|
14
|
+
hasFullSnapshot: boolean;
|
|
11
15
|
lastTs: number | null;
|
|
12
16
|
}
|
|
13
17
|
interface SplitReplayEventsResult {
|
|
14
18
|
chunks: BufferedReplayEvent[][];
|
|
15
19
|
droppedEventBytes: number[];
|
|
16
20
|
}
|
|
21
|
+
declare function classifyReplayEvent(event: unknown): {
|
|
22
|
+
isActivity: boolean;
|
|
23
|
+
isFullSnapshot: boolean;
|
|
24
|
+
};
|
|
17
25
|
declare function toReplayChunkPayload(group: BufferedReplayEvent[]): ReplayChunkPayload;
|
|
18
26
|
declare function splitReplayEvents(buffered: BufferedReplayEvent[]): SplitReplayEventsResult;
|
|
19
27
|
declare function utf8ByteLength(value: string): number;
|
|
20
28
|
//#endregion
|
|
21
|
-
export { BufferedReplayEvent, ReplayChunkPayload, SplitReplayEventsResult, splitReplayEvents, toReplayChunkPayload, utf8ByteLength };
|
|
29
|
+
export { BufferedReplayEvent, ReplayChunkPayload, SplitReplayEventsResult, classifyReplayEvent, splitReplayEvents, toReplayChunkPayload, utf8ByteLength };
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
const textEncoder=new TextEncoder;function
|
|
1
|
+
import{EventType,IncrementalSource}from"@rrweb/types";const textEncoder=new TextEncoder,ACTIVITY_SOURCES=new Set([IncrementalSource.MouseMove,IncrementalSource.MouseInteraction,IncrementalSource.Scroll,IncrementalSource.Input,IncrementalSource.TouchMove,IncrementalSource.Drag,IncrementalSource.Selection]);function classifyReplayEvent(event){let typed=event;if(!typed||typeof typed.type!=`number`)return{isActivity:!1,isFullSnapshot:!1};if(typed.type===EventType.FullSnapshot)return{isActivity:!1,isFullSnapshot:!0};if(typed.type===EventType.IncrementalSnapshot&&typed.data){let source=typed.data.source;if(source!==void 0&&ACTIVITY_SOURCES.has(source))return{isActivity:!0,isFullSnapshot:!1}}return{isActivity:!1,isFullSnapshot:!1}}function countActivityEvents(group){let count=0;for(let entry of group)entry.isActivity&&(count+=1);return count}function toReplayChunkPayload(group){let parts=[],hasFullSnapshot=!1;for(let entry of group)parts.push(entry.json),entry.isFullSnapshot&&(hasFullSnapshot=!0);let firstTs=group[0]?.ts??null;return{activityCount:countActivityEvents(group),bodyJson:parts.length>0?`${parts.join(`
|
|
2
|
+
`)}\n`:``,eventCount:group.length,firstTs,hasFullSnapshot,lastTs:group.at(-1)?.ts??null}}function splitReplayEvents(buffered){let chunks=[],droppedEventBytes=[],current=[],currentBytes=0;for(let entry of buffered){let singleEventBodyBytes=entry.bytes+1;if(singleEventBodyBytes>8388608){droppedEventBytes.push(singleEventBodyBytes);continue}current.length>0&¤tBytes+singleEventBodyBytes>6291456&&(chunks.push(current),current=[],currentBytes=0),currentBytes+=singleEventBodyBytes,current.push(entry)}return current.length>0&&chunks.push(current),{chunks,droppedEventBytes}}function utf8ByteLength(value){return textEncoder.encode(value).length}export{classifyReplayEvent,splitReplayEvents,toReplayChunkPayload,utf8ByteLength};
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { PluginContext } from "../lib/types.mjs";
|
|
2
2
|
import { ReplayChunkPayload } from "./chunking.mjs";
|
|
3
3
|
import { Compressor } from "./compressor-host.mjs";
|
|
4
|
-
|
|
5
4
|
//#region src/plugins/replay/delivery.d.ts
|
|
5
|
+
type DeliverResult = "ok" | "retryable" | "fatal";
|
|
6
|
+
interface ReplayChunkRef {
|
|
7
|
+
segmentId: number;
|
|
8
|
+
windowId: string;
|
|
9
|
+
}
|
|
6
10
|
interface DeliverInput {
|
|
7
11
|
authHeaders: Record<string, string>;
|
|
12
|
+
chunk: ReplayChunkRef;
|
|
8
13
|
compressor: Compressor;
|
|
9
14
|
ctx: PluginContext;
|
|
10
15
|
payload: ReplayChunkPayload;
|
|
11
16
|
skipCompression: boolean;
|
|
12
17
|
uploadBaseUrl: string;
|
|
13
18
|
}
|
|
14
|
-
declare function deliverChunk({
|
|
15
|
-
ctx,
|
|
16
|
-
uploadBaseUrl,
|
|
17
|
-
authHeaders,
|
|
18
|
-
compressor,
|
|
19
|
-
payload,
|
|
20
|
-
skipCompression
|
|
21
|
-
}: DeliverInput): Promise<void>;
|
|
19
|
+
declare function deliverChunk({ ctx, chunk, uploadBaseUrl, authHeaders, compressor, payload, skipCompression }: DeliverInput): Promise<DeliverResult>;
|
|
22
20
|
//#endregion
|
|
23
|
-
export { DeliverInput, deliverChunk };
|
|
21
|
+
export { DeliverInput, DeliverResult, ReplayChunkRef, deliverChunk };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"../../util/log.mjs";import{appendPathBeforeQuery}from"../../internal/config.mjs";import{trace}from"@opentelemetry/api";const log=createLogger(`replay`),textEncoder=new TextEncoder;async function prepareBody(compressor,rawBytes){if(!compressor.gzip)return{body:rawBytes,encoding:null};try{return{body:await compressor.gzip(rawBytes),encoding:`gzip`}}catch(error){return log.warn(`gzip failed for chunk; sending uncompressed: %o`,error),{body:rawBytes,encoding:null}}}async function deliverChunk({ctx,uploadBaseUrl,authHeaders,compressor,payload,skipCompression}){let sessionId=ctx.getSessionId();if(!sessionId)return
|
|
1
|
+
import{createLogger}from"../../util/log.mjs";import{appendPathBeforeQuery}from"../../internal/config.mjs";import{trace}from"@opentelemetry/api";const log=createLogger(`replay`),textEncoder=new TextEncoder;async function prepareBody(compressor,rawBytes){if(!compressor.gzip)return{body:rawBytes,encoding:null};try{return{body:await compressor.gzip(rawBytes),encoding:`gzip`}}catch(error){return log.warn(`gzip failed for chunk; sending uncompressed: %o`,error),{body:rawBytes,encoding:null}}}function encodeReplayMeta(chunk,payload){return btoa(JSON.stringify({windowId:chunk.windowId,segmentId:chunk.segmentId,firstTs:payload.firstTs,lastTs:payload.lastTs,eventCount:payload.eventCount,hasFullSnapshot:payload.hasFullSnapshot,activityCount:payload.activityCount}))}async function deliverChunk({ctx,chunk,uploadBaseUrl,authHeaders,compressor,payload,skipCompression}){let sessionId=ctx.getSessionId();if(!sessionId)return`ok`;let rawBytes=textEncoder.encode(payload.bodyJson),uncompressedBytes=rawBytes.byteLength,prepared=skipCompression?{body:rawBytes,encoding:null}:await prepareBody(compressor,rawBytes),headers={...authHeaders,"content-type":`application/json`,"x-replay-meta":encodeReplayMeta(chunk,payload),...prepared.encoding===`gzip`?{"content-encoding":`gzip`}:{}},res;try{res=await fetch(appendPathBeforeQuery(uploadBaseUrl,`/v2/replay/upload/${encodeURIComponent(sessionId)}`),{method:`POST`,headers,credentials:`omit`,body:prepared.body})}catch(error){return log.warn(`replay chunk upload failed: %o`,error),`retryable`}if(!res.ok)return log.warn(`replay chunk upload rejected (%d)`,res.status),res.status>=400&&res.status<500?`fatal`:`retryable`;let objectKey=await res.json().catch(()=>({}));return trace.getTracer(`@interfere/react/replay`).startSpan(`replay.chunk`,{attributes:{...objectKey.objectKey?{"replay.chunk.uri":objectKey.objectKey}:{},"replay.chunk.size_bytes":uncompressedBytes,...prepared.encoding===`gzip`?{"replay.chunk.compressed_bytes":prepared.body.byteLength}:{},"replay.chunk.event_count":payload.eventCount,...payload.firstTs===null?{}:{"replay.chunk.first_event_ts":payload.firstTs},...payload.lastTs===null?{}:{"replay.chunk.last_event_ts":payload.lastTs}}}).end(),`ok`}export{deliverChunk};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"../../util/log.mjs";import{onPageHidden,onPageShown}from"../../internal/page-lifecycle.mjs";import{resolveTargets}from"../../internal/config.mjs";import{splitReplayEvents,toReplayChunkPayload}from"./chunking.mjs";import{createReplayBuffer}from"./buffer.mjs";import{createCompressor}from"./compressor-host.mjs";import{toRecordOptions}from"./config.mjs";import{deliverChunk}from"./delivery.mjs";import{startReplayRecorder}from"./recorder.mjs";const log=createLogger(`replay`),replayPlugin={name:`replay`,setup(ctx){let targets=resolveTargets(),uploadBaseUrl=targets.collectorBaseUrl,authHeaders=Object.fromEntries(targets.ingest.headers.entries()),recorder=null,flushTimer=null,unsubscribeConfig=null,unsubscribeHidden=null,unsubscribeShown=null,unsubscribePause=null,unsubscribeResume=null,isPaused=!1,compressor=createCompressor();function flush(opts){if(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)deliverChunk({ctx,uploadBaseUrl,authHeaders,compressor,payload:toReplayChunkPayload(group),skipCompression:opts?.skipCompression??!1}).catch(error=>log.warn(`replay chunk dropped: %o`,error))}let buffer=createReplayBuffer({softLimitBytes:4194304,onSoftLimit:flush}),pauseSending=unload=>{isPaused||(isPaused=!0,flush(unload?{skipCompression:!0}:void 0))},resumeSending=()=>{isPaused&&(isPaused=!1,recorder?.takeFullSnapshot())},recordOptions=toRecordOptions(ctx.getReplayConfig());return(async()=>{recorder=await startReplayRecorder(event=>{isPaused||buffer.push(event)},recordOptions),recorder&&(unsubscribeConfig=ctx.subscribePluginConfigState(`replay`,state=>{state===`enabled`&&flush()}),flushTimer=setInterval(flush,1e4),unsubscribeHidden=onPageHidden(()=>pauseSending(!0)),unsubscribeShown=onPageShown(resumeSending),unsubscribePause=ctx.onSessionPause(()=>pauseSending(!1)),unsubscribeResume=ctx.onSessionResume(resumeSending),log.debug(`recording started`))})(),()=>{flush(),recorder?.stop(),flushTimer&&clearInterval(flushTimer),unsubscribeConfig?.(),unsubscribeHidden?.(),unsubscribeShown?.(),unsubscribePause?.(),unsubscribeResume?.(),compressor.dispose()}}};export{replayPlugin as default};
|
|
1
|
+
import{createLogger}from"../../util/log.mjs";import{onPageHidden,onPageShown}from"../../internal/page-lifecycle.mjs";import{resolveTargets}from"../../internal/config.mjs";import{splitReplayEvents,toReplayChunkPayload}from"./chunking.mjs";import{createReplayBuffer}from"./buffer.mjs";import{createCompressor}from"./compressor-host.mjs";import{toRecordOptions}from"./config.mjs";import{deliverChunk}from"./delivery.mjs";import{startReplayRecorder}from"./recorder.mjs";import{createSegmentSequence}from"./sequence.mjs";const log=createLogger(`replay`),replayPlugin={name:`replay`,setup(ctx){let targets=resolveTargets(),uploadBaseUrl=targets.collectorBaseUrl,authHeaders=Object.fromEntries(targets.ingest.headers.entries()),recorder=null,flushTimer=null,unsubscribeConfig=null,unsubscribeHidden=null,unsubscribeShown=null,unsubscribePause=null,unsubscribeResume=null,isPaused=!1,compressor=createCompressor(),windowId=ctx.getWindowId(),sequence=createSegmentSequence(windowId),consecutiveFailures=0,halted=!1;function halt(){halted||(halted=!0,flushTimer&&=(clearInterval(flushTimer),null),recorder?.stop(),recorder=null)}function handleResult(result){if(result===`ok`){consecutiveFailures=0;return}if(result===`fatal`){log.warn(`replay halted: upload rejected`),halt();return}consecutiveFailures+=1,consecutiveFailures>=3&&(log.warn(`replay halted after %d consecutive upload failures`,consecutiveFailures),halt())}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)deliverChunk({ctx,chunk:{windowId,segmentId:sequence.take()},uploadBaseUrl,authHeaders,compressor,payload:toReplayChunkPayload(group),skipCompression:opts?.skipCompression??!1}).then(handleResult).catch(error=>{log.warn(`replay chunk dropped: %o`,error),handleResult(`retryable`)})}let buffer=createReplayBuffer({softLimitBytes:4194304,onSoftLimit:flush}),pauseSending=unload=>{isPaused||(isPaused=!0,flush(unload?{skipCompression:!0}:void 0))},resumeSending=()=>{isPaused&&(isPaused=!1,recorder?.takeFullSnapshot())},recordOptions=toRecordOptions(ctx.getReplayConfig());return(async()=>{recorder=await startReplayRecorder(event=>{isPaused||buffer.push(event)},recordOptions),recorder&&(unsubscribeConfig=ctx.subscribePluginConfigState(`replay`,state=>{state===`enabled`&&flush()}),flushTimer=setInterval(flush,1e4),unsubscribeHidden=onPageHidden(()=>pauseSending(!0)),unsubscribeShown=onPageShown(resumeSending),unsubscribePause=ctx.onSessionPause(()=>pauseSending(!1)),unsubscribeResume=ctx.onSessionResume(resumeSending),log.debug(`recording started`))})(),()=>{flush(),recorder?.stop(),flushTimer&&clearInterval(flushTimer),unsubscribeConfig?.(),unsubscribeHidden?.(),unsubscribeShown?.(),unsubscribePause?.(),unsubscribeResume?.(),compressor.dispose()}}};export{replayPlugin as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"../../util/log.mjs";const log=createLogger(`replay`);async function startReplayRecorder(onEvent,maskingOptions){try{let rrweb=await import(`rrweb`),stop=rrweb.record({emit:onEvent,recordAfter:`load`,inlineStylesheet:!0,slimDOMOptions:`all`,sampling:{mousemove:50,scroll:150,media:800},...maskingOptions})??null;return{stop:()=>{stop?.()},takeFullSnapshot:()=>{try{rrweb.record.takeFullSnapshot?.(!0)}catch(error){log.warn(`takeFullSnapshot failed: %o`,error)}}}}catch{return log.error(`rrweb failed to load, replay disabled`),null}}export{startReplayRecorder};
|
|
1
|
+
import{createLogger}from"../../util/log.mjs";const log=createLogger(`replay`);async function startReplayRecorder(onEvent,maskingOptions){try{let rrweb=await import(`rrweb`),stop=rrweb.record({emit:onEvent,recordAfter:`load`,inlineStylesheet:!0,slimDOMOptions:`all`,checkoutEveryNms:6e4,sampling:{mousemove:50,scroll:150,media:800},...maskingOptions})??null;return{stop:()=>{stop?.()},takeFullSnapshot:()=>{try{rrweb.record.takeFullSnapshot?.(!0)}catch(error){log.warn(`takeFullSnapshot failed: %o`,error)}}}}catch{return log.error(`rrweb failed to load, replay disabled`),null}}export{startReplayRecorder};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function sessionStore(){try{let store=globalThis.sessionStorage,probe=`__interfere_replay_seq_probe__`;return store.setItem(probe,`1`),store.removeItem(probe),store}catch{return null}}function createSegmentSequence(windowId){let key=`interfere:replay_seq:${windowId}`,store=sessionStore(),stored=store?.getItem(key),next=stored?Number(stored):0;return(!Number.isInteger(next)||next<0)&&(next=0),{take(){let seq=next;return next+=1,store?.setItem(key,String(next)),seq}}}export{createSegmentSequence};
|
package/dist/provider.d.mts
CHANGED
|
@@ -4,7 +4,6 @@ import { Kernel } from "./internal/kernel.mjs";
|
|
|
4
4
|
import { InterfereContext, InterfereContextValue } from "./internal/react-context.mjs";
|
|
5
5
|
import { PropsWithChildren, ReactNode } from "react";
|
|
6
6
|
import { ConsentState } from "@interfere/types/sdk/plugins/manifest";
|
|
7
|
-
|
|
8
7
|
//#region src/provider.d.ts
|
|
9
8
|
interface InterfereProviderProps extends PropsWithChildren {
|
|
10
9
|
/**
|
|
@@ -53,13 +52,7 @@ interface InterfereProviderProps extends PropsWithChildren {
|
|
|
53
52
|
*/
|
|
54
53
|
plugins?: PluginOverrides | undefined;
|
|
55
54
|
}
|
|
56
|
-
declare function InterfereProvider({
|
|
57
|
-
kernel,
|
|
58
|
-
children,
|
|
59
|
-
consent,
|
|
60
|
-
plugins,
|
|
61
|
-
errorBoundary
|
|
62
|
-
}: InterfereProviderProps): ReactNode;
|
|
55
|
+
declare function InterfereProvider({ kernel, children, consent, plugins, errorBoundary }: InterfereProviderProps): ReactNode;
|
|
63
56
|
declare function useInterfere(): InterfereContextValue;
|
|
64
57
|
declare function useSession(): string | null;
|
|
65
58
|
//#endregion
|
package/dist/tracking/api.d.mts
CHANGED
|
@@ -4,7 +4,6 @@ import { DeviceManager } from "./device.mjs";
|
|
|
4
4
|
import { GeoDetector } from "./geo.mjs";
|
|
5
5
|
import { SessionId } from "@interfere/types/data/session";
|
|
6
6
|
import { IdentifyParams } from "@interfere/types/sdk/identify";
|
|
7
|
-
|
|
8
7
|
//#region src/tracking/api.d.ts
|
|
9
8
|
interface SessionTrackerOptions {
|
|
10
9
|
device?: DeviceManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v7}from"uuid";const SESSION_ID_KEY=`interfere:session_id`,LAST_ACTIVITY_KEY=`interfere:last_activity`,SESSION_STARTED_KEY=`interfere:session_started`,WINDOW_ID_KEY=`interfere:window_id`;function tryStorage(type){try{let s=globalThis[type],key=`__interfere_probe__`;return s.setItem(key,`1`),s.removeItem(key),s}catch{return null}}var SessionManager=class{sessionId=null;windowId=null;local;session;onRotate=null;lastActivityMs=0;sessionStartedMs=0;constructor(onRotate){this.local=tryStorage(`localStorage`),this.session=tryStorage(`sessionStorage`),this.onRotate=onRotate??null,this.restore()}getSessionId(){return this.sessionId?this.sessionId:this.rotate()}markActivity(){this.touch()}getSessionStartedAt(){return this.sessionStartedMs}getWindowId(){if(this.windowId)return this.windowId;let stored=this.session?.getItem(WINDOW_ID_KEY);return stored?(this.windowId=stored,stored):(this.windowId=`win_${crypto.randomUUID()}`,this.session?.setItem(WINDOW_ID_KEY,this.windowId),this.windowId)}reset(){return this.rotate()}restore(){let stored=this.local?.getItem(SESSION_ID_KEY),startedRaw=this.local?.getItem(SESSION_STARTED_KEY);this.sessionStartedMs=startedRaw?Number(startedRaw):0,stored&&!this.isExpired()?(this.sessionId=stored,this.touch()):this.rotate()}rotate(){return this.sessionId=v7(),this.sessionStartedMs=Date.now(),this.local?.setItem(SESSION_ID_KEY,this.sessionId),this.local?.setItem(SESSION_STARTED_KEY,String(this.sessionStartedMs)),this.touch(),this.onRotate?.(this.sessionId),this.sessionId}touch(){this.lastActivityMs=Date.now(),this.local?.setItem(LAST_ACTIVITY_KEY,String(this.lastActivityMs))}isExpired(){if(this.sessionStartedMs>0&&Date.now()-this.sessionStartedMs>864e5)return!0;let raw=this.local?.getItem(LAST_ACTIVITY_KEY),ts=raw?Number(raw):this.lastActivityMs;return ts===0
|
|
1
|
+
import{v7}from"uuid";const SESSION_ID_KEY=`interfere:session_id`,LAST_ACTIVITY_KEY=`interfere:last_activity`,SESSION_STARTED_KEY=`interfere:session_started`,WINDOW_ID_KEY=`interfere:window_id`;function tryStorage(type){try{let s=globalThis[type],key=`__interfere_probe__`;return s.setItem(key,`1`),s.removeItem(key),s}catch{return null}}var SessionManager=class{sessionId=null;windowId=null;local;session;onRotate=null;lastActivityMs=0;sessionStartedMs=0;constructor(onRotate){this.local=tryStorage(`localStorage`),this.session=tryStorage(`sessionStorage`),this.onRotate=onRotate??null,this.restore()}getSessionId(){return this.sessionId?this.sessionId:this.rotate()}markActivity(){this.touch()}getSessionStartedAt(){return this.sessionStartedMs}getWindowId(){if(this.windowId)return this.windowId;let stored=this.session?.getItem(WINDOW_ID_KEY);return stored?(this.windowId=stored,stored):(this.windowId=`win_${crypto.randomUUID()}`,this.session?.setItem(WINDOW_ID_KEY,this.windowId),this.windowId)}reset(){return this.rotate()}restore(){let stored=this.local?.getItem(SESSION_ID_KEY),startedRaw=this.local?.getItem(SESSION_STARTED_KEY);this.sessionStartedMs=startedRaw?Number(startedRaw):0,stored&&!this.isExpired()?(this.sessionId=stored,this.touch()):this.rotate()}rotate(){return this.sessionId=v7(),this.sessionStartedMs=Date.now(),this.local?.setItem(SESSION_ID_KEY,this.sessionId),this.local?.setItem(SESSION_STARTED_KEY,String(this.sessionStartedMs)),this.touch(),this.onRotate?.(this.sessionId),this.sessionId}touch(){this.lastActivityMs=Date.now(),this.local?.setItem(LAST_ACTIVITY_KEY,String(this.lastActivityMs))}isExpired(){if(this.sessionStartedMs>0&&Date.now()-this.sessionStartedMs>864e5)return!0;let raw=this.local?.getItem(LAST_ACTIVITY_KEY),ts=raw?Number(raw):this.lastActivityMs;return ts===0||Date.now()-ts>9e5}};export{SessionManager};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/react",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Client-side React SDK for Interfere. Error tracking, session replay, and analytics.",
|
|
6
6
|
"keywords": [
|
|
@@ -87,9 +87,9 @@
|
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
89
|
"@fingerprintjs/fingerprintjs": "^5.2.0",
|
|
90
|
-
"@interfere/constants": "^9.0.
|
|
91
|
-
"@interfere/helpers": "^9.0.
|
|
92
|
-
"@interfere/types": "^10.0.
|
|
90
|
+
"@interfere/constants": "^9.0.3",
|
|
91
|
+
"@interfere/helpers": "^9.0.3",
|
|
92
|
+
"@interfere/types": "^10.0.1",
|
|
93
93
|
"@opentelemetry/api": "^1.9.1",
|
|
94
94
|
"@opentelemetry/api-logs": "^0.219.0",
|
|
95
95
|
"@opentelemetry/context-zone": "^2.7.1",
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
"@opentelemetry/sdk-trace-base": "^2.7.0",
|
|
110
110
|
"@opentelemetry/sdk-trace-web": "^2.7.1",
|
|
111
111
|
"@opentelemetry/web-common": "^0.219.0",
|
|
112
|
+
"@rrweb/types": "2.1.0",
|
|
112
113
|
"@ua-parser-js/pro-enterprise": "^2.0.6",
|
|
113
114
|
"rrweb": "2.1.0",
|
|
114
115
|
"uuid": "^14.0.1",
|
|
@@ -128,7 +129,7 @@
|
|
|
128
129
|
}
|
|
129
130
|
},
|
|
130
131
|
"devDependencies": {
|
|
131
|
-
"@interfere/test-utils": "^9.0.
|
|
132
|
+
"@interfere/test-utils": "^9.0.4",
|
|
132
133
|
"@interfere/typescript-config": "^9.0.1",
|
|
133
134
|
"@types/node": "^26.1.0",
|
|
134
135
|
"@types/react": "19.2.17",
|