@interfere/react 11.1.1 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +4 -4
  2. package/dist/activity-BfYxFVcK.d.mts +36 -0
  3. package/dist/api-wpS4xoMY.d.mts +70 -0
  4. package/dist/api.d.mts +8 -7
  5. package/dist/api.mjs +1 -1
  6. package/dist/config-Rm-ct4K1.d.mts +12 -0
  7. package/dist/device-vFtWy12y.d.mts +35 -0
  8. package/dist/error-boundary.d.mts +7 -7
  9. package/dist/error-boundary.mjs +1 -1
  10. package/dist/exporter-logs-CeGwMiMo.d.mts +51 -0
  11. package/dist/geo-PDfIZY4L.d.mts +16 -0
  12. package/dist/index-CatPKbtv.d.mts +4 -0
  13. package/dist/instrumentations-Bgm2EazU.d.mts +91 -0
  14. package/dist/internal/activity.d.mts +1 -35
  15. package/dist/internal/activity.mjs +1 -1
  16. package/dist/internal/browser-context.d.mts +44 -4
  17. package/dist/internal/browser-context.mjs +1 -1
  18. package/dist/internal/capture-boundary.d.mts +6 -5
  19. package/dist/internal/capture-boundary.mjs +1 -1
  20. package/dist/internal/capture.d.mts +3 -4
  21. package/dist/internal/capture.mjs +1 -1
  22. package/dist/internal/config.d.mts +26 -27
  23. package/dist/internal/config.mjs +1 -1
  24. package/dist/internal/consent.d.mts +16 -8
  25. package/dist/internal/console-patch.d.mts +6 -7
  26. package/dist/internal/console-patch.mjs +1 -1
  27. package/dist/internal/dom/actionable.d.mts +5 -7
  28. package/dist/internal/dom/actionable.mjs +1 -1
  29. package/dist/internal/hydration.d.mts +2 -3
  30. package/dist/internal/kernel-registry.d.mts +5 -6
  31. package/dist/internal/kernel.d.mts +2 -292
  32. package/dist/internal/kernel.mjs +1 -1
  33. package/dist/internal/otel/exporter-logs.d.mts +1 -12
  34. package/dist/internal/otel/exporter-logs.mjs +1 -1
  35. package/dist/internal/otel/exporter-metrics.d.mts +2 -14
  36. package/dist/internal/otel/exporter-metrics.mjs +1 -1
  37. package/dist/internal/otel/exporter.d.mts +2 -29
  38. package/dist/internal/otel/exporter.mjs +1 -1
  39. package/dist/internal/otel/http-span-route.d.mts +4 -0
  40. package/dist/internal/otel/http-span-route.mjs +1 -0
  41. package/dist/internal/otel/index.d.mts +7 -5
  42. package/dist/internal/otel/index.mjs +1 -1
  43. package/dist/internal/otel/initial-navigation.d.mts +3 -4
  44. package/dist/internal/otel/initial-navigation.mjs +1 -1
  45. package/dist/internal/otel/instrumentations.d.mts +2 -89
  46. package/dist/internal/otel/instrumentations.mjs +1 -1
  47. package/dist/internal/otel/navigation.d.mts +2 -0
  48. package/dist/internal/otel/navigation.mjs +1 -0
  49. package/dist/internal/otel/normalize-path.d.mts +9 -0
  50. package/dist/internal/otel/normalize-path.mjs +1 -0
  51. package/dist/internal/otel/page-scope-context-manager.d.mts +2 -31
  52. package/dist/internal/otel/page-scope-context-manager.mjs +1 -1
  53. package/dist/internal/otel/propagation.d.mts +1 -19
  54. package/dist/internal/otel/propagation.mjs +1 -1
  55. package/dist/internal/otel/provider.d.mts +1 -86
  56. package/dist/internal/otel/provider.mjs +1 -1
  57. package/dist/internal/otel/url-attrs.d.mts +7 -0
  58. package/dist/internal/otel/url-attrs.mjs +1 -0
  59. package/dist/internal/otel/web-vitals.d.mts +1 -33
  60. package/dist/internal/otel/web-vitals.mjs +1 -1
  61. package/dist/internal/page-lifecycle.d.mts +4 -5
  62. package/dist/internal/page-lifecycle.mjs +1 -1
  63. package/dist/internal/plugin-runtime.d.mts +1 -38
  64. package/dist/internal/plugin-runtime.mjs +1 -1
  65. package/dist/internal/react-context.d.mts +1 -43
  66. package/dist/internal/react-context.mjs +1 -1
  67. package/dist/internal/server-digest.d.mts +4 -3
  68. package/dist/internal/server-digest.mjs +1 -1
  69. package/dist/internal/sw-queue.d.mts +4 -5
  70. package/dist/internal/sw-queue.mjs +1 -1
  71. package/dist/internal/third-party-hosts.d.mts +2 -3
  72. package/dist/internal/third-party-hosts.mjs +1 -1
  73. package/dist/internal/version.d.mts +4 -5
  74. package/dist/internal/version.mjs +1 -1
  75. package/dist/internal/wrapper-singleton.d.mts +5 -6
  76. package/dist/internal/wrapper-singleton.mjs +1 -1
  77. package/dist/navigation-CkiV6lJY.d.mts +54 -0
  78. package/dist/page-scope-context-manager-r92ZMJok.d.mts +17 -0
  79. package/dist/plugins/device.d.mts +5 -0
  80. package/dist/plugins/device.mjs +1 -0
  81. package/dist/plugins/errors.d.mts +1 -1
  82. package/dist/plugins/errors.mjs +1 -1
  83. package/dist/plugins/lib/loader.d.mts +2 -11
  84. package/dist/plugins/lib/loader.mjs +1 -1
  85. package/dist/plugins/lib/types.d.mts +2 -24
  86. package/dist/plugins/logs.d.mts +1 -1
  87. package/dist/plugins/logs.mjs +1 -1
  88. package/dist/plugins/page-events.d.mts +5 -0
  89. package/dist/plugins/page-events.mjs +1 -0
  90. package/dist/plugins/rage-clicks.d.mts +1 -1
  91. package/dist/plugins/rage-clicks.mjs +1 -1
  92. package/dist/plugins/replay/buffer.d.mts +9 -6
  93. package/dist/plugins/replay/buffer.mjs +1 -1
  94. package/dist/plugins/replay/chunking.d.mts +18 -9
  95. package/dist/plugins/replay/chunking.mjs +1 -1
  96. package/dist/plugins/replay/compressor-host.d.mts +3 -4
  97. package/dist/plugins/replay/compressor-host.mjs +1 -1
  98. package/dist/plugins/replay/config.d.mts +1 -11
  99. package/dist/plugins/replay/config.mjs +1 -1
  100. package/dist/plugins/replay/delivery.d.mts +8 -9
  101. package/dist/plugins/replay/delivery.mjs +1 -1
  102. package/dist/plugins/replay/index.d.mts +1 -1
  103. package/dist/plugins/replay/index.mjs +1 -1
  104. package/dist/plugins/replay/recorder.d.mts +12 -6
  105. package/dist/plugins/replay/recorder.mjs +1 -1
  106. package/dist/plugins/replay/sequence.d.mts +5 -4
  107. package/dist/plugins/replay/sequence.mjs +1 -1
  108. package/dist/plugins/replay/upload.d.mts +4 -0
  109. package/dist/plugins/replay/upload.mjs +1 -0
  110. package/dist/propagation-CssinKCy.d.mts +26 -0
  111. package/dist/provider-50LbJ4Tl.d.mts +466 -0
  112. package/dist/provider-Cp6noibq.d.mts +101 -0
  113. package/dist/provider.d.mts +2 -58
  114. package/dist/provider.mjs +1 -1
  115. package/dist/react-error-handler.d.mts +9 -11
  116. package/dist/react-error-handler.mjs +1 -1
  117. package/dist/rrweb-CE6GKCEq.mjs +150 -0
  118. package/dist/tracking/api.d.mts +1 -54
  119. package/dist/tracking/api.mjs +1 -1
  120. package/dist/tracking/device.d.mts +1 -32
  121. package/dist/tracking/device.mjs +1 -1
  122. package/dist/tracking/geo.d.mts +1 -13
  123. package/dist/tracking/geo.mjs +1 -1
  124. package/dist/tracking/session.d.mts +6 -7
  125. package/dist/tracking/session.mjs +1 -1
  126. package/dist/util/bot.d.mts +2 -3
  127. package/dist/util/bot.mjs +1 -1
  128. package/dist/util/global.d.mts +4 -10
  129. package/dist/util/global.mjs +1 -1
  130. package/dist/util/log.d.mts +11 -7
  131. package/dist/util/log.mjs +1 -1
  132. package/dist/util/stringify.d.mts +2 -3
  133. package/dist/version-BniHrwLD.mjs +1 -0
  134. package/dist/web-vitals-x8y70B5x.d.mts +34 -0
  135. package/package.json +67 -48
  136. package/dist/package.mjs +0 -1
@@ -1,55 +1,2 @@
1
- import { SessionResumeReason } from "../internal/activity.mjs";
2
- import { IngestTarget } from "../internal/config.mjs";
3
- import { DeviceManager } from "./device.mjs";
4
- import { GeoDetector } from "./geo.mjs";
5
- import { SessionId } from "@interfere/types/data/session";
6
- import { IdentifyParams } from "@interfere/types/sdk/identify";
7
- //#region src/tracking/api.d.ts
8
- interface SessionTrackerOptions {
9
- device?: DeviceManager;
10
- fetcher?: typeof globalThis.fetch;
11
- geo?: GeoDetector;
12
- target: IngestTarget;
13
- }
14
- declare class SessionTracker {
15
- private readonly target;
16
- private readonly fetcher;
17
- private readonly device;
18
- private readonly geo;
19
- private mgr;
20
- private readonly activity;
21
- private currentIdentity;
22
- private identifiedSessionId;
23
- private syncedSessionId;
24
- private syncAttemptMs;
25
- private generation;
26
- constructor(opts: SessionTrackerOptions);
27
- start(): void;
28
- onSessionPause(handler: () => void): () => void;
29
- onSessionResume(handler: (reason: SessionResumeReason) => void): () => void;
30
- sessionId(): SessionId | null;
31
- windowId(): string | null;
32
- markActivity(): void;
33
- getSessionStartedAt(): number;
34
- getDeviceId(): string | null;
35
- getFpHash(): string | null;
36
- /**
37
- * Identity headers (session / window / device). Layered onto the
38
- * session/identify POSTs alongside the target's static headers
39
- * (content-type + auth + force-enable).
40
- */
41
- headers(): Record<string, string>;
42
- getIdentity(): IdentifyParams | null;
43
- identify(params: IdentifyParams): Promise<void>;
44
- private postIdentify;
45
- clearIdentity(): void;
46
- reset(): void;
47
- rotateSession(): void;
48
- dispose(): void;
49
- private requestHeaders;
50
- private ensureSynced;
51
- private syncSession;
52
- private onRotate;
53
- }
54
- //#endregion
1
+ import { n as SessionTrackerOptions, t as SessionTracker } from "../api-wpS4xoMY.mjs";
55
2
  export { SessionTracker, SessionTrackerOptions };
@@ -1 +1 @@
1
- import{createLogger}from"../util/log.mjs";import{ActivityMonitor}from"../internal/activity.mjs";import{appendPathBeforeQuery}from"../internal/config.mjs";import{DeviceManager}from"./device.mjs";import{GeoDetector}from"./geo.mjs";import{SessionManager}from"./session.mjs";const log=createLogger(`tracking`);var SessionTracker=class{target;fetcher;device;geo;mgr=null;activity=new ActivityMonitor;currentIdentity=null;identifiedSessionId=null;syncedSessionId=null;syncAttemptMs=0;generation=0;constructor(opts){this.target=opts.target,this.fetcher=opts.fetcher??globalThis.fetch.bind(globalThis),this.device=opts.device??new DeviceManager,this.geo=opts.geo??new GeoDetector}start(){this.device.init(),this.geo.detect(),this.mgr=new SessionManager(id=>{this.onRotate(id)}),this.activity.start({markActivity:()=>this.markActivity(),reset:()=>this.rotateSession(),startedAt:()=>this.getSessionStartedAt()})}onSessionPause(handler){return this.activity.onPause(handler)}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()}headers(){let h={},sid=this.mgr?.getSessionId()??null;sid&&(h[`x-interfere-session`]=sid);let wid=this.mgr?.getWindowId()??null;wid&&(h[`x-interfere-window`]=wid);let did=this.device.getDeviceId();return did&&(h[`x-interfere-device`]=did),h}getIdentity(){return this.currentIdentity}async identify(params){if(!this.mgr)return;let sessionId=this.mgr.getSessionId();if(this.identifiedSessionId===sessionId){log.debug(`skipped, already identified for session %s`,sessionId);return}this.currentIdentity=params,this.identifiedSessionId=sessionId;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,{sessionId,deviceId,fpHash,...params,...country&&{country}})}async postIdentify(sessionId,body){try{await this.fetcher(appendPathBeforeQuery(this.target.url,`/identify`),{method:`POST`,headers:this.requestHeaders(),body:JSON.stringify(body),keepalive:!0,credentials:`omit`,signal:AbortSignal.timeout(1e4)})}catch{this.identifiedSessionId=null,log.warn(`identify failed for session %s`,sessionId)}}clearIdentity(){this.currentIdentity=null,this.identifiedSessionId=null}reset(){this.clearIdentity(),this.device.reset(),this.mgr?.reset()}rotateSession(){this.mgr?.reset()}dispose(){this.activity.stop(),this.generation+=1,this.clearIdentity(),this.syncedSessionId=null,this.syncAttemptMs=0,this.mgr=null}requestHeaders(){return{...Object.fromEntries(this.target.headers.entries()),...this.headers()}}ensureSynced(sessionId){this.syncedSessionId!==sessionId&&(Date.now()-this.syncAttemptMs<5e3||this.syncSession(sessionId,this.device.getDeviceId(),this.device.getFpHash()))}async syncSession(sessionId,deviceId,fpHash){this.syncAttemptMs=Date.now(),this.syncedSessionId=sessionId;try{(await this.fetcher(this.target.url,{method:`POST`,headers:this.requestHeaders(),body:JSON.stringify({sessionId,deviceId,fpHash}),keepalive:!0,credentials:`omit`,signal:AbortSignal.timeout(1e4)})).ok||(this.syncedSessionId=null)}catch{this.syncedSessionId=null,log.warn(`session sync failed, will retry`)}}async onRotate(sessionId){this.syncedSessionId=null,this.syncAttemptMs=Date.now();let gen=this.generation;try{let fpHash=await this.device.whenFingerprintReady(),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};
1
+ import{createLogger}from"../util/log.mjs";import{ActivityMonitor}from"../internal/activity.mjs";import{DeviceManager}from"./device.mjs";import{GeoDetector}from"./geo.mjs";import{SessionManager}from"./session.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{InterfereClient}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;lastSyncedKey=null;inflightSyncKey=null;syncAttemptMs=0;generation=0;identityStarted=!1;constructor(opts){this.client=new InterfereClient({...opts.target,maxRetries:0,timeoutInSeconds:10,fetch:Object.assign(async(input,init)=>(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.identityStarted=!0,this.device.init(),this.geo.detect(),this.backfillIdentity())}discardDeviceIdentity(){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);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)}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){log.debug(`skipped, already identified for session %s`,sessionId);return}this.currentIdentity=params,this.identifiedSessionId=sessionId;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}reset(){this.clearIdentity(),this.identityStarted&&this.device.reset(),this.mgr?.reset()}rotateSession(){this.mgr?.reset()}dispose(){this.activity.stop(),this.generation+=1,this.clearIdentity(),this.lastSyncedKey=null,this.inflightSyncKey=null,this.syncAttemptMs=0,this.mgr=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){this.inflightSyncKey=key,this.syncAttemptMs=Date.now();try{await this.client.sessions.createSession({sessionId,deviceId,fpHash}),this.lastSyncedKey=key}catch{log.warn(`session sync failed, will retry`)}finally{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};
@@ -1,33 +1,2 @@
1
- //#region src/tracking/device.d.ts
2
- /**
3
- * Producer of an opaque, stable per-browser fingerprint hash. The default
4
- * dynamic-imports the FingerprintJS OSS library and self-defers via
5
- * `requestIdleCallback` so the ~1.5s of synchronous font / canvas / WebGL
6
- * probing the library performs on a cold load doesn't land on the
7
- * hydration tick. Tests inject a fixed-value provider that resolves
8
- * immediately — they pay nothing for the production deferral.
9
- */
10
- type FingerprintProvider = () => Promise<string | null>;
11
- /**
12
- * Resolves on the next browser idle frame, capped at 5s. Falls back to
13
- * `setTimeout(0)` (next macrotask) on hosts without
14
- * `requestIdleCallback`. Exported only for the unit test that pins the
15
- * "default provider gates fingerprint work via RIC" contract — not part
16
- * of the package's public surface.
17
- */
18
- declare function whenIdle(): Promise<void>;
19
- declare class DeviceManager {
20
- private deviceId;
21
- private fpHash;
22
- private fpPending;
23
- private readonly fingerprintProvider;
24
- constructor(fingerprintProvider?: FingerprintProvider);
25
- init(): void;
26
- private startFingerprint;
27
- getDeviceId(): string | null;
28
- getFpHash(): string | null;
29
- whenFingerprintReady(): Promise<string | null>;
30
- reset(): string;
31
- }
32
- //#endregion
1
+ import { n as FingerprintProvider, r as whenIdle, t as DeviceManager } from "../device-vFtWy12y.mjs";
33
2
  export { DeviceManager, FingerprintProvider, whenIdle };
@@ -1 +1 @@
1
- import{createLogger}from"../util/log.mjs";const log=createLogger(`device`),LS_KEY=`interfere:device_id`,COOKIE_NAME=`interfere_did`;function whenIdle(){let{promise,resolve}=Promise.withResolvers();return typeof globalThis.requestIdleCallback==`function`?globalThis.requestIdleCallback(()=>resolve(void 0),{timeout:5e3}):setTimeout(()=>resolve(void 0),0),promise}const defaultFingerprintProvider=async()=>{await whenIdle();try{let result=await(await(await import(`@fingerprintjs/fingerprintjs`)).load()).get();return result.visitorId?result.visitorId:(log.error(`Fingerprinting returned an empty visitor id; visitor identity will be cookie-only`),null)}catch(error){return log.error(`fingerprint init failed; visitor identity will be cookie-only`,error),null}};function tryLocalStorage(){try{let s=globalThis.localStorage,key=`__interfere_device_probe__`;return s.setItem(key,`1`),s.removeItem(key),s}catch{return null}}function getCookie(name){if(typeof document>`u`)return null;let match=document.cookie.split(`; `).find(c=>c.startsWith(`${name}=`));return match?decodeURIComponent(match.split(`=`)[1]??``):null}function setCookie(name,value){typeof document>`u`||(document.cookie=`${name}=${encodeURIComponent(value)};path=/;max-age=34560000;SameSite=Lax`)}function generateId(){return crypto.randomUUID()}var DeviceManager=class{deviceId=null;fpHash=null;fpPending=null;fingerprintProvider;constructor(fingerprintProvider){this.fingerprintProvider=fingerprintProvider??defaultFingerprintProvider}init(){if(this.deviceId)return;let ls=tryLocalStorage(),fromLs=ls?.getItem(LS_KEY)??null,fromCookie=getCookie(COOKIE_NAME);this.deviceId=fromLs??fromCookie??generateId(),!fromLs&&ls&&ls.setItem(LS_KEY,this.deviceId),fromCookie||setCookie(COOKIE_NAME,this.deviceId),fromLs&&!fromCookie&&setCookie(COOKIE_NAME,this.deviceId),fromCookie&&!fromLs&&ls&&ls.setItem(LS_KEY,this.deviceId),log.debug(`device %s (ls=%s cookie=%s)`,this.deviceId,!!fromLs,!!fromCookie),this.startFingerprint()}startFingerprint(){this.fpHash||this.fpPending||(this.fpPending=(async()=>{let hash=await this.fingerprintProvider();return this.fpHash=hash,hash&&log.debug(`fpHash %s`,hash),hash})())}getDeviceId(){return this.deviceId}getFpHash(){return this.fpHash}whenFingerprintReady(){return this.fpHash?Promise.resolve(this.fpHash):this.fpPending??Promise.resolve(null)}reset(){return this.deviceId=generateId(),tryLocalStorage()?.setItem(LS_KEY,this.deviceId),setCookie(COOKIE_NAME,this.deviceId),log.debug(`device %s (reset)`,this.deviceId),this.deviceId}};export{DeviceManager,whenIdle};
1
+ import{createLogger}from"../util/log.mjs";const log=createLogger(`device`),LS_KEY=`interfere:device_id`,COOKIE_NAME=`interfere_did`;async function whenIdle(){let{promise,resolve}=Promise.withResolvers();return typeof globalThis.requestIdleCallback==`function`?globalThis.requestIdleCallback(()=>{resolve(void 0)},{timeout:5e3}):setTimeout(()=>{resolve(void 0)},0),promise}const defaultFingerprintProvider=async()=>{await whenIdle();try{let result=await(await(await import(`@fingerprintjs/fingerprintjs`)).load()).get();return result.visitorId?result.visitorId:(log.error(`Fingerprinting returned an empty visitor id; visitor identity will be cookie-only`),null)}catch(error){return log.error(`fingerprint init failed; visitor identity will be cookie-only`,error),null}};function tryLocalStorage(){try{let s=globalThis.localStorage,key=`__interfere_device_probe__`;return s.setItem(key,`1`),s.removeItem(key),s}catch{return null}}function getCookie(name){if(typeof document>`u`)return null;let match=document.cookie.split(`; `).find(c=>c.startsWith(`${name}=`));return match?decodeURIComponent(match.split(`=`)[1]??``):null}function setCookie(name,value,maxAgeSeconds){typeof document>`u`||(document.cookie=`${name}=${encodeURIComponent(value)};path=/;max-age=${maxAgeSeconds};SameSite=Lax`)}function persistCookie(name,value){setCookie(name,value,3456e4)}function deleteCookie(name){setCookie(name,``,0)}function generateId(){return crypto.randomUUID()}var DeviceManager=class{deviceId=null;fpHash=null;fpPending=null;epoch=0;fingerprintProvider;constructor(fingerprintProvider){this.fingerprintProvider=fingerprintProvider??defaultFingerprintProvider}init(){if(this.deviceId)return;let ls=tryLocalStorage(),fromLs=ls?.getItem(LS_KEY)??null,fromCookie=getCookie(COOKIE_NAME);this.deviceId=fromLs??fromCookie??generateId(),!fromLs&&ls&&ls.setItem(LS_KEY,this.deviceId),fromCookie||persistCookie(COOKIE_NAME,this.deviceId),fromLs&&!fromCookie&&persistCookie(COOKIE_NAME,this.deviceId),fromCookie&&!fromLs&&ls&&ls.setItem(LS_KEY,this.deviceId),log.debug(`device %s (ls=%s cookie=%s)`,this.deviceId,!!fromLs,!!fromCookie),this.startFingerprint()}startFingerprint(){if(this.fpHash||this.fpPending)return;let{epoch}=this;this.fpPending=(async()=>{let hash=await this.fingerprintProvider();return epoch===this.epoch?(this.fpHash=hash,hash&&log.debug(`fpHash %s`,hash),hash):null})()}getDeviceId(){return this.deviceId}getFpHash(){return this.fpHash}async whenFingerprintReady(){return this.fpHash?this.fpHash:this.fpPending??Promise.resolve(null)}reset(){return this.deviceId=generateId(),tryLocalStorage()?.setItem(LS_KEY,this.deviceId),persistCookie(COOKIE_NAME,this.deviceId),log.debug(`device %s (reset)`,this.deviceId),this.deviceId}clear(){this.epoch+=1,this.deviceId=null,this.fpHash=null,this.fpPending=null,tryLocalStorage()?.removeItem(LS_KEY),deleteCookie(COOKIE_NAME),log.debug(`device identity cleared`)}};export{DeviceManager,whenIdle};
@@ -1,14 +1,2 @@
1
- //#region src/tracking/geo.d.ts
2
- declare class GeoDetector {
3
- private cached;
4
- private pending;
5
- private failed;
6
- private readonly fetcher;
7
- constructor(fetcher?: typeof globalThis.fetch);
8
- detect(): Promise<string | null>;
9
- private resolveCountryCode;
10
- getCountry(): string | null;
11
- private fetchCountryCode;
12
- }
13
- //#endregion
1
+ import { t as GeoDetector } from "../geo-PDfIZY4L.mjs";
14
2
  export { GeoDetector };
@@ -1,2 +1,2 @@
1
1
  import{cloudflareTraceSchema}from"@interfere/types/sdk/geo";function parseTrace(text){let result={};for(let line of text.split(`
2
- `)){let idx=line.indexOf(`=`);idx>0&&(result[line.slice(0,idx)]=line.slice(idx+1))}return result}var GeoDetector=class{cached=null;pending=null;failed=!1;fetcher;constructor(fetcher){this.fetcher=fetcher??globalThis.fetch.bind(globalThis)}detect(){return this.cached?Promise.resolve(this.cached):this.failed?Promise.resolve(null):(this.pending||=this.resolveCountryCode(),this.pending)}async resolveCountryCode(){let code=await this.fetchCountryCode();return this.cached=code,code||(this.failed=!0),this.pending=null,code}getCountry(){return this.cached}async fetchCountryCode(){try{let res=await this.fetcher(`https://cloudflare.com/cdn-cgi/trace`,{signal:AbortSignal.timeout(3e3)});if(!res.ok)return null;let raw=parseTrace(await res.text()),trace=cloudflareTraceSchema.safeParse(raw);return trace.success?trace.data.loc.toUpperCase():null}catch{return null}}};export{GeoDetector};
2
+ `)){let idx=line.indexOf(`=`);idx>0&&(result[line.slice(0,idx)]=line.slice(idx+1))}return result}var GeoDetector=class{cached=null;pending=null;failed=!1;epoch=0;fetcher;constructor(fetcher){this.fetcher=fetcher??globalThis.fetch.bind(globalThis)}async detect(){return this.cached?this.cached:this.failed?null:(this.pending??=this.resolveCountryCode(),this.pending)}async resolveCountryCode(){let{epoch}=this,code=await this.fetchCountryCode();return epoch===this.epoch?(this.cached=code,code||(this.failed=!0),this.pending=null,code):null}getCountry(){return this.cached}clear(){this.epoch+=1,this.cached=null,this.failed=!1,this.pending=null}async fetchCountryCode(){try{let res=await this.fetcher(`https://cloudflare.com/cdn-cgi/trace`,{signal:AbortSignal.timeout(3e3)});if(!res.ok)return null;let raw=parseTrace(await res.text()),trace=cloudflareTraceSchema.safeParse(raw);return trace.success?trace.data.loc.toUpperCase():null}catch{return null}}};export{GeoDetector};
@@ -1,8 +1,8 @@
1
1
  import { SessionId } from "@interfere/types/data/session";
2
2
  //#region src/tracking/session.d.ts
3
- type OnRotate = (sessionId: string) => void;
4
- declare class SessionManager {
5
- sessionId: string | null;
3
+ export type OnRotate = (sessionId: string) => void;
4
+ export declare class SessionManager {
5
+ sessionId: SessionId | null;
6
6
  windowId: string | null;
7
7
  private readonly local;
8
8
  private readonly session;
@@ -10,15 +10,14 @@ declare class SessionManager {
10
10
  private lastActivityMs;
11
11
  private sessionStartedMs;
12
12
  constructor(onRotate?: OnRotate);
13
- getSessionId(): SessionId;
13
+ getSessionId(): string & import("zod").$brand<"SessionId">;
14
14
  markActivity(): void;
15
15
  getSessionStartedAt(): number;
16
16
  getWindowId(): string;
17
- reset(): SessionId;
17
+ reset(): string & import("zod").$brand<"SessionId">;
18
18
  private restore;
19
19
  private rotate;
20
20
  private touch;
21
21
  private isExpired;
22
22
  }
23
- //#endregion
24
- export { OnRotate, SessionManager };
23
+ //#endregion
@@ -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||Date.now()-ts>9e5}};export{SessionManager};
1
+ import{sessionIdSchema}from"@interfere/types/data/session";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),parsed=sessionIdSchema.safeParse(stored);this.sessionStartedMs=startedRaw?Number(startedRaw):0,parsed.success&&!this.isExpired()?(this.sessionId=parsed.data,this.touch()):this.rotate()}rotate(){return this.sessionId=sessionIdSchema.parse(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};
@@ -5,6 +5,5 @@
5
5
  * don't need separate checks. Returns `false` outside the browser (no UA
6
6
  * to inspect).
7
7
  */
8
- declare function isBotUserAgent(): boolean;
9
- //#endregion
10
- export { isBotUserAgent };
8
+ export declare function isBotUserAgent(): boolean;
9
+ //#endregion
package/dist/util/bot.mjs CHANGED
@@ -1 +1 @@
1
- import{isBot}from"@ua-parser-js/pro-enterprise/bot-detection";function isBotUserAgent(){return typeof navigator>`u`?!1:isBot(navigator.userAgent)}export{isBotUserAgent};
1
+ import{isBot}from"@ua-parser-js/pro-enterprise/bot-detection";const AUTOMATION_UA_RE=/headless|electron|puppeteer|playwright/iu;function isBotUserAgent(){return typeof navigator>`u`?!1:navigator.webdriver||AUTOMATION_UA_RE.test(navigator.userAgent)?!0:isBot(navigator.userAgent)}export{isBotUserAgent};
@@ -1,11 +1,5 @@
1
1
  //#region src/util/global.d.ts
2
- /**
3
- * Typed read of a build-time-injected global. The Vite plugin and
4
- * `withInterfere()` stamp values like `__INTERFERE_RELEASE_SLUG__` onto
5
- * `globalThis`; this is the single read site so the unsafe cast lives in
6
- * one place.
7
- */
8
- declare function getGlobal<T>(key: string): T | undefined;
9
- declare function setGlobal(key: string, value: unknown): void;
10
- //#endregion
11
- export { getGlobal, setGlobal };
2
+ export declare function getGlobal(key: string): unknown;
3
+ export declare function getStringGlobal(key: string): string | undefined;
4
+ export declare function setGlobal(key: string, value: unknown): void;
5
+ //#endregion
@@ -1 +1 @@
1
- function getGlobal(key){return globalThis[key]}function setGlobal(key,value){globalThis[key]=value}export{getGlobal,setGlobal};
1
+ function getGlobal(key){return Reflect.get(globalThis,key)}function getStringGlobal(key){let value=getGlobal(key);return typeof value==`string`?value:void 0}function setGlobal(key,value){Reflect.set(globalThis,key,value)}export{getGlobal,getStringGlobal,setGlobal};
@@ -1,13 +1,17 @@
1
1
  //#region src/util/log.d.ts
2
- type LogLevel = "debug" | "info" | "warn" | "error" | "none";
3
- declare function setLogLevel(level: LogLevel): void;
4
- declare function getLogLevel(): LogLevel;
5
- interface Logger {
2
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "none";
3
+ export declare function setLogLevel(level: LogLevel): void;
4
+ export declare function getLogLevel(): LogLevel;
5
+ export interface Logger {
6
6
  debug: (...args: unknown[]) => void;
7
7
  error: (...args: unknown[]) => void;
8
8
  info: (...args: unknown[]) => void;
9
9
  warn: (...args: unknown[]) => void;
10
10
  }
11
- declare function createLogger(scope: string): Logger;
12
- //#endregion
13
- export { LogLevel, Logger, createLogger, getLogLevel, setLogLevel };
11
+ export declare function createLogger(scope: string): {
12
+ debug: (...args: unknown[]) => void;
13
+ error: (...args: unknown[]) => void;
14
+ info: (...args: unknown[]) => void;
15
+ warn: (...args: unknown[]) => void;
16
+ };
17
+ //#endregion
package/dist/util/log.mjs CHANGED
@@ -1 +1 @@
1
- const PRIORITY={debug:0,info:1,warn:2,error:3,none:4},CONSOLE_FN={debug:`debug`,info:`info`,warn:`warn`,error:`error`};let threshold=PRIORITY.warn;function setLogLevel(level){threshold=PRIORITY[level]}function getLogLevel(){return Object.entries(PRIORITY).find(([,v])=>v===threshold)?.[0]??`warn`}function emit(level,prefix,args){if(PRIORITY[level]<threshold)return;let fn=CONSOLE_FN[level];globalThis.console[fn](prefix,...args)}function createLogger(scope){let prefix=`[Interfere:${scope}]`;return{debug:(...args)=>emit(`debug`,prefix,args),info:(...args)=>emit(`info`,prefix,args),warn:(...args)=>emit(`warn`,prefix,args),error:(...args)=>emit(`error`,prefix,args)}}export{createLogger,getLogLevel,setLogLevel};
1
+ const PRIORITY={debug:0,error:3,info:1,none:4,warn:2},CONSOLE_FN={debug:`debug`,error:`error`,info:`info`,warn:`warn`};let currentLevel=`warn`;function setLogLevel(level){currentLevel=level}function getLogLevel(){return currentLevel}function emit(level,prefix,args){if(PRIORITY[level]<PRIORITY[currentLevel])return;let fn=CONSOLE_FN[level];globalThis.console[fn](prefix,...args)}function createLogger(scope){let prefix=`[Interfere:${scope}]`;return{debug:(...args)=>{emit(`debug`,prefix,args)},error:(...args)=>{emit(`error`,prefix,args)},info:(...args)=>{emit(`info`,prefix,args)},warn:(...args)=>{emit(`warn`,prefix,args)}}}export{createLogger,getLogLevel,setLogLevel};
@@ -4,6 +4,5 @@
4
4
  * non-serialisable values (BigInt, …). Strings pass through unchanged so
5
5
  * single-arg log calls don't get re-quoted.
6
6
  */
7
- declare function safeStringify(value: unknown): string;
8
- //#endregion
9
- export { safeStringify };
7
+ export declare function safeStringify(value: unknown): string;
8
+ //#endregion
@@ -0,0 +1 @@
1
+ var name=`@interfere/react`,version=`12.0.0`;const SDK_NAME=name,SDK_VERSION=version,PRODUCER_VERSION=`${SDK_NAME}@${SDK_VERSION}`;export{SDK_NAME as n,SDK_VERSION as r,PRODUCER_VERSION as t};
@@ -0,0 +1,34 @@
1
+ import { Meter } from "@opentelemetry/api";
2
+ //#region src/internal/otel/web-vitals.d.ts
3
+ interface WebVitalsInput {
4
+ /**
5
+ * Called after the page-load vitals have all fired. The kernel passes
6
+ * its own `flush()` so short-visit exports don't depend on the
7
+ * `visibilitychange` listener firing.
8
+ */
9
+ flush: () => Promise<void>;
10
+ /** OTel meter from the kernel's private provider. */
11
+ meter: Meter;
12
+ /**
13
+ * Pathname → low-cardinality route template (e.g. `/blog/[slug]`).
14
+ * Without this, dynamic routes produce one unique `url.path` label
15
+ * per visited slug — a metric cardinality hazard.
16
+ */
17
+ resolveRoute?: (pathname: string) => string | undefined;
18
+ }
19
+ /**
20
+ * Subscribes to Core Web Vitals (LCP/FCP/TTFB/INP/CLS) and records OTel
21
+ * histograms. Time-based vitals are converted to seconds per
22
+ * observability convention; CLS is dimensionless and recorded as-is.
23
+ *
24
+ * Each record carries `web_vital.rating`, `web_vital.navigation_type`,
25
+ * and `url.path` (templated when `resolveRoute` is provided). Browser
26
+ * and device dimensions come from the resource attached to the
27
+ * MeterProvider, so every histogram datapoint already carries them.
28
+ *
29
+ * Bucket boundaries match the rum.ts SDK — same dashboards, same
30
+ * histograms, same percentile shape.
31
+ */
32
+ declare function captureWebVitals(input: WebVitalsInput): void;
33
+ //#endregion
34
+ export { captureWebVitals as n, WebVitalsInput as t };
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@interfere/react",
3
- "version": "11.1.1",
4
- "license": "MIT",
3
+ "version": "12.0.0",
5
4
  "description": "Client-side React SDK for Interfere. Error tracking, session replay, and analytics.",
6
5
  "keywords": [
6
+ "error-tracking",
7
7
  "observability",
8
- "typescript",
9
8
  "react",
10
- "error-tracking",
11
- "session-replay"
9
+ "session-replay",
10
+ "typescript"
12
11
  ],
13
12
  "homepage": "https://interfere.com",
14
13
  "bugs": {
15
14
  "url": "mailto:support@interfere.com"
16
15
  },
16
+ "license": "MIT",
17
17
  "author": "Interfere <support@interfere.com> (https://interfere.com)",
18
18
  "repository": {
19
19
  "type": "git",
@@ -24,6 +24,7 @@
24
24
  "dist"
25
25
  ],
26
26
  "type": "module",
27
+ "sideEffects": false,
27
28
  "exports": {
28
29
  "./provider": {
29
30
  "monorepo": "./src/provider.tsx",
@@ -70,54 +71,85 @@
70
71
  "types": "./dist/internal/sw-queue.d.mts",
71
72
  "default": "./dist/internal/sw-queue.mjs"
72
73
  },
74
+ "./util/global": {
75
+ "monorepo": "./src/util/global.ts",
76
+ "types": "./dist/util/global.d.mts",
77
+ "default": "./dist/util/global.mjs"
78
+ },
73
79
  "./util/log": {
74
80
  "monorepo": "./src/util/log.ts",
75
81
  "types": "./dist/util/log.d.mts",
76
82
  "default": "./dist/util/log.mjs"
77
83
  }
78
84
  },
79
- "sideEffects": false,
80
85
  "publishConfig": {
81
86
  "access": "public"
82
87
  },
83
88
  "scripts": {
84
89
  "build": "tsdown",
85
90
  "test": "vitest run",
91
+ "test:artifact": "bun run build && node --test test/recorder-artifact.test.mts",
86
92
  "typecheck": "tsc --noEmit"
87
93
  },
88
94
  "dependencies": {
89
95
  "@fingerprintjs/fingerprintjs": "^5.2.0",
90
- "@interfere/constants": "^9.0.5",
91
- "@interfere/helpers": "^9.1.1",
92
- "@interfere/types": "^10.1.1",
96
+ "@interfere/constants": "^9.1.0",
97
+ "@interfere/helpers": "^9.2.0",
98
+ "@interfere/javascript": "^0.2.0",
99
+ "@interfere/types": "^10.2.0",
93
100
  "@opentelemetry/api": "^1.9.1",
94
- "@opentelemetry/api-logs": "^0.221.0",
95
- "@opentelemetry/context-zone": "^2.7.1",
96
- "@opentelemetry/core": "^2.7.0",
97
- "@opentelemetry/instrumentation": "^0.221.0",
98
- "@opentelemetry/instrumentation-browser-navigation": "^0.14.0",
99
- "@opentelemetry/instrumentation-document-load": "^0.66.0",
100
- "@opentelemetry/instrumentation-fetch": "^0.221.0",
101
- "@opentelemetry/instrumentation-long-task": "^0.65.0",
102
- "@opentelemetry/instrumentation-user-interaction": "^0.65.0",
103
- "@opentelemetry/instrumentation-xml-http-request": "^0.221.0",
104
- "@opentelemetry/opentelemetry-browser-detector": "^0.221.0",
105
- "@opentelemetry/otlp-transformer": "^0.221.0",
106
- "@opentelemetry/resources": "^2.7.0",
107
- "@opentelemetry/sdk-logs": "^0.221.0",
108
- "@opentelemetry/sdk-metrics": "^2.7.0",
109
- "@opentelemetry/sdk-trace-base": "^2.7.0",
110
- "@opentelemetry/sdk-trace-web": "^2.7.1",
111
- "@opentelemetry/web-common": "^0.221.0",
101
+ "@opentelemetry/api-logs": "^0.222.0",
102
+ "@opentelemetry/context-zone": "^2.11.0",
103
+ "@opentelemetry/core": "^2.11.0",
104
+ "@opentelemetry/instrumentation": "^0.222.0",
105
+ "@opentelemetry/instrumentation-browser-navigation": "^0.15.0",
106
+ "@opentelemetry/instrumentation-document-load": "^0.67.0",
107
+ "@opentelemetry/instrumentation-fetch": "^0.222.0",
108
+ "@opentelemetry/instrumentation-long-task": "^0.66.0",
109
+ "@opentelemetry/instrumentation-user-interaction": "^0.66.0",
110
+ "@opentelemetry/instrumentation-xml-http-request": "^0.222.0",
111
+ "@opentelemetry/opentelemetry-browser-detector": "^0.222.0",
112
+ "@opentelemetry/otlp-transformer": "^0.222.0",
113
+ "@opentelemetry/resources": "^2.11.0",
114
+ "@opentelemetry/sdk-logs": "^0.222.0",
115
+ "@opentelemetry/sdk-metrics": "^2.11.0",
116
+ "@opentelemetry/sdk-trace-base": "^2.11.0",
117
+ "@opentelemetry/sdk-trace-web": "^2.11.0",
118
+ "@opentelemetry/web-common": "^0.222.0",
112
119
  "@rrweb/types": "2.1.1",
113
120
  "@ua-parser-js/pro-enterprise": "^2.0.6",
114
121
  "rrweb": "2.1.1",
115
- "uuid": "^14.0.1",
116
- "web-vitals": "^6.1.0",
117
- "workbox-background-sync": "^7.4.0"
122
+ "uuid": "^14.0.2",
123
+ "web-vitals": "^6.2.1",
124
+ "workbox-background-sync": "^7.4.0",
125
+ "zod": "^4.5.4"
126
+ },
127
+ "devDependencies": {
128
+ "@babel/core": "^7.29.7",
129
+ "@interfere/typescript-config": "^9.0.2",
130
+ "@interfere/vitest-config": "0.0.0",
131
+ "@rolldown/plugin-babel": "^0.2.3",
132
+ "@types/babel__core": "^7.20.5",
133
+ "@types/node": "^26.4.1",
134
+ "@types/react": "19.2.18",
135
+ "@types/react-dom": "19.2.7",
136
+ "@vitejs/plugin-react": "^6.1.1",
137
+ "@vitest/browser": "5.0.1",
138
+ "@vitest/browser-playwright": "5.0.1",
139
+ "@vitest/coverage-v8": "5.0.1",
140
+ "babel-plugin-react-compiler": "1.0.0",
141
+ "fflate": "^0.8.3",
142
+ "msw": "^2.14.6",
143
+ "playwright": "^1.63.0",
144
+ "react": "19.3.0",
145
+ "react-dom": "19.3.0",
146
+ "tsdown": "^0.23.0",
147
+ "typescript": "^7.0.2",
148
+ "vitest": "5.0.1",
149
+ "vitest-browser-react": "2.3.0"
118
150
  },
119
151
  "peerDependencies": {
120
- "react": "^19.2.6",
152
+ "react": "^19.0.0",
121
153
  "react-dom": "^19.0.0"
122
154
  },
123
155
  "peerDependenciesMeta": {
@@ -128,22 +160,9 @@
128
160
  "optional": true
129
161
  }
130
162
  },
131
- "devDependencies": {
132
- "@interfere/test-utils": "^9.1.1",
133
- "@interfere/typescript-config": "^9.0.2",
134
- "@types/node": "^26.2.0",
135
- "@types/react": "19.2.18",
136
- "@types/react-dom": "19.2.4",
137
- "@vitest/browser": "4.1.10",
138
- "@vitest/browser-playwright": "4.1.10",
139
- "@vitest/coverage-v8": "4.1.10",
140
- "fflate": "^0.8.3",
141
- "playwright": "^1.62.1",
142
- "react": "^19.2.6",
143
- "react-dom": "19.2.8",
144
- "tsdown": "^0.22.2",
145
- "typescript": "^7.0.2",
146
- "vitest": "4.1.10",
147
- "vitest-browser-react": "2.2.0"
163
+ "msw": {
164
+ "workerDirectory": [
165
+ "test/public"
166
+ ]
148
167
  }
149
168
  }
package/dist/package.mjs DELETED
@@ -1 +0,0 @@
1
- var name=`@interfere/react`,version=`11.1.1`;export{name,version};