@interfere/react 8.1.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/internal/client.d.mts +4 -1
- package/dist/internal/client.d.mts.map +1 -1
- package/dist/internal/client.mjs +8 -2
- package/dist/internal/client.mjs.map +1 -1
- package/dist/internal/envelope.d.mts +1 -0
- package/dist/internal/envelope.d.mts.map +1 -1
- package/dist/internal/envelope.mjs +3 -1
- package/dist/internal/envelope.mjs.map +1 -1
- package/dist/package.mjs +1 -1
- package/dist/transport/http.d.mts.map +1 -1
- package/dist/transport/http.mjs +6 -2
- package/dist/transport/http.mjs.map +1 -1
- package/package.json +16 -11
package/README.md
CHANGED
|
@@ -4,7 +4,10 @@ import { ConsentState } from "@interfere/types/sdk/plugins/manifest";
|
|
|
4
4
|
import { EnvelopePayload, EventType } from "@interfere/types/sdk/envelope";
|
|
5
5
|
|
|
6
6
|
//#region src/internal/client.d.ts
|
|
7
|
+
declare function buildSdkStack(wrapperVersions?: string[]): string[];
|
|
7
8
|
interface ClientOptions {
|
|
9
|
+
/** @internal Wrapper SDK versions (e.g. `@interfere/next@8.1.0`). */
|
|
10
|
+
_wrapperVersions?: string[];
|
|
8
11
|
batch?: Omit<Partial<QueueOptions>, "transport">;
|
|
9
12
|
consent?: ConsentState;
|
|
10
13
|
/**
|
|
@@ -42,4 +45,4 @@ declare function flush(): void;
|
|
|
42
45
|
/** @internal Test-only. Resets the module state so init() can be called again. */
|
|
43
46
|
declare function _reset(): void;
|
|
44
47
|
//#endregion
|
|
45
|
-
export { ClientOptions, _reset, close, consent, flush, getClient, init, syncConsent };
|
|
48
|
+
export { ClientOptions, _reset, buildSdkStack, close, consent, flush, getClient, init, syncConsent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.mts","names":[],"sources":["../../src/internal/client.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"client.d.mts","names":[],"sources":["../../src/internal/client.ts"],"mappings":";;;;;;iBAmBgB,aAAA,CAAc,eAAA;AAAA,UAIb,aAAA;EAJD;EAMd,gBAAA;EACA,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,YAAA;EACrB,OAAA,GAAU,YAAA;EAR4C;AAIxD;;;;;;EAYE,OAAA;EACA,OAAA,GAAU,eAAA;AAAA;AAAA,cAGN,MAAA;EAAA,iBACa,QAAA;EAAA,iBACA,KAAA;EAAA,iBACA,OAAA;cAEL,IAAA,EAAM,aAAA,EAAe,OAAA,UAAiB,SAAA;EAAA,QAuC1C,iBAAA;EA0BR,OAAA,WAAkB,SAAA,CAAA,CAAW,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,eAAA,CAAgB,CAAA;EAS/D,KAAA,CAAA;EAIM,OAAA,CAAA,GAAW,OAAA;EAMjB,UAAA,CAAA,GAAc,YAAA;EAId,UAAA,CAAW,KAAA,GAAQ,YAAA;EAInB,YAAA,CAAA;AAAA;AAAA,iBAOc,SAAA,CAAA,GAAa,MAAA;AAAA,iBA6Bb,IAAA,CAAK,IAAA,GAAM,aAAA;AAAA,iBAoCL,KAAA,CAAA,GAAS,OAAA;AAAA,cASlB,OAAA;SACJ,YAAA;cAIK,YAAA;AAAA;AAAA,iBAKE,WAAA,CAAY,YAAA,EAAc,YAAA;AAAA,iBAa1B,KAAA,CAAA;;iBAKA,MAAA,CAAA"}
|
package/dist/internal/client.mjs
CHANGED
|
@@ -4,12 +4,16 @@ import { bootstrap, session, teardown } from "../tracking/api.mjs";
|
|
|
4
4
|
import { BatchQueue } from "../transport/queue.mjs";
|
|
5
5
|
import { resolveTargets } from "./config.mjs";
|
|
6
6
|
import { collectContext } from "./context.mjs";
|
|
7
|
+
import { PRODUCER_VERSION } from "./version.mjs";
|
|
7
8
|
import { buildEnvelope } from "./envelope.mjs";
|
|
8
9
|
import { PluginRuntime } from "./plugin-runtime.mjs";
|
|
9
10
|
import { registerServiceWorker } from "./sw.mjs";
|
|
10
11
|
import { inferRuntime, normalizeEnv } from "@interfere/types/sdk/runtime";
|
|
11
12
|
//#region src/internal/client.ts
|
|
12
13
|
const log = createLogger("client");
|
|
14
|
+
function buildSdkStack(wrapperVersions) {
|
|
15
|
+
return [...wrapperVersions ?? [], PRODUCER_VERSION];
|
|
16
|
+
}
|
|
13
17
|
var Client = class {
|
|
14
18
|
metadata;
|
|
15
19
|
queue;
|
|
@@ -23,7 +27,8 @@ var Client = class {
|
|
|
23
27
|
environment: normalizeEnv(typeof process === "undefined" ? void 0 : process.env["NODE_ENV"]),
|
|
24
28
|
runtime: inferRuntime(),
|
|
25
29
|
buildId,
|
|
26
|
-
releaseId
|
|
30
|
+
releaseId,
|
|
31
|
+
...opts._wrapperVersions ? { wrapperVersions: opts._wrapperVersions } : {}
|
|
27
32
|
};
|
|
28
33
|
registerServiceWorker();
|
|
29
34
|
this.queue = new BatchQueue({
|
|
@@ -106,6 +111,7 @@ function init(opts = {}) {
|
|
|
106
111
|
return;
|
|
107
112
|
}
|
|
108
113
|
instance = new Client(opts, buildId, releaseId ?? null);
|
|
114
|
+
if (typeof window !== "undefined") window["__INTERFERE_SDK_STACK__"] = buildSdkStack(opts._wrapperVersions);
|
|
109
115
|
}
|
|
110
116
|
async function close() {
|
|
111
117
|
if (!instance) return;
|
|
@@ -136,4 +142,4 @@ function _reset() {
|
|
|
136
142
|
instance = null;
|
|
137
143
|
}
|
|
138
144
|
//#endregion
|
|
139
|
-
export { _reset, close, consent, flush, getClient, init, syncConsent };
|
|
145
|
+
export { _reset, buildSdkStack, close, consent, flush, getClient, init, syncConsent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../../src/internal/client.ts"],"sourcesContent":["import type { EnvelopePayload, EventType } from \"@interfere/types/sdk/envelope\";\nimport type { ConsentState } from \"@interfere/types/sdk/plugins/manifest\";\nimport type { RemoteConfig } from \"@interfere/types/sdk/remote-config\";\nimport { inferRuntime, normalizeEnv } from \"@interfere/types/sdk/runtime\";\n\nimport type { PluginOverrides } from \"../plugins/lib/loader.js\";\nimport { bootstrap, session, teardown } from \"../tracking/api.js\";\nimport { buildHeaders, HttpTransport } from \"../transport/http.js\";\nimport { BatchQueue, type QueueOptions } from \"../transport/queue.js\";\nimport { createLogger } from \"../util/log.js\";\nimport { resolveTargets } from \"./config.js\";\nimport { collectContext } from \"./context.js\";\nimport { buildEnvelope, type EnvelopeMetadata } from \"./envelope.js\";\nimport { PluginRuntime } from \"./plugin-runtime.js\";\nimport { registerServiceWorker } from \"./sw.js\";\n\nconst log = createLogger(\"client\");\n\nexport interface ClientOptions {\n batch?: Omit<Partial<QueueOptions>, \"transport\">;\n consent?: ConsentState;\n /**\n * Override the automatic dev-mode guard. When `undefined`, the SDK\n * auto-detects: it disables itself if `process.env[\"NODE_ENV\"]` is not\n * `\"production\"` (Node / webpack / Next.js). In environments where\n * `process` does not exist (Vite, CRA, plain browser) the SDK\n * defaults to **enabled** — pass `false` to disable explicitly.\n */\n enabled?: boolean;\n plugins?: PluginOverrides;\n}\n\nclass Client {\n private readonly metadata: EnvelopeMetadata;\n private readonly queue: BatchQueue;\n private readonly runtime: PluginRuntime;\n\n constructor(opts: ClientOptions, buildId: string, releaseId: string | null) {\n const targets = resolveTargets();\n bootstrap(targets.session);\n\n log.info(\"target: %s\", targets.ingest.url);\n\n this.metadata = {\n context: collectContext(),\n environment: normalizeEnv(\n typeof process === \"undefined\" ? undefined : process.env[\"NODE_ENV\"]\n ),\n runtime: inferRuntime(),\n buildId,\n releaseId,\n };\n\n registerServiceWorker();\n\n const transport = new HttpTransport(targets.ingest);\n this.queue = new BatchQueue({ transport, ...opts.batch });\n this.queue.start();\n\n this.runtime = new PluginRuntime(\n {\n capture: (type, payload) => this.capture(type, payload),\n getSessionId: () => session.getId() ?? \"\",\n },\n opts.plugins,\n opts.consent\n );\n\n this.runtime.start();\n\n this.fetchRemoteConfig(targets.config);\n }\n\n private fetchRemoteConfig(configTarget: {\n url: string;\n headers: Headers;\n }): void {\n fetch(configTarget.url, {\n method: \"GET\",\n headers: buildHeaders(configTarget.headers),\n signal: AbortSignal.timeout(10_000),\n })\n .then((res) => {\n if (!res.ok) {\n return;\n }\n return res.json() as Promise<RemoteConfig>;\n })\n .then((config) => {\n if (config?.plugins) {\n this.runtime.applyRemoteConfig(config.plugins);\n log.debug(\"applied remote config\");\n }\n })\n .catch(() => {\n log.warn(\"remote config fetch failed, using local defaults\");\n });\n }\n\n capture<T extends EventType>(type: T, payload: EnvelopePayload<T>): void {\n const sessionId = session.getId();\n if (!(sessionId && this.runtime.canCapture(type))) {\n return;\n }\n\n this.queue.enqueue(buildEnvelope(type, payload, sessionId, this.metadata));\n }\n\n flush(): void {\n this.queue.flush();\n }\n\n async dispose(): Promise<void> {\n await this.runtime.dispose();\n teardown();\n this.queue.dispose();\n }\n\n getConsent(): ConsentState | null {\n return this.runtime.getConsent();\n }\n\n setConsent(value?: ConsentState): void {\n this.runtime.setConsent(value);\n }\n\n resetConsent(): void {\n this.runtime.resetConsent();\n }\n}\n\nlet instance: Client | null = null;\n\nexport function getClient(): Client {\n if (!instance) {\n throw new Error(\n \"Interfere SDK not initialized. Call init() from your instrumentation-client entrypoint.\"\n );\n }\n return instance;\n}\n\nfunction isEnabledByEnvironment(): boolean {\n try {\n if (typeof process === \"undefined\" || !process.env) {\n return true;\n }\n if (process.env[\"NODE_ENV\"] === \"production\") {\n return true;\n }\n if (process.env[\"NODE_ENV\"] === undefined) {\n return true;\n }\n return !!(\n (globalThis as Record<string, unknown>)[\"__INTERFERE_FORCE_ENABLE__\"] ||\n process.env[\"INTERFERE_FORCE_ENABLE\"]\n );\n } catch {\n return true;\n }\n}\n\nexport function init(opts: ClientOptions = {}): void {\n if (instance) {\n return;\n }\n\n if (!(opts.enabled ?? isEnabledByEnvironment())) {\n log.info(\n \"Disabled in non-production. Pass enabled: true to init() or set INTERFERE_FORCE_ENABLE=1.\"\n );\n return;\n }\n\n const buildId = (globalThis as Record<string, unknown>)[\n \"__INTERFERE_BUILD_ID__\"\n ] as string | undefined;\n\n const releaseId = (globalThis as Record<string, unknown>)[\n \"__INTERFERE_RELEASE_ID__\"\n ] as string | null | undefined;\n\n if (!buildId) {\n log.error(\n \"buildId not found — ensure withInterfere() is configured in \" +\n \"next.config and instrumentation-client.ts exists in your project root.\"\n );\n return;\n }\n\n instance = new Client(opts, buildId, releaseId ?? null);\n}\n\nexport async function close(): Promise<void> {\n if (!instance) {\n return;\n }\n\n await instance.dispose();\n instance = null;\n}\n\nexport const consent = {\n get(): ConsentState | null {\n return instance?.getConsent() ?? null;\n },\n\n set(value?: ConsentState): void {\n instance?.setConsent(value);\n },\n};\n\nexport function syncConsent(consentState: ConsentState | undefined): void {\n if (!instance) {\n return;\n }\n\n if (consentState) {\n instance.setConsent(consentState);\n return;\n }\n\n instance.resetConsent();\n}\n\nexport function flush(): void {\n instance?.flush();\n}\n\n/** @internal Test-only. Resets the module state so init() can be called again. */\nexport function _reset(): void {\n instance = null;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../../src/internal/client.ts"],"sourcesContent":["import type { EnvelopePayload, EventType } from \"@interfere/types/sdk/envelope\";\nimport type { ConsentState } from \"@interfere/types/sdk/plugins/manifest\";\nimport type { RemoteConfig } from \"@interfere/types/sdk/remote-config\";\nimport { inferRuntime, normalizeEnv } from \"@interfere/types/sdk/runtime\";\n\nimport type { PluginOverrides } from \"../plugins/lib/loader.js\";\nimport { bootstrap, session, teardown } from \"../tracking/api.js\";\nimport { buildHeaders, HttpTransport } from \"../transport/http.js\";\nimport { BatchQueue, type QueueOptions } from \"../transport/queue.js\";\nimport { createLogger } from \"../util/log.js\";\nimport { resolveTargets } from \"./config.js\";\nimport { collectContext } from \"./context.js\";\nimport { buildEnvelope, type EnvelopeMetadata } from \"./envelope.js\";\nimport { PluginRuntime } from \"./plugin-runtime.js\";\nimport { registerServiceWorker } from \"./sw.js\";\nimport { PRODUCER_VERSION } from \"./version.js\";\n\nconst log = createLogger(\"client\");\n\nexport function buildSdkStack(wrapperVersions?: string[]): string[] {\n return [...(wrapperVersions ?? []), PRODUCER_VERSION];\n}\n\nexport interface ClientOptions {\n /** @internal Wrapper SDK versions (e.g. `@interfere/next@8.1.0`). */\n _wrapperVersions?: string[];\n batch?: Omit<Partial<QueueOptions>, \"transport\">;\n consent?: ConsentState;\n /**\n * Override the automatic dev-mode guard. When `undefined`, the SDK\n * auto-detects: it disables itself if `process.env[\"NODE_ENV\"]` is not\n * `\"production\"` (Node / webpack / Next.js). In environments where\n * `process` does not exist (Vite, CRA, plain browser) the SDK\n * defaults to **enabled** — pass `false` to disable explicitly.\n */\n enabled?: boolean;\n plugins?: PluginOverrides;\n}\n\nclass Client {\n private readonly metadata: EnvelopeMetadata;\n private readonly queue: BatchQueue;\n private readonly runtime: PluginRuntime;\n\n constructor(opts: ClientOptions, buildId: string, releaseId: string | null) {\n const targets = resolveTargets();\n bootstrap(targets.session);\n\n log.info(\"target: %s\", targets.ingest.url);\n\n this.metadata = {\n context: collectContext(),\n environment: normalizeEnv(\n typeof process === \"undefined\" ? undefined : process.env[\"NODE_ENV\"]\n ),\n runtime: inferRuntime(),\n buildId,\n releaseId,\n ...(opts._wrapperVersions\n ? { wrapperVersions: opts._wrapperVersions }\n : {}),\n };\n\n registerServiceWorker();\n\n const transport = new HttpTransport(targets.ingest);\n this.queue = new BatchQueue({ transport, ...opts.batch });\n this.queue.start();\n\n this.runtime = new PluginRuntime(\n {\n capture: (type, payload) => this.capture(type, payload),\n getSessionId: () => session.getId() ?? \"\",\n },\n opts.plugins,\n opts.consent\n );\n\n this.runtime.start();\n\n this.fetchRemoteConfig(targets.config);\n }\n\n private fetchRemoteConfig(configTarget: {\n url: string;\n headers: Headers;\n }): void {\n fetch(configTarget.url, {\n method: \"GET\",\n headers: buildHeaders(configTarget.headers),\n signal: AbortSignal.timeout(10_000),\n })\n .then((res) => {\n if (!res.ok) {\n return;\n }\n return res.json() as Promise<RemoteConfig>;\n })\n .then((config) => {\n if (config?.plugins) {\n this.runtime.applyRemoteConfig(config.plugins);\n log.debug(\"applied remote config\");\n }\n })\n .catch(() => {\n log.warn(\"remote config fetch failed, using local defaults\");\n });\n }\n\n capture<T extends EventType>(type: T, payload: EnvelopePayload<T>): void {\n const sessionId = session.getId();\n if (!(sessionId && this.runtime.canCapture(type))) {\n return;\n }\n\n this.queue.enqueue(buildEnvelope(type, payload, sessionId, this.metadata));\n }\n\n flush(): void {\n this.queue.flush();\n }\n\n async dispose(): Promise<void> {\n await this.runtime.dispose();\n teardown();\n this.queue.dispose();\n }\n\n getConsent(): ConsentState | null {\n return this.runtime.getConsent();\n }\n\n setConsent(value?: ConsentState): void {\n this.runtime.setConsent(value);\n }\n\n resetConsent(): void {\n this.runtime.resetConsent();\n }\n}\n\nlet instance: Client | null = null;\n\nexport function getClient(): Client {\n if (!instance) {\n throw new Error(\n \"Interfere SDK not initialized. Call init() from your instrumentation-client entrypoint.\"\n );\n }\n return instance;\n}\n\nfunction isEnabledByEnvironment(): boolean {\n try {\n if (typeof process === \"undefined\" || !process.env) {\n return true;\n }\n if (process.env[\"NODE_ENV\"] === \"production\") {\n return true;\n }\n if (process.env[\"NODE_ENV\"] === undefined) {\n return true;\n }\n return !!(\n (globalThis as Record<string, unknown>)[\"__INTERFERE_FORCE_ENABLE__\"] ||\n process.env[\"INTERFERE_FORCE_ENABLE\"]\n );\n } catch {\n return true;\n }\n}\n\nexport function init(opts: ClientOptions = {}): void {\n if (instance) {\n return;\n }\n\n if (!(opts.enabled ?? isEnabledByEnvironment())) {\n log.info(\n \"Disabled in non-production. Pass enabled: true to init() or set INTERFERE_FORCE_ENABLE=1.\"\n );\n return;\n }\n\n const buildId = (globalThis as Record<string, unknown>)[\n \"__INTERFERE_BUILD_ID__\"\n ] as string | undefined;\n\n const releaseId = (globalThis as Record<string, unknown>)[\n \"__INTERFERE_RELEASE_ID__\"\n ] as string | null | undefined;\n\n if (!buildId) {\n log.error(\n \"buildId not found — ensure withInterfere() is configured in \" +\n \"next.config and instrumentation-client.ts exists in your project root.\"\n );\n return;\n }\n\n instance = new Client(opts, buildId, releaseId ?? null);\n\n if (typeof window !== \"undefined\") {\n (window as unknown as Record<string, unknown>)[\"__INTERFERE_SDK_STACK__\"] =\n buildSdkStack(opts._wrapperVersions);\n }\n}\n\nexport async function close(): Promise<void> {\n if (!instance) {\n return;\n }\n\n await instance.dispose();\n instance = null;\n}\n\nexport const consent = {\n get(): ConsentState | null {\n return instance?.getConsent() ?? null;\n },\n\n set(value?: ConsentState): void {\n instance?.setConsent(value);\n },\n};\n\nexport function syncConsent(consentState: ConsentState | undefined): void {\n if (!instance) {\n return;\n }\n\n if (consentState) {\n instance.setConsent(consentState);\n return;\n }\n\n instance.resetConsent();\n}\n\nexport function flush(): void {\n instance?.flush();\n}\n\n/** @internal Test-only. Resets the module state so init() can be called again. */\nexport function _reset(): void {\n instance = null;\n}\n"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ interface EnvelopeMetadata {
|
|
|
8
8
|
environment: Env;
|
|
9
9
|
releaseId: string | null;
|
|
10
10
|
runtime: Runtime;
|
|
11
|
+
wrapperVersions?: string[];
|
|
11
12
|
}
|
|
12
13
|
declare function buildEnvelope<T extends EventType>(type: T, payload: EnvelopePayload<T>, sessionId: string, metadata: EnvelopeMetadata): Envelope<T>;
|
|
13
14
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope.d.mts","names":[],"sources":["../../src/internal/envelope.ts"],"mappings":";;;;UAYiB,gBAAA;EACf,OAAA;EACA,OAAA,EAAS,eAAA;EACT,WAAA,EAAa,GAAA;EACb,SAAA;EACA,OAAA,EAAS,OAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"envelope.d.mts","names":[],"sources":["../../src/internal/envelope.ts"],"mappings":";;;;UAYiB,gBAAA;EACf,OAAA;EACA,OAAA,EAAS,eAAA;EACT,WAAA,EAAa,GAAA;EACb,SAAA;EACA,OAAA,EAAS,OAAA;EACT,eAAA;AAAA;AAAA,iBAGc,aAAA,WAAwB,SAAA,CAAA,CACtC,IAAA,EAAM,CAAA,EACN,OAAA,EAAS,eAAA,CAAgB,CAAA,GACzB,SAAA,UACA,QAAA,EAAU,gBAAA,GACT,QAAA,CAAS,CAAA"}
|
|
@@ -2,6 +2,7 @@ import { PRODUCER_VERSION } from "./version.mjs";
|
|
|
2
2
|
import { v7 } from "uuid";
|
|
3
3
|
//#region src/internal/envelope.ts
|
|
4
4
|
function buildEnvelope(type, payload, sessionId, metadata) {
|
|
5
|
+
const sdkStack = [...metadata.wrapperVersions ?? [], PRODUCER_VERSION];
|
|
5
6
|
return {
|
|
6
7
|
uuid: v7(),
|
|
7
8
|
v: 0,
|
|
@@ -12,7 +13,8 @@ function buildEnvelope(type, payload, sessionId, metadata) {
|
|
|
12
13
|
environment: metadata.environment,
|
|
13
14
|
buildId: metadata.buildId,
|
|
14
15
|
releaseId: metadata.releaseId,
|
|
15
|
-
producerVersion:
|
|
16
|
+
producerVersion: sdkStack[0],
|
|
17
|
+
sdkStack,
|
|
16
18
|
clientTs: Date.now(),
|
|
17
19
|
sessionId,
|
|
18
20
|
sessionSource: "client"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope.mjs","names":["uuidv7"],"sources":["../../src/internal/envelope.ts"],"sourcesContent":["import type {\n Envelope,\n EnvelopeContext,\n EnvelopePayload,\n EventType,\n} from \"@interfere/types/sdk/envelope\";\nimport type { Env, Runtime } from \"@interfere/types/sdk/runtime\";\n\nimport { v7 as uuidv7 } from \"uuid\";\n\nimport { PRODUCER_VERSION } from \"./version.js\";\n\nexport interface EnvelopeMetadata {\n buildId: string;\n context: EnvelopeContext;\n environment: Env;\n releaseId: string | null;\n runtime: Runtime;\n}\n\nexport function buildEnvelope<T extends EventType>(\n type: T,\n payload: EnvelopePayload<T>,\n sessionId: string,\n metadata: EnvelopeMetadata\n): Envelope<T> {\n return {\n uuid: uuidv7(),\n v: 0 as const,\n type,\n payload,\n context: metadata.context,\n runtime: metadata.runtime,\n environment: metadata.environment,\n buildId: metadata.buildId,\n releaseId: metadata.releaseId,\n producerVersion:
|
|
1
|
+
{"version":3,"file":"envelope.mjs","names":["uuidv7"],"sources":["../../src/internal/envelope.ts"],"sourcesContent":["import type {\n Envelope,\n EnvelopeContext,\n EnvelopePayload,\n EventType,\n} from \"@interfere/types/sdk/envelope\";\nimport type { Env, Runtime } from \"@interfere/types/sdk/runtime\";\n\nimport { v7 as uuidv7 } from \"uuid\";\n\nimport { PRODUCER_VERSION } from \"./version.js\";\n\nexport interface EnvelopeMetadata {\n buildId: string;\n context: EnvelopeContext;\n environment: Env;\n releaseId: string | null;\n runtime: Runtime;\n wrapperVersions?: string[];\n}\n\nexport function buildEnvelope<T extends EventType>(\n type: T,\n payload: EnvelopePayload<T>,\n sessionId: string,\n metadata: EnvelopeMetadata\n): Envelope<T> {\n const sdkStack = [...(metadata.wrapperVersions ?? []), PRODUCER_VERSION];\n\n return {\n uuid: uuidv7(),\n v: 0 as const,\n type,\n payload,\n context: metadata.context,\n runtime: metadata.runtime,\n environment: metadata.environment,\n buildId: metadata.buildId,\n releaseId: metadata.releaseId,\n producerVersion: sdkStack[0],\n sdkStack,\n clientTs: Date.now(),\n sessionId,\n sessionSource: \"client\" as const,\n } as Envelope<T>;\n}\n"],"mappings":";;;AAqBA,SAAgB,cACd,MACA,SACA,WACA,UACa;CACb,MAAM,WAAW,CAAC,GAAI,SAAS,mBAAmB,EAAE,EAAG,iBAAiB;AAExE,QAAO;EACL,MAAMA,IAAQ;EACd,GAAG;EACH;EACA;EACA,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,aAAa,SAAS;EACtB,SAAS,SAAS;EAClB,WAAW,SAAS;EACpB,iBAAiB,SAAS;EAC1B;EACA,UAAU,KAAK,KAAK;EACpB;EACA,eAAe;EAChB"}
|
package/dist/package.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.mts","names":[],"sources":["../../src/transport/http.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"http.d.mts","names":[],"sources":["../../src/transport/http.ts"],"mappings":";;;UAUiB,YAAA;EACf,OAAA,EAAS,OAAA;EACT,GAAA;AAAA;AAAA,UAGe,YAAA;EACf,UAAA;EACA,UAAA;AAAA;AAAA,iBAYc,YAAA,CACd,IAAA,EAAM,OAAA,EACN,IAAA,GAAO,YAAA,GACN,MAAA;AAAA,iBAgCa,gBAAA,CAAA;AAAA,cAiBH,aAAA;EAAA,iBACM,MAAA;EAAA,QACT,gBAAA;cAEI,MAAA,EAAQ,YAAA;EAId,IAAA,CAAK,SAAA,EAAW,QAAA,IAAY,IAAA,GAAO,YAAA,GAAe,OAAA;AAAA"}
|
package/dist/transport/http.mjs
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { PRODUCER_VERSION } from "../internal/version.mjs";
|
|
2
1
|
import { createLogger } from "../util/log.mjs";
|
|
3
2
|
import { getDeviceId } from "../tracking/device.mjs";
|
|
4
3
|
import { session } from "../tracking/api.mjs";
|
|
5
4
|
//#region src/transport/http.ts
|
|
6
5
|
const log = createLogger("http");
|
|
7
6
|
const SEND_TIMEOUT_MS = 1e4;
|
|
7
|
+
function getSdkStack() {
|
|
8
|
+
if (typeof window !== "undefined") return window["__INTERFERE_SDK_STACK__"];
|
|
9
|
+
}
|
|
8
10
|
function buildHeaders(base, meta) {
|
|
9
11
|
const h = Object.fromEntries(base.entries());
|
|
10
|
-
|
|
12
|
+
const stack = getSdkStack();
|
|
13
|
+
h["x-interfere-sdk-version"] = stack?.[0] ?? "unknown";
|
|
14
|
+
if (stack && stack.length > 1) h["x-interfere-sdk-stack"] = stack.join(", ");
|
|
11
15
|
const sessionId = session.getId();
|
|
12
16
|
if (sessionId) h["x-interfere-session"] = sessionId;
|
|
13
17
|
const windowId = session.getWindowId();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.mjs","names":[],"sources":["../../src/transport/http.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"http.mjs","names":[],"sources":["../../src/transport/http.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { session } from \"../tracking/api.js\";\nimport { getDeviceId } from \"../tracking/device.js\";\nimport { createLogger } from \"../util/log.js\";\n\nconst log = createLogger(\"http\");\n\nconst SEND_TIMEOUT_MS = 10_000;\n\nexport interface IngestTarget {\n headers: Headers;\n url: string;\n}\n\nexport interface DeliveryMeta {\n queueDepth: number;\n retryCount: number;\n}\n\nfunction getSdkStack(): string[] | undefined {\n if (typeof window !== \"undefined\") {\n return (window as unknown as Record<string, unknown>)[\n \"__INTERFERE_SDK_STACK__\"\n ] as string[] | undefined;\n }\n return undefined;\n}\n\nexport function buildHeaders(\n base: Headers,\n meta?: DeliveryMeta\n): Record<string, string> {\n const h: Record<string, string> = Object.fromEntries(base.entries());\n\n const stack = getSdkStack();\n h[\"x-interfere-sdk-version\"] = stack?.[0] ?? \"unknown\";\n if (stack && stack.length > 1) {\n h[\"x-interfere-sdk-stack\"] = stack.join(\", \");\n }\n\n const sessionId = session.getId();\n if (sessionId) {\n h[\"x-interfere-session\"] = sessionId;\n }\n\n const windowId = session.getWindowId();\n if (windowId) {\n h[\"x-interfere-window\"] = windowId;\n }\n\n const deviceId = getDeviceId();\n if (deviceId) {\n h[\"x-interfere-device\"] = deviceId;\n }\n\n if (meta) {\n h[\"x-interfere-retry-count\"] = String(meta.retryCount);\n h[\"x-interfere-queue-depth\"] = String(meta.queueDepth);\n }\n\n return h;\n}\n\nexport function hasServiceWorker(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n navigator.serviceWorker.controller !== null\n );\n}\n\nfunction assertOk(response: Response): void {\n if (!response.ok) {\n throw new Error(`ingest responded ${response.status}`);\n }\n}\n\nconst KEEPALIVE_BUDGET_BYTES = 61_440;\nconst MAX_CONCURRENT_KEEPALIVE = 15;\n\nexport class HttpTransport {\n private readonly target: IngestTarget;\n private pendingKeepalive = 0;\n\n constructor(target: IngestTarget) {\n this.target = target;\n }\n\n async send(envelopes: Envelope[], meta?: DeliveryMeta): Promise<void> {\n const body = JSON.stringify(envelopes);\n const headers = buildHeaders(this.target.headers, meta);\n\n if (hasServiceWorker()) {\n log.debug(\"POST %d envelopes via SW\", envelopes.length);\n const res = await fetch(this.target.url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n assertOk(res);\n return;\n }\n\n const bytes = new TextEncoder().encode(body).byteLength;\n const useKeepalive =\n bytes < KEEPALIVE_BUDGET_BYTES &&\n this.pendingKeepalive < MAX_CONCURRENT_KEEPALIVE;\n\n if (useKeepalive) {\n this.pendingKeepalive++;\n }\n\n log.debug(\n \"POST %d envelopes direct (%d bytes, keepalive=%s)\",\n envelopes.length,\n bytes,\n useKeepalive\n );\n\n try {\n const res = await fetch(this.target.url, {\n method: \"POST\",\n headers,\n body,\n keepalive: useKeepalive,\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n assertOk(res);\n } finally {\n if (useKeepalive) {\n this.pendingKeepalive--;\n }\n }\n }\n}\n"],"mappings":";;;;AAMA,MAAM,MAAM,aAAa,OAAO;AAEhC,MAAM,kBAAkB;AAYxB,SAAS,cAAoC;AAC3C,KAAI,OAAO,WAAW,YACpB,QAAQ,OACN;;AAMN,SAAgB,aACd,MACA,MACwB;CACxB,MAAM,IAA4B,OAAO,YAAY,KAAK,SAAS,CAAC;CAEpE,MAAM,QAAQ,aAAa;AAC3B,GAAE,6BAA6B,QAAQ,MAAM;AAC7C,KAAI,SAAS,MAAM,SAAS,EAC1B,GAAE,2BAA2B,MAAM,KAAK,KAAK;CAG/C,MAAM,YAAY,QAAQ,OAAO;AACjC,KAAI,UACF,GAAE,yBAAyB;CAG7B,MAAM,WAAW,QAAQ,aAAa;AACtC,KAAI,SACF,GAAE,wBAAwB;CAG5B,MAAM,WAAW,aAAa;AAC9B,KAAI,SACF,GAAE,wBAAwB;AAG5B,KAAI,MAAM;AACR,IAAE,6BAA6B,OAAO,KAAK,WAAW;AACtD,IAAE,6BAA6B,OAAO,KAAK,WAAW;;AAGxD,QAAO;;AAGT,SAAgB,mBAA4B;AAC1C,QACE,OAAO,cAAc,eACrB,mBAAmB,aACnB,UAAU,cAAc,eAAe;;AAI3C,SAAS,SAAS,UAA0B;AAC1C,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,oBAAoB,SAAS,SAAS;;AAI1D,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B;AAEjC,IAAa,gBAAb,MAA2B;CACzB;CACA,mBAA2B;CAE3B,YAAY,QAAsB;AAChC,OAAK,SAAS;;CAGhB,MAAM,KAAK,WAAuB,MAAoC;EACpE,MAAM,OAAO,KAAK,UAAU,UAAU;EACtC,MAAM,UAAU,aAAa,KAAK,OAAO,SAAS,KAAK;AAEvD,MAAI,kBAAkB,EAAE;AACtB,OAAI,MAAM,4BAA4B,UAAU,OAAO;AAOvD,YANY,MAAM,MAAM,KAAK,OAAO,KAAK;IACvC,QAAQ;IACR;IACA;IACA,QAAQ,YAAY,QAAQ,gBAAgB;IAC7C,CAAC,CACW;AACb;;EAGF,MAAM,QAAQ,IAAI,aAAa,CAAC,OAAO,KAAK,CAAC;EAC7C,MAAM,eACJ,QAAQ,0BACR,KAAK,mBAAmB;AAE1B,MAAI,aACF,MAAK;AAGP,MAAI,MACF,qDACA,UAAU,QACV,OACA,aACD;AAED,MAAI;AAQF,YAPY,MAAM,MAAM,KAAK,OAAO,KAAK;IACvC,QAAQ;IACR;IACA;IACA,WAAW;IACX,QAAQ,YAAY,QAAQ,gBAAgB;IAC7C,CAAC,CACW;YACL;AACR,OAAI,aACF,MAAK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/react",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Client-side React SDK for Interfere. Error tracking, session replay, and analytics.",
|
|
6
6
|
"keywords": [
|
|
@@ -39,6 +39,11 @@
|
|
|
39
39
|
"@source": "./src/internal/client.ts",
|
|
40
40
|
"types": "./dist/internal/client.d.mts",
|
|
41
41
|
"default": "./dist/internal/client.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./internal/version": {
|
|
44
|
+
"@source": "./src/internal/version.ts",
|
|
45
|
+
"types": "./dist/internal/version.d.mts",
|
|
46
|
+
"default": "./dist/internal/version.mjs"
|
|
42
47
|
}
|
|
43
48
|
},
|
|
44
49
|
"sideEffects": false,
|
|
@@ -53,31 +58,31 @@
|
|
|
53
58
|
},
|
|
54
59
|
"dependencies": {
|
|
55
60
|
"@fingerprintjs/fingerprintjs": "^5.2.0",
|
|
56
|
-
"@interfere/constants": "^8.1.
|
|
57
|
-
"@interfere/types": "^8.1.
|
|
61
|
+
"@interfere/constants": "^8.1.2",
|
|
62
|
+
"@interfere/types": "^8.1.2",
|
|
58
63
|
"@ua-parser-js/pro-enterprise": "^2.0.6",
|
|
59
64
|
"rrweb": "2.0.0-alpha.4",
|
|
60
65
|
"uuid": "^13.0.0"
|
|
61
66
|
},
|
|
62
67
|
"peerDependencies": {
|
|
63
|
-
"react": ">=19",
|
|
64
|
-
"react-dom": ">=19"
|
|
68
|
+
"react": ">=19.2.5",
|
|
69
|
+
"react-dom": ">=19.2.5"
|
|
65
70
|
},
|
|
66
71
|
"devDependencies": {
|
|
67
|
-
"@interfere/test-utils": "^1.0.
|
|
68
|
-
"@interfere/typescript-config": "^8.1.
|
|
72
|
+
"@interfere/test-utils": "^1.0.1",
|
|
73
|
+
"@interfere/typescript-config": "^8.1.1",
|
|
69
74
|
"@rrweb/types": "2.0.0-alpha.20",
|
|
70
75
|
"@types/node": "^24.12.0",
|
|
71
76
|
"@types/react": "19.2.14",
|
|
72
77
|
"@types/react-dom": "19.2.3",
|
|
73
78
|
"@vitejs/plugin-react": "^6.0.1",
|
|
74
|
-
"@vitest/browser": "4.1.
|
|
75
|
-
"@vitest/browser-playwright": "4.1.
|
|
76
|
-
"@vitest/coverage-v8": "^4.1.
|
|
79
|
+
"@vitest/browser": "4.1.4",
|
|
80
|
+
"@vitest/browser-playwright": "4.1.4",
|
|
81
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
77
82
|
"playwright": "^1.59.0",
|
|
78
83
|
"tsdown": "^0.21.7",
|
|
79
84
|
"typescript": "6.0.2",
|
|
80
|
-
"vitest": "^4.1.
|
|
85
|
+
"vitest": "^4.1.4",
|
|
81
86
|
"vitest-browser-react": "2.2.0"
|
|
82
87
|
}
|
|
83
88
|
}
|