@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
@@ -0,0 +1,466 @@
1
+ import { c as SessionResumeReason } from "./activity-BfYxFVcK.mjs";
2
+ import { a as ReplayOption, i as ReplayConfig } from "./config-Rm-ct4K1.mjs";
3
+ import { t as SessionTracker } from "./api-wpS4xoMY.mjs";
4
+ import { n as CaptureFailedRequestsOption, t as BundledInstrumentations } from "./instrumentations-Bgm2EazU.mjs";
5
+ import { t as OtelProviderHandle } from "./provider-Cp6noibq.mjs";
6
+ import "./index-CatPKbtv.mjs";
7
+ import { NonErrorException } from "@interfere/types/sdk/errors";
8
+ import { Tracer } from "@opentelemetry/api";
9
+ import { PropsWithChildren } from "react";
10
+ import { ConsentState, PluginKey } from "@interfere/types/sdk/plugins/manifest";
11
+ import { RemotePluginConfig } from "@interfere/types/sdk/remote-config";
12
+ import { SessionId } from "@interfere/types/data/session";
13
+ import { MetricReader } from "@opentelemetry/sdk-metrics";
14
+ import { LogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
15
+ import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
16
+ import { IngestedFrame } from "@interfere/types/data/frame";
17
+ import { IdentifyParams } from "@interfere/types/sdk/identify";
18
+ import { ErrorMechanism } from "@interfere/types/sdk/plugins/payload/errors";
19
+ //#region src/plugins/lib/types.d.ts
20
+ type PluginTeardownReason = "consent-revoked" | "disabled" | "dispose";
21
+ type PluginCleanup = (reason?: PluginTeardownReason) => void;
22
+ type PluginConfigState = "disabled" | "enabled" | "pending";
23
+ interface PluginContext {
24
+ getPluginConfigState: (key: PluginKey) => PluginConfigState;
25
+ getReplayConfig: () => ReplayConfig;
26
+ getSessionId: () => string;
27
+ getTracer: (name: string) => Tracer;
28
+ getWindowId: () => string;
29
+ onSessionPause: (handler: () => void) => () => void;
30
+ onSessionResume: (handler: (reason: SessionResumeReason) => void) => () => void;
31
+ recordException: (value: Error | NonErrorException, opts: RecordExceptionOpts) => void;
32
+ startDeviceInfoCapture: () => PluginCleanup | null;
33
+ startPageEventsCapture: () => PluginCleanup | null;
34
+ subscribePluginConfigState: (key: PluginKey, listener: (state: PluginConfigState) => void) => () => void;
35
+ }
36
+ interface Plugin {
37
+ readonly name: string;
38
+ setup: (ctx: PluginContext) => PluginCleanup | undefined;
39
+ }
40
+ //#endregion
41
+ //#region src/plugins/lib/loader.d.ts
42
+ type PluginLoader = () => Promise<{
43
+ default: Plugin;
44
+ } | Plugin> | Plugin;
45
+ declare const LOADERS: Record<PluginKey, PluginLoader>;
46
+ type PluginOverrides = Partial<Record<Exclude<PluginKey, "replay">, boolean>> & {
47
+ replay?: ReplayOption;
48
+ };
49
+ declare function resolveFeatures(overrides?: PluginOverrides): {
50
+ device: boolean;
51
+ errors: boolean;
52
+ logs: boolean;
53
+ pageEvents: boolean;
54
+ rageClick: boolean;
55
+ replay: boolean;
56
+ };
57
+ declare function loadPlugin(key: PluginKey, context: PluginContext): Promise<PluginCleanup | null>;
58
+ //#endregion
59
+ //#region src/internal/plugin-runtime.d.ts
60
+ declare class PluginRuntime {
61
+ private readonly activeCleanups;
62
+ private readonly pending;
63
+ private features;
64
+ private readonly pluginConfigListeners;
65
+ private remoteConfig;
66
+ private remoteConfigSettled;
67
+ private consentState;
68
+ private configSettled;
69
+ private replayConfig;
70
+ private syncVersion;
71
+ private disposed;
72
+ private readonly context;
73
+ private readonly hasInitialConsent;
74
+ constructor(context: PluginContext, consent?: ConsentState, remoteConfig?: RemotePluginConfig);
75
+ getConsent(): ConsentState | null;
76
+ getReplayConfig(): ReplayConfig;
77
+ applyProviderConfig(overrides: PluginOverrides | undefined, consent: ConsentState | undefined): void;
78
+ setConsent(nextConsent?: ConsentState): void;
79
+ resetConsent(): void;
80
+ applyRemoteConfig(config: RemotePluginConfig): void;
81
+ applyRemoteConfigDefaults(): void;
82
+ start(): void;
83
+ dispose(): Promise<void>;
84
+ private shouldEnablePlugin;
85
+ getPluginConfigState(key: PluginKey): "disabled" | "enabled" | "pending";
86
+ subscribePluginConfigState(key: PluginKey, listener: (state: PluginConfigState) => void): () => void;
87
+ private emitPluginConfigState;
88
+ private teardownReason;
89
+ private deactivate;
90
+ private activate;
91
+ private sync;
92
+ }
93
+ //#endregion
94
+ //#region src/internal/kernel.d.ts
95
+ declare function buildSdkStack(wrapperVersions?: string[]): string[];
96
+ interface KernelOptions {
97
+ /** Saved consent applied before device identity and tracing start. */
98
+ consent?: ConsentState | undefined;
99
+ /**
100
+ * The endpoint the SDK posts telemetry to. Defaults to Interfere's
101
+ * endpoint. Set it to a subdomain of your own site that resolves to
102
+ * Interfere via a DNS record (e.g. `"https://in.example.com"`) to
103
+ * survive ad-blockers, or to a regional endpoint. Must be a full URL.
104
+ */
105
+ apiHost?: string;
106
+ /**
107
+ * Override the automatic dev-mode guard. When `undefined`, the SDK
108
+ * auto-detects: it disables itself if `process.env["NODE_ENV"]` is not
109
+ * `"production"` (Node / webpack / Next.js). In environments where
110
+ * `process` does not exist (Vite, CRA, plain browser) the SDK
111
+ * defaults to **enabled** — pass `false` to disable explicitly.
112
+ */
113
+ enabled?: boolean;
114
+ /** Override `globalThis.fetch` for tests / non-browser hosts. */
115
+ fetch?: typeof globalThis.fetch;
116
+ /**
117
+ * Override the OTel `service.name` resource attribute. Defaults to
118
+ * `"interfere-sdk"`. Customers running multiple frontends in one
119
+ * monitoring backend (e.g. `"@interfere/website"` vs
120
+ * `"@interfere/app"`) set this so spans/metrics/logs slice
121
+ * cleanly by surface.
122
+ */
123
+ serviceName?: string;
124
+ /**
125
+ * `false` skips the OTel module entirely — the bundler code-splits
126
+ * `internal/otel/*` out of this path so the error-only bundle never
127
+ * imports the OTel SDK. `true` (default) loads it with default
128
+ * instrumentation config. An object loads it with the supplied
129
+ * config.
130
+ */
131
+ tracing?: boolean | TracingOptions;
132
+ }
133
+ /**
134
+ * Per-instrumentation tuning. Every field is optional; defaults match
135
+ * what `interfere/homepage` and `interfere/dashboard` use today via
136
+ * the internal `observability/browser/rum.ts`. New customers don't
137
+ * need to touch any of these — sensible defaults ship out of the box.
138
+ */
139
+ interface TracingOptions {
140
+ /**
141
+ * Hostnames where your backend runs, e.g. `["api.example.com"]`. Every
142
+ * request to a listed host carries the W3C `traceparent` header so the
143
+ * browser trace continues on the server. Same-origin requests always
144
+ * propagate — you only need this when your API is on a different host
145
+ * than your app. Matched by hostname (any path, port, or scheme); no regex.
146
+ */
147
+ apiHosts?: string[];
148
+ /**
149
+ * Promote failed `fetch` / `XHR` responses to exception events on the
150
+ * active span. **On by default** — captures same-origin (and
151
+ * `propagateContextUrls`) 4xx + 5xx, deduped by `method+status+path` and
152
+ * rate-limited so a flapping endpoint can't flood. Pass `false` to
153
+ * disable, or `{ statusCodes }` to tune the ranges.
154
+ * See {@link CaptureFailedRequestsOption}.
155
+ */
156
+ captureFailedRequests?: CaptureFailedRequestsOption;
157
+ /**
158
+ * Additional URL patterns to skip when creating fetch / XHR spans.
159
+ * The SDK's own collector endpoint is always ignored; customer-side
160
+ * third-party SDKs (Clerk, Sentry, GTM, etc.) are also skipped by
161
+ * default — supplement with anything specific to your app.
162
+ */
163
+ ignoreUrls?: (string | RegExp)[];
164
+ /**
165
+ * @deprecated Prefer {@link apiHosts} — it takes plain hostnames and
166
+ * needs no regex. Still fully supported: raw URL patterns injected with
167
+ * `traceparent` + `baggage` on outgoing fetch / XHR. Note string entries
168
+ * match the full request URL by exact equality (an OpenTelemetry quirk),
169
+ * so cross-origin values usually have to be a `RegExp`.
170
+ */
171
+ propagateContextUrls?: (string | RegExp)[];
172
+ /**
173
+ * Resolve a URL pathname to a low-cardinality route template
174
+ * (e.g. `/blog/[slug]`). Without this, dynamic routes produce one
175
+ * unique span / metric label per visited slug — a cardinality
176
+ * hazard. Used by fetch, document-load resource enrichment,
177
+ * user-interaction, long-task, and web-vitals.
178
+ */
179
+ resolveRoute?: (pathname: string) => string | undefined;
180
+ /**
181
+ * `false` disables Core Web Vitals capture (LCP/FCP/TTFB/INP/CLS).
182
+ * Defaults to enabled; customers who run their own vitals reporting
183
+ * can opt out.
184
+ */
185
+ webVitals?: boolean;
186
+ }
187
+ /**
188
+ * Framework wrappers (`@interfere/next`, `@interfere/vite`) pass extra
189
+ * fields through `createKernel` that customers never set themselves.
190
+ * Kept off the customer-facing `KernelOptions` to make the public surface
191
+ * clean.
192
+ *
193
+ * @internal
194
+ */
195
+ interface KernelInternalOptions extends KernelOptions {
196
+ /** @internal */
197
+ _internalAdditionalLogRecordProcessors?: LogRecordProcessor[];
198
+ /** @internal */
199
+ _internalAdditionalMetricReaders?: MetricReader[];
200
+ /** @internal */
201
+ _internalAdditionalSpanProcessors?: SpanProcessor[];
202
+ /** Wrapper SDK versions (e.g. `@interfere/next@10.0.0`). */
203
+ _wrapperVersions?: string[];
204
+ }
205
+ interface KernelConsent {
206
+ get: () => ConsentState | null;
207
+ set: (value?: ConsentState) => void;
208
+ }
209
+ interface KernelIdentity {
210
+ clear: () => void;
211
+ get: () => IdentifyParams | null;
212
+ set: (params: IdentifyParams) => Promise<void>;
213
+ }
214
+ interface KernelDevice {
215
+ getDeviceId: () => string | null;
216
+ getFpHash: () => string | null;
217
+ }
218
+ interface KernelSession {
219
+ getId: () => SessionId | null;
220
+ getWindowId: () => string | null;
221
+ }
222
+ interface RecordExceptionOpts {
223
+ /**
224
+ * Frames always appended to the first exception's stack. Used by
225
+ * `<ErrorBoundary>` to inject React's component-stack frames as
226
+ * supplementary context — these add on top of the real JS frames, they
227
+ * don't replace them.
228
+ */
229
+ readonly appendFrames?: readonly IngestedFrame[];
230
+ /**
231
+ * `error.digest` from React when an RSC server-side throw is
232
+ * sanitised and rebuilt as a synthetic Error on the client. The only
233
+ * identifier that pairs the redacted client capture with the
234
+ * unredacted server capture — enrichment mixes this into the
235
+ * fingerprint so both events group as one problem.
236
+ */
237
+ readonly errorDigest?: string;
238
+ /**
239
+ * Frames adopted only when the first exception's parsed stack is empty.
240
+ * Used by the `window.onerror` handler when the browser hands us
241
+ * source/line/col but the `Error` itself has a degenerate stack — never
242
+ * glued on top of a real stack.
243
+ */
244
+ readonly fallbackFrames?: readonly IngestedFrame[];
245
+ readonly mechanism: ErrorMechanism;
246
+ /**
247
+ * A distinct error sub-classification layered on top of the mechanism —
248
+ * currently `"hydration"` for React hydration mismatches. Lets Interfere
249
+ * triage by kind without re-parsing the message.
250
+ */
251
+ readonly subtype?: string;
252
+ }
253
+ /**
254
+ * The replacement for the old `Client` god-object. Pure construction graph
255
+ * via `createKernel`; no module-level mutable state, no global lookups.
256
+ * Framework wrappers (`@interfere/next`, `@interfere/vite`) own the
257
+ * singleton lifecycle.
258
+ *
259
+ * Implements `PluginContext` directly: plugins are wired with the kernel
260
+ * itself rather than a closure adapter. The kernel⇄runtime cycle is
261
+ * resolved by constructing the kernel first and binding the runtime via
262
+ * `attachRuntime` immediately after.
263
+ */
264
+ declare class Kernel implements PluginContext {
265
+ readonly consent: KernelConsent;
266
+ readonly identity: KernelIdentity;
267
+ readonly device: KernelDevice;
268
+ readonly session: KernelSession;
269
+ private readonly seen;
270
+ private readonly initialNavigationSeen;
271
+ private runtime;
272
+ private otel;
273
+ private otelDispose;
274
+ private otelControls;
275
+ private deviceInfoCaptureEnabled;
276
+ private unsubscribePageHidden;
277
+ private readonly tracker;
278
+ constructor(tracker: SessionTracker);
279
+ /**
280
+ * Bound by `createKernel` immediately after construction.
281
+ *
282
+ * @internal
283
+ */
284
+ attachRuntime(runtime: PluginRuntime): void;
285
+ private requireRuntime;
286
+ /** PluginContext shim: plugins expect a non-null string. */
287
+ getSessionId(): "" | (string & import("zod").$brand<"SessionId">);
288
+ getWindowId(): string;
289
+ onSessionPause(handler: () => void): () => void;
290
+ onSessionResume(handler: (reason: SessionResumeReason) => void): () => void;
291
+ getPluginConfigState(key: PluginKey): "disabled" | "enabled" | "pending";
292
+ getReplayConfig(): ReplayConfig;
293
+ subscribePluginConfigState(key: PluginKey, listener: (state: PluginConfigState) => void): () => void;
294
+ getTracer(name: string): import("@opentelemetry/api").Tracer;
295
+ startPageEventsCapture(): (() => void) | null;
296
+ startDeviceInfoCapture(): (reason: PluginTeardownReason | undefined) => void;
297
+ isDeviceInfoCaptureEnabled(): boolean;
298
+ /**
299
+ * Records an exception event on the active OTel span. No envelope
300
+ * path — the SDK is OTel-only. Single dedup boundary: drops repeats
301
+ * of the same `Error` instance, plus browser-extension noise and
302
+ * unresolvable stacks. Upstream callers (the errors plugin's
303
+ * `window.onerror` / `console.error` / `unhandledrejection`, the
304
+ * React error boundary) just call this — they don't pre-filter.
305
+ *
306
+ * Does NOT mark the active span as failed. A console.error inside a
307
+ * customer-owned `span()` block would otherwise taint the customer's
308
+ * span even when the customer caught the error explicitly. The
309
+ * customer's `span()` helper sets status itself when it observes a
310
+ * throw.
311
+ *
312
+ * `appendFrames` are always appended (component-stack supplements);
313
+ * `fallbackFrames` are only adopted when the parsed stack is empty
314
+ * (`window.onerror` source/line/col when the Error has no usable
315
+ * stack). Both ride on the serialised `interfere.exception.chain`
316
+ * attribute when the chain is non-trivial.
317
+ */
318
+ recordException(value: Error | NonErrorException, opts: RecordExceptionOpts): void;
319
+ /**
320
+ * Emits an OTel `LogRecord` via the kernel's logger provider. Used by
321
+ * `plugins/logs.ts` to capture string-only `console.*` calls (the
322
+ * errors plugin still owns Error-bearing console calls — class
323
+ * boundary). No-ops when OTel is not wired (`tracing: false`) since
324
+ * there's no logger provider to emit through.
325
+ */
326
+ recordLog(input: {
327
+ severityText: string;
328
+ severityNumber: number;
329
+ body: string;
330
+ attributes?: Record<string, string>;
331
+ }): void;
332
+ recordInitialNavigation(loggerProvider: LoggerProvider): void;
333
+ /**
334
+ * Force-flushes the OTel exporters. Returns once they've settled
335
+ * (success or failure) so callers driving unload — page-lifecycle
336
+ * handlers, integration test teardown — can actually await
337
+ * completion. The OTel SDK swallows export errors internally; we
338
+ * surface the resolution either way.
339
+ */
340
+ flush(): Promise<void>;
341
+ /**
342
+ * Wired by `createKernel` after the OTel module has been
343
+ * lazy-loaded. Held on the kernel so `flush()` and `dispose()` can fan
344
+ * out to the providers. The tracer/meter providers stay private —
345
+ * customers don't get raw OTel access; the public surface is the
346
+ * `span()` / `capture()` helpers in `api.ts`.
347
+ *
348
+ * @internal
349
+ */
350
+ attachOtel(handle: OtelProviderHandle, dispose: () => void, controls?: Pick<BundledInstrumentations, "setPageEventsEnabled">): void;
351
+ syncProviderConfig(config: {
352
+ consent?: ConsentState | undefined;
353
+ plugins?: PluginOverrides | undefined;
354
+ }): void;
355
+ dispose(): Promise<void>;
356
+ }
357
+ interface CreateKernelInput {
358
+ opts?: KernelInternalOptions;
359
+ }
360
+ declare function createKernel(input?: CreateKernelInput): Promise<Kernel>;
361
+ declare function isEnabledByEnvironment(): boolean;
362
+ /**
363
+ * Build-time-derived release slug. The build step
364
+ * (`@interfere/next/withInterfere`, `@interfere/vite/plugin`) takes the
365
+ * leading 16 hex chars of the commit SHA (`rel_<16hex>`) and stamps it into
366
+ * the bundle as `__INTERFERE_RELEASE_SLUG__`. The collector derives the same
367
+ * value from the create-release request, so the bundle's runtime slug is
368
+ * guaranteed to match the row without a round-trip.
369
+ *
370
+ * Returns `null` when no slug was injected (dev builds, customers who
371
+ * haven't wired up the plugin).
372
+ */
373
+ declare function readReleaseSlugFromGlobals(): (`rel_${string}` & import("zod").$brand<"ReleaseSlug">) | null;
374
+ //#endregion
375
+ //#region src/internal/react-context.d.ts
376
+ interface InterfereContextValue {
377
+ consent: {
378
+ get: () => ConsentState | null;
379
+ set: (state?: ConsentState) => void;
380
+ };
381
+ device: {
382
+ getDeviceId: () => string | null;
383
+ getFpHash: () => string | null;
384
+ };
385
+ identity: {
386
+ clear: () => void;
387
+ get: () => IdentifyParams | null;
388
+ set: (params: IdentifyParams) => Promise<void>;
389
+ };
390
+ /**
391
+ * The active kernel, or `null` when the SDK isn't initialized yet — for
392
+ * example during server-side prerender, when `init()` is client-only.
393
+ * Accessor objects (consent/device/identity/session) above stay safe to
394
+ * call in either state; they no-op when the kernel is null.
395
+ */
396
+ kernel: Kernel | null;
397
+ session: {
398
+ getId: () => string | null;
399
+ getWindowId: () => string | null;
400
+ };
401
+ }
402
+ /**
403
+ * Context value used when the provider is mounted without a kernel — every
404
+ * accessor returns `null` and mutations are no-ops. Lets `useInterfere()`
405
+ * work seamlessly across SSR/CSR boundaries (server gets nulls, client
406
+ * gets real values once the kernel resolves).
407
+ */
408
+ declare const NULL_CONTEXT_VALUE: InterfereContextValue;
409
+ /**
410
+ * Lives in its own module so `provider.tsx` and `internal/capture-boundary.tsx`
411
+ * can both import it without forming an import cycle.
412
+ */
413
+ declare const InterfereContext: import("react").Context<InterfereContextValue | null>;
414
+ //#endregion
415
+ //#region src/provider.d.ts
416
+ interface InterfereProviderProps extends PropsWithChildren {
417
+ /**
418
+ * Consent state gating which plugin categories may run. Omit (or pass
419
+ * `undefined`) to preserve consent supplied to `init()`. Without initial
420
+ * consent, omitting this prop leaves every category allowed.
421
+ */
422
+ consent?: ConsentState | undefined;
423
+ /**
424
+ * Auto-install an internal capture boundary around `children` so
425
+ * render-phase React errors are reported even when the host app has no
426
+ * `ErrorBoundary` / `error.tsx` of its own.
427
+ *
428
+ * The internal boundary is transparent: it captures the error and then
429
+ * re-throws so upstream boundaries (the customer's own, Next.js's
430
+ * `error.tsx` / `global-error.tsx`, or React's default unmount) keep full
431
+ * control of what the user sees. Safe to leave enabled.
432
+ *
433
+ * Pass `false` only if you explicitly don't want automatic capture of
434
+ * render-phase errors — for example, if you've already wired
435
+ * {@link reactErrorHandler} into `createRoot()`.
436
+ *
437
+ * @default true
438
+ */
439
+ errorBoundary?: boolean;
440
+ /**
441
+ * The active kernel from `init()`. Pass `null` (or omit on the server)
442
+ * when the SDK isn't initialized — useful during SSR/SSG where `init()`
443
+ * runs client-side only. The provider mounts with null-safe accessors
444
+ * and switches to the real kernel once it's available.
445
+ */
446
+ kernel: Kernel | null;
447
+ /**
448
+ * Per-plugin overrides, merged over the manifest defaults. Generic plugins
449
+ * are booleans (e.g. `{ pageEvents: false }`). `replay` additionally accepts
450
+ * a config object — `{ replay: { maskAllInputs: true } }` enables replay
451
+ * with that masking config; `{ replay: false }` disables it. Privacy classes
452
+ * are always applied, regardless of config: `interfere-block` elements are
453
+ * dropped and replay as a same-size placeholder, `interfere-mask` masks the
454
+ * text of an element and all its children, and `interfere-ignore` stops an
455
+ * element's input events from being recorded. `input[type="password"]` is
456
+ * masked by default; use `maskInputOptions`/`maskAllInputs` to mask other
457
+ * input values. `init()` no longer accepts plugin config; this is the only
458
+ * place it lives.
459
+ */
460
+ plugins?: PluginOverrides | undefined;
461
+ }
462
+ declare function InterfereProvider({ kernel, children, consent, plugins, errorBoundary }: InterfereProviderProps): import("react").JSX.Element;
463
+ declare function useInterfere(): InterfereContextValue;
464
+ declare function useSession(): string | null;
465
+ //#endregion
466
+ export { loadPlugin as C, PluginConfigState as D, PluginCleanup as E, PluginContext as O, PluginOverrides as S, Plugin as T, createKernel as _, InterfereContextValue as a, PluginRuntime as b, KernelConsent as c, KernelInternalOptions as d, KernelOptions as f, buildSdkStack as g, TracingOptions as h, InterfereContext as i, PluginTeardownReason as k, KernelDevice as l, RecordExceptionOpts as m, useInterfere as n, NULL_CONTEXT_VALUE as o, KernelSession as p, useSession as r, Kernel as s, InterfereProvider as t, KernelIdentity as u, isEnabledByEnvironment as v, resolveFeatures as w, LOADERS as x, readReleaseSlugFromGlobals as y };
@@ -0,0 +1,101 @@
1
+ import { t as PageScopeContextManager } from "./page-scope-context-manager-r92ZMJok.mjs";
2
+ import { InterfereClient } from "@interfere/javascript";
3
+ import { ReleaseSlug } from "@interfere/types/releases/slug";
4
+ import { SessionId } from "@interfere/types/data/session";
5
+ import { MeterProvider, MetricReader, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
6
+ import { LogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
7
+ import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
8
+ import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
9
+ //#region src/internal/otel/provider.d.ts
10
+ interface OtelProviderInput {
11
+ /** @internal */
12
+ additionalLogRecordProcessors?: LogRecordProcessor[];
13
+ /** @internal */
14
+ additionalMetricReaders?: MetricReader[];
15
+ /** @internal */
16
+ additionalSpanProcessors?: SpanProcessor[];
17
+ /**
18
+ * Auth + content headers for OTLP exports. Sourced from the kernel's
19
+ * already-resolved ingest target so the OTLP path inherits the same
20
+ * transport metadata the rest of the SDK uses — no separate auth knob.
21
+ */
22
+ clientOptions: InterfereClient.Options;
23
+ /**
24
+ * Returns the current `DeviceManager` device id. Wired into per-span
25
+ * and per-log processors so a mid-page device rotation
26
+ * (`identity.clear()` after logout) lands on subsequent spans / logs
27
+ * without the kernel rebuilding the providers. Returns `null` before
28
+ * the device manager has bootstrapped, or in SSR / test boot paths.
29
+ *
30
+ * Not applied to metrics: the MeterProvider takes a static resource
31
+ * and rebuilding it mid-page would destroy the periodic reader; metrics
32
+ * remain stamped with the boot-time device id.
33
+ */
34
+ getDeviceId: () => string | null;
35
+ /**
36
+ * Returns the kernel's current session id. Wired into per-span /
37
+ * per-log session processors so a mid-page session rotation (30-min
38
+ * idle expiry, manual reset) lands on subsequent spans without the
39
+ * kernel having to rebuild the providers. Returns `null` before the
40
+ * `SessionTracker` has bootstrapped.
41
+ */
42
+ getSessionId: () => SessionId | null;
43
+ /**
44
+ * Consent gate for the browser-detector attributes (`browser.*`,
45
+ * `user_agent.original`), read per span / log / metric export so a
46
+ * mid-page consent change needs no provider rebuild. Defaults to deny;
47
+ * the kernel wires it to the `device` plugin's activation state.
48
+ */
49
+ isDeviceInfoEnabled?: () => boolean;
50
+ /** Optional release slug — top-level `release.slug` attr (Phase 6 wire identity). */
51
+ releaseSlug?: ReleaseSlug | null | undefined;
52
+ /**
53
+ * Producer chain for the `interfere.sdk.stack` resource attribute —
54
+ * e.g. `["@interfere/next@10.0.0", "@interfere/react@10.0.0"]`.
55
+ * Wrapper-injected; the kernel just forwards.
56
+ */
57
+ sdkStack: string[];
58
+ /**
59
+ * Override the OTel `service.name` resource attribute. Defaults to
60
+ * `"interfere-sdk"`.
61
+ */
62
+ serviceName?: string;
63
+ }
64
+ interface OtelProviderHandle {
65
+ /**
66
+ * Page-scope context manager. The kernel calls `setPageScope(ctx)` after
67
+ * extracting the SSR `traceparent` meta tag so spans without a more
68
+ * specific zone descend from the server-side parent.
69
+ */
70
+ contextManager: PageScopeContextManager;
71
+ /** Force-flush all three providers — call from kernel.flush() / on visibility hidden. */
72
+ flush: () => Promise<void>;
73
+ loggerProvider: LoggerProvider;
74
+ meterProvider: MeterProvider;
75
+ metricReader: MetricReader;
76
+ /** Tear down all three providers — called from kernel.dispose(). */
77
+ shutdown: () => Promise<void>;
78
+ tracerProvider: WebTracerProvider;
79
+ }
80
+ /**
81
+ * Constructs the SDK's private OTel providers. `WebTracerProvider` is never
82
+ * installed globally — it's passed to `registerInstrumentations(...)`
83
+ * explicitly. `ContextManager` and `TextMapPropagator` are process-wide
84
+ * singletons; we install ours only when nothing else has claimed them
85
+ * (`setGlobal*` returns `false` on duplicate). If we lose that race, the
86
+ * SSR-embedded pageload parent isn't honored — everything else works.
87
+ *
88
+ * Kept out of `Kernel` so the error-only bundle path never imports the
89
+ * OTel SDK.
90
+ */
91
+ declare function buildOtelProvider(input: OtelProviderInput): {
92
+ contextManager: PageScopeContextManager;
93
+ flush: () => Promise<void>;
94
+ loggerProvider: LoggerProvider;
95
+ meterProvider: MeterProvider;
96
+ metricReader: PeriodicExportingMetricReader;
97
+ shutdown: () => Promise<void>;
98
+ tracerProvider: WebTracerProvider;
99
+ };
100
+ //#endregion
101
+ export { OtelProviderInput as n, buildOtelProvider as r, OtelProviderHandle as t };
@@ -1,59 +1,3 @@
1
- import { ReplayConfig, ReplayOption } from "./plugins/replay/config.mjs";
2
- import { PluginOverrides } from "./plugins/lib/loader.mjs";
3
- import { Kernel } from "./internal/kernel.mjs";
4
- import { InterfereContext, InterfereContextValue } from "./internal/react-context.mjs";
5
- import { PropsWithChildren, ReactNode } from "react";
6
- import { ConsentState } from "@interfere/types/sdk/plugins/manifest";
7
- //#region src/provider.d.ts
8
- interface InterfereProviderProps extends PropsWithChildren {
9
- /**
10
- * Consent state gating which plugin categories may run. Omit (or pass
11
- * `undefined`) to leave consent unmanaged — every category is allowed.
12
- * This is the only place consent is configured; `init()` no longer
13
- * accepts it.
14
- */
15
- consent?: ConsentState | undefined;
16
- /**
17
- * Auto-install an internal capture boundary around `children` so
18
- * render-phase React errors are reported even when the host app has no
19
- * `ErrorBoundary` / `error.tsx` of its own.
20
- *
21
- * The internal boundary is transparent: it captures the error and then
22
- * re-throws so upstream boundaries (the customer's own, Next.js's
23
- * `error.tsx` / `global-error.tsx`, or React's default unmount) keep full
24
- * control of what the user sees. Safe to leave enabled.
25
- *
26
- * Pass `false` only if you explicitly don't want automatic capture of
27
- * render-phase errors — for example, if you've already wired
28
- * {@link reactErrorHandler} into `createRoot()`.
29
- *
30
- * @default true
31
- */
32
- errorBoundary?: boolean;
33
- /**
34
- * The active kernel from `init()`. Pass `null` (or omit on the server)
35
- * when the SDK isn't initialized — useful during SSR/SSG where `init()`
36
- * runs client-side only. The provider mounts with null-safe accessors
37
- * and switches to the real kernel once it's available.
38
- */
39
- kernel: Kernel | null;
40
- /**
41
- * Per-plugin overrides, merged over the manifest defaults. Generic plugins
42
- * are booleans (e.g. `{ pageEvents: false }`). `replay` additionally accepts
43
- * a config object — `{ replay: { maskAllInputs: true } }` enables replay
44
- * with that masking config; `{ replay: false }` disables it. Privacy classes
45
- * are always applied, regardless of config: `interfere-block` elements are
46
- * dropped and replay as a same-size placeholder, `interfere-mask` masks the
47
- * text of an element and all its children, and `interfere-ignore` stops an
48
- * element's input events from being recorded. `input[type="password"]` is
49
- * masked by default; use `maskInputOptions`/`maskAllInputs` to mask other
50
- * input values. `init()` no longer accepts plugin config; this is the only
51
- * place it lives.
52
- */
53
- plugins?: PluginOverrides | undefined;
54
- }
55
- declare function InterfereProvider({ kernel, children, consent, plugins, errorBoundary }: InterfereProviderProps): ReactNode;
56
- declare function useInterfere(): InterfereContextValue;
57
- declare function useSession(): string | null;
58
- //#endregion
1
+ import { a as ReplayOption, i as ReplayConfig } from "./config-Rm-ct4K1.mjs";
2
+ import { S as PluginOverrides, a as InterfereContextValue, i as InterfereContext, n as useInterfere, r as useSession, t as InterfereProvider } from "./provider-50LbJ4Tl.mjs";
59
3
  export { InterfereContext, type InterfereContextValue, InterfereProvider, type PluginOverrides, type ReplayConfig, type ReplayOption, useInterfere, useSession };
package/dist/provider.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{InterfereContext,NULL_CONTEXT_VALUE}from"./internal/react-context.mjs";import{CaptureBoundary}from"./internal/capture-boundary.mjs";import{useContext,useEffect}from"react";import{jsx}from"react/jsx-runtime";function InterfereProvider({kernel,children,consent,plugins,errorBoundary=!0}){useEffect(()=>{kernel?.syncProviderConfig({consent,plugins})},[kernel,consent,plugins]);let value=kernel?{consent:kernel.consent,device:kernel.device,identity:kernel.identity,kernel,session:kernel.session}:NULL_CONTEXT_VALUE;return jsx(InterfereContext,{value,children:errorBoundary?jsx(CaptureBoundary,{children}):children})}function useInterfere(){let ctx=useContext(InterfereContext);if(!ctx)throw Error(`useInterfere must be used within <InterfereProvider>`);return ctx}function useSession(){return useInterfere().session.getId()}export{InterfereContext,InterfereProvider,useInterfere,useSession};
1
+ "use client";import{InterfereContext,NULL_CONTEXT_VALUE}from"./internal/react-context.mjs";import{CaptureBoundary}from"./internal/capture-boundary.mjs";import{useContext,useLayoutEffect}from"react";import{c}from"react/compiler-runtime";import{jsx}from"react/jsx-runtime";function InterfereProvider(t0){let $=c(13),{kernel,children,consent,plugins,errorBoundary:t1}=t0,errorBoundary=t1===void 0||t1,t2,t3;$[0]!==consent||$[1]!==kernel||$[2]!==plugins?(t2=()=>{kernel?.syncProviderConfig({consent,plugins})},t3=[kernel,consent,plugins],$[0]=consent,$[1]=kernel,$[2]=plugins,$[3]=t2,$[4]=t3):(t2=$[3],t3=$[4]),useLayoutEffect(t2,t3);let t4;$[5]===kernel?t4=$[6]:(t4=kernel?{consent:kernel.consent,device:kernel.device,identity:kernel.identity,kernel,session:kernel.session}:NULL_CONTEXT_VALUE,$[5]=kernel,$[6]=t4);let value=t4,t5;$[7]!==children||$[8]!==errorBoundary?(t5=errorBoundary?jsx(CaptureBoundary,{children}):children,$[7]=children,$[8]=errorBoundary,$[9]=t5):t5=$[9];let body=t5,t6;return $[10]!==body||$[11]!==value?(t6=jsx(InterfereContext,{value,children:body}),$[10]=body,$[11]=value,$[12]=t6):t6=$[12],t6}function useInterfere(){let ctx=useContext(InterfereContext);if(!ctx)throw Error(`useInterfere must be used within <InterfereProvider>`);return ctx}function useSession(){"use no memo";return useInterfere().session.getId()}export{InterfereContext,InterfereProvider,useInterfere,useSession};