@genn-inc/cluebase-frontend-sdk 0.0.3 → 0.0.6

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 (73) hide show
  1. package/README.md +21 -0
  2. package/dist/_generated/{identity-pii-policy.d.ts → identity-pii-policy-text-contains.d.ts} +1 -1
  3. package/dist/_generated/{identity-pii-policy.js → identity-pii-policy-text-contains.js} +1 -1
  4. package/dist/_generated/identity-pii-policy-whole-value.d.ts +37 -0
  5. package/dist/_generated/identity-pii-policy-whole-value.js +106 -0
  6. package/dist/_generated/otel-span-conversion.js +1 -9
  7. package/dist/context/browser-storage.js +1 -2
  8. package/dist/context/environment.js +5 -3
  9. package/dist/context/identity.js +5 -9
  10. package/dist/context/organization.d.ts +1 -1
  11. package/dist/context/organization.js +6 -8
  12. package/dist/context/session.js +6 -8
  13. package/dist/context/tab.js +8 -12
  14. package/dist/context/trace.js +2 -1
  15. package/dist/exporter/batch.d.ts +3 -1
  16. package/dist/exporter/batch.js +6 -10
  17. package/dist/exporter/browser-outbox-records.d.ts +1 -1
  18. package/dist/exporter/browser-outbox-records.js +15 -6
  19. package/dist/exporter/browser-outbox.d.ts +5 -2
  20. package/dist/exporter/browser-outbox.js +48 -11
  21. package/dist/exporter/client.d.ts +2 -2
  22. package/dist/exporter/client.js +15 -30
  23. package/dist/exporter/delivery-response-contract.js +67 -17
  24. package/dist/exporter/delivery-response.d.ts +3 -1
  25. package/dist/exporter/delivery-response.js +31 -20
  26. package/dist/exporter/diagnostics.d.ts +1 -1
  27. package/dist/exporter/diagnostics.js +4 -1
  28. package/dist/exporter/event-id.js +1 -3
  29. package/dist/exporter/frontend-resource.js +5 -4
  30. package/dist/exporter/observation-source-event-exporter.d.ts +1 -0
  31. package/dist/exporter/observation-source-event-exporter.js +5 -2
  32. package/dist/exporter/path-template.js +3 -1
  33. package/dist/exporter/raw-event-to-source-signal.js +4 -2
  34. package/dist/exporter/sanitize.d.ts +3 -2
  35. package/dist/exporter/sanitize.js +4 -3
  36. package/dist/exporter/sdk-core-wasm.d.ts +5 -0
  37. package/dist/exporter/sdk-core-wasm.js +18 -0
  38. package/dist/exporter/source-event.d.ts +1 -0
  39. package/dist/exporter/span-to-source-signal.d.ts +1 -1
  40. package/dist/exporter/span-to-source-signal.js +122 -82
  41. package/dist/index.d.ts +5 -4
  42. package/dist/index.js +16 -6
  43. package/dist/instrumentation/action.js +9 -8
  44. package/dist/instrumentation/dom.js +13 -21
  45. package/dist/instrumentation/drag.js +0 -3
  46. package/dist/instrumentation/error.js +3 -1
  47. package/dist/instrumentation/form.js +5 -6
  48. package/dist/instrumentation/input.js +4 -8
  49. package/dist/instrumentation/location.js +3 -1
  50. package/dist/instrumentation/network-request.js +1 -1
  51. package/dist/instrumentation/network-span-attributes.js +2 -2
  52. package/dist/instrumentation/network.js +7 -3
  53. package/dist/instrumentation/performance.js +1 -2
  54. package/dist/internal/internal-log.js +2 -1
  55. package/dist/provider/_version.d.ts +1 -1
  56. package/dist/provider/_version.js +1 -1
  57. package/dist/provider/config.js +0 -1
  58. package/dist/provider/constants.d.ts +1 -1
  59. package/dist/provider/constants.js +0 -1
  60. package/dist/provider/sdk-event-pipeline.d.ts +2 -1
  61. package/dist/provider/sdk-event-pipeline.js +6 -3
  62. package/dist/provider/sdk-input-normalization.js +2 -2
  63. package/dist/provider/sdk-otel-pipeline.js +5 -4
  64. package/dist/provider/sdk-runtime-surfaces.d.ts +15 -12
  65. package/dist/provider/sdk-runtime-surfaces.js +8 -7
  66. package/dist/provider/sdk.js +67 -12
  67. package/dist/provider/types.d.ts +6 -5
  68. package/dist/wasm/pkg-web/cluebase_sdk_core_wasm.d.ts +41 -0
  69. package/dist/wasm/pkg-web/cluebase_sdk_core_wasm.js +267 -0
  70. package/dist/wasm/pkg-web/cluebase_sdk_core_wasm_bg.wasm +0 -0
  71. package/dist/wasm/pkg-web/cluebase_sdk_core_wasm_bg.wasm.d.ts +12 -0
  72. package/dist/wasm/pkg-web/package.json +15 -0
  73. package/package.json +62 -53
@@ -1,10 +1,10 @@
1
1
  import { SpanStatusCode } from "@opentelemetry/api";
2
2
  import { buildLocalStructuredSummary } from "../exporter/local-minimization.js";
3
- import { cluebaseAuthoredMetricAttribute, cluebaseAuthoredPropertyAttribute, } from "./cluebase-authored-attributes.js";
3
+ import { buildParameterSnapshotBundle } from "../exporter/parameter-snapshot.js";
4
4
  import { sanitizeHeaders } from "../exporter/sanitize.js";
5
5
  import { FRONTEND_EVENT_CATEGORY, FRONTEND_EVENT_NAME, FRONTEND_EVENT_STATUS, } from "../provider/contracts.js";
6
- import { buildParameterSnapshotBundle } from "../exporter/parameter-snapshot.js";
7
6
  import { allowedValuePathsFor } from "../provider/privacy-policy-store.js";
7
+ import { cluebaseAuthoredMetricAttribute, cluebaseAuthoredPropertyAttribute, } from "./cluebase-authored-attributes.js";
8
8
  import { buildResponseShapeEvidence, } from "./network-request.js";
9
9
  const PRIVACY_POLICY_VERSION = 1;
10
10
  const setOptionalString = (span, key, value) => {
@@ -324,9 +324,12 @@ const failOpenRequestLifecycles = (failureType) => {
324
324
  }
325
325
  pendingRequestLifecycles.clear();
326
326
  };
327
- const trackFetchSpanEndWait = () => {
327
+ const trackFetchSpanEndWait = (capture) => {
328
328
  const wait = new Promise((resolve) => {
329
- setTimeout(resolve, FETCH_SPAN_END_SETTLE_MS);
329
+ setTimeout(() => {
330
+ capture.context.requestFlush?.();
331
+ resolve();
332
+ }, FETCH_SPAN_END_SETTLE_MS);
330
333
  });
331
334
  pendingFetchSpanEndWaits.add(wait);
332
335
  void wait.finally(() => pendingFetchSpanEndWaits.delete(wait));
@@ -400,7 +403,7 @@ const configureFetchInstrumentation = (capture) => {
400
403
  observationContext: capture.context.getObservationContext?.() ?? null,
401
404
  deniedKeys: capture.deniedKeys,
402
405
  });
403
- trackFetchSpanEndWait();
406
+ trackFetchSpanEndWait(capture);
404
407
  markRequestLifecycleTerminal(meta);
405
408
  capture.context.requestFlush?.();
406
409
  },
@@ -448,6 +451,7 @@ const configureXhrInstrumentation = (capture) => {
448
451
  observationContext: capture.context.getObservationContext?.() ?? null,
449
452
  deniedKeys: capture.deniedKeys,
450
453
  });
454
+ trackFetchSpanEndWait(capture);
451
455
  markRequestLifecycleTerminal(meta);
452
456
  capture.context.requestFlush?.();
453
457
  },
@@ -91,8 +91,7 @@ const observeEntryType = (observers, entryType, callback) => {
91
91
  observer.observe({ type: entryType, buffered: true });
92
92
  observers.push(observer);
93
93
  }
94
- catch {
95
- }
94
+ catch { }
96
95
  };
97
96
  const readPerformanceNavigation = () => {
98
97
  if (typeof performance === "undefined") {
@@ -26,7 +26,8 @@ export function logSwallowed(operation, _cause, context = {}) {
26
26
  const details = {};
27
27
  for (const [key, value] of Object.entries(context)) {
28
28
  if (SAFE_CONTEXT_KEYS.has(key) &&
29
- (value === null || typeof value === "boolean" ||
29
+ (value === null ||
30
+ typeof value === "boolean" ||
30
31
  (typeof value === "number" && Number.isFinite(value)) ||
31
32
  (typeof value === "string" && SAFE_TOKEN.test(value)))) {
32
33
  details[key] = value;
@@ -1 +1 @@
1
- export declare const SDK_VERSION: "0.0.3";
1
+ export declare const SDK_VERSION: "0.0.6";
@@ -1,3 +1,3 @@
1
1
  // This file is generated by scripts/generate-version-module.mjs.
2
2
  // Do NOT edit by hand. The source of truth is `package.json` `version`.
3
- export const SDK_VERSION = "0.0.3";
3
+ export const SDK_VERSION = "0.0.6";
@@ -104,7 +104,6 @@ export const resolveConfig = (options) => {
104
104
  localSetupCheckEndpoint: null,
105
105
  projectKey: options.projectKey?.trim() ?? "",
106
106
  producerId: DEFAULT_FRONTEND_SOURCE_IDENTIFIER,
107
- transportProfile: DEFAULT_CONFIG.transportProfile,
108
107
  autocapture: options.autocapture ?? DEFAULT_CONFIG.autocapture,
109
108
  captureNetwork: options.captureNetwork ?? DEFAULT_CONFIG.captureNetwork,
110
109
  captureErrors: options.captureErrors ?? DEFAULT_CONFIG.captureErrors,
@@ -1,5 +1,5 @@
1
- import type { CluebaseConsentState, ResolvedCluebaseConfig } from "./types.js";
2
1
  import { SDK_VERSION } from "./_version.js";
2
+ import type { CluebaseConsentState, ResolvedCluebaseConfig } from "./types.js";
3
3
  export { SDK_VERSION };
4
4
  export declare const SDK_NAME = "@genn-inc/cluebase-frontend-sdk";
5
5
  export declare const EVENT_SOURCE: "frontend_sdk";
@@ -44,7 +44,6 @@ export const DEFAULT_CONFIG = {
44
44
  localSetupCheckEndpoint: null,
45
45
  projectKey: "",
46
46
  producerId: DEFAULT_FRONTEND_SOURCE_IDENTIFIER,
47
- transportProfile: "standard",
48
47
  autocapture: true,
49
48
  captureNetwork: true,
50
49
  captureErrors: true,
@@ -1,9 +1,9 @@
1
- import { TraceManager } from "../context/trace.js";
2
1
  import type { EnvironmentManager } from "../context/environment.js";
3
2
  import type { IdentityManager } from "../context/identity.js";
4
3
  import type { OrganizationManager } from "../context/organization.js";
5
4
  import type { SessionManager } from "../context/session.js";
6
5
  import type { TabManager } from "../context/tab.js";
6
+ import { TraceManager } from "../context/trace.js";
7
7
  import type { BatchTransport } from "../exporter/batch.js";
8
8
  import type { InternalMetricsStore } from "../internal/metrics.js";
9
9
  import type { CluebaseConsentState, CluebaseContext, CluebaseInternalLogger, IngestUsageGovernorFeedback, RawCapturedEvent, ResolvedCluebaseConfig } from "./types.js";
@@ -11,6 +11,7 @@ export declare const OFFICIAL_CUSTOM_EVENT_NAME: {
11
11
  readonly identityIdentified: "identity_identified";
12
12
  readonly identityReset: "identity_reset";
13
13
  readonly organizationAssociated: "organization_associated";
14
+ readonly externalAccountLinked: "external_account_linked";
14
15
  readonly sdkInitialized: "sdk_initialized";
15
16
  };
16
17
  export type OfficialCustomEventProperties = Record<string, string | string[] | number>;
@@ -1,12 +1,12 @@
1
1
  import { TraceManager } from "../context/trace.js";
2
2
  import { generateViewId } from "../exporter/event-id.js";
3
- import { rawEventToSourceSignalEvent } from "../exporter/raw-event-to-source-signal.js";
4
3
  import { createFrontendResourceAttributes } from "../exporter/frontend-resource.js";
4
+ import { rawEventToSourceSignalEvent } from "../exporter/raw-event-to-source-signal.js";
5
5
  import { sanitizeObject, } from "../exporter/sanitize.js";
6
- import { DEFAULT_INGEST_USAGE_GOVERNOR_FEEDBACK, hasUsageGovernorFeedbackChanged, isCostCapabilityDisabled, normalizeIngestUsageGovernorFeedback, } from "./usage-governor.js";
7
6
  import { FRONTEND_EVENT_NAME } from "./contracts.js";
8
7
  import { shouldSampleSession } from "./sampling.js";
9
8
  import { stripQueryAndHashFromUrl, toStringOrNull, toSubjectProfile, } from "./sdk-input-normalization.js";
9
+ import { DEFAULT_INGEST_USAGE_GOVERNOR_FEEDBACK, hasUsageGovernorFeedbackChanged, isCostCapabilityDisabled, normalizeIngestUsageGovernorFeedback, } from "./usage-governor.js";
10
10
  const TRACE_ROOT_EVENTS = new Set([
11
11
  "page_view",
12
12
  "route_change",
@@ -23,6 +23,7 @@ export const OFFICIAL_CUSTOM_EVENT_NAME = {
23
23
  identityIdentified: "identity_identified",
24
24
  identityReset: "identity_reset",
25
25
  organizationAssociated: "organization_associated",
26
+ externalAccountLinked: "external_account_linked",
26
27
  sdkInitialized: "sdk_initialized",
27
28
  };
28
29
  const OFFICIAL_CUSTOM_EVENT_NAMES = new Set(Object.values(OFFICIAL_CUSTOM_EVENT_NAME));
@@ -458,7 +459,9 @@ export class ProviderEventPipeline {
458
459
  }
459
460
  function sanitizeContextTraits(traits, deniedKeys, excludedKeys = new Set(), summary, pathPrefix = "", maskIdentityPii = true, preserveExplicitTraits = false) {
460
461
  const sanitized = sanitizeObject(traits, deniedKeys, summary, pathPrefix, maskIdentityPii, preserveExplicitTraits);
461
- if (typeof sanitized !== "object" || sanitized === null || Array.isArray(sanitized)) {
462
+ if (typeof sanitized !== "object" ||
463
+ sanitized === null ||
464
+ Array.isArray(sanitized)) {
462
465
  return {};
463
466
  }
464
467
  return Object.fromEntries(Object.entries(sanitized).filter(([key]) => !excludedKeys.has(key)));
@@ -1,4 +1,4 @@
1
- import { detectIdentityPII, hashIdentityValue } from "../exporter/sanitize.js";
1
+ import { detectWholeValuePII, hashIdentityValue } from "../exporter/sanitize.js";
2
2
  const PUBLIC_CUSTOM_EVENT_NAME_PATTERN = /^[A-Za-z0-9_.:-]{1,128}$/;
3
3
  const SAFE_DATA_IMAGE_MIME_TYPES = new Set([
4
4
  "image/png",
@@ -80,7 +80,7 @@ const normalizeEmailTrait = (raw) => {
80
80
  return null;
81
81
  }
82
82
  const normalized = value.trim().toLowerCase();
83
- return detectIdentityPII(normalized) === "email" ? normalized : null;
83
+ return detectWholeValuePII(normalized) === "email" ? normalized : null;
84
84
  };
85
85
  const emailDomain = (email) => {
86
86
  if (email === null) {
@@ -3,8 +3,8 @@ import { resourceFromAttributes } from "@opentelemetry/resources";
3
3
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
4
4
  import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
5
5
  import { resolveBrowserTokenEndpoint, resolveCanonicalIngestEndpoint, } from "../exporter/client.js";
6
- import { ObservationSourceEventExporter } from "../exporter/observation-source-event-exporter.js";
7
6
  import { createFrontendResourceAttributes } from "../exporter/frontend-resource.js";
7
+ import { ObservationSourceEventExporter } from "../exporter/observation-source-event-exporter.js";
8
8
  import { createCluebaseNetworkPropagator } from "../instrumentation/network.js";
9
9
  import { getSessionCaptureEligibility } from "./sdk-event-pipeline.js";
10
10
  const globalSnapshots = new WeakMap();
@@ -88,7 +88,9 @@ export const createCluebaseOtelPipeline = ({ resolved, getTransport, getContext,
88
88
  propagator: createCluebaseNetworkPropagator(),
89
89
  });
90
90
  globalSnapshots.set(provider, {
91
- installedTracer: getTracerDelegate(trace.getTracerProvider()) === provider ? provider : null,
91
+ installedTracer: getTracerDelegate(trace.getTracerProvider()) === provider
92
+ ? provider
93
+ : null,
92
94
  installedContextManager: isNoopContextManager(contextBeforeRegister)
93
95
  ? readContextManager()
94
96
  : null,
@@ -162,8 +164,7 @@ export const forceFlushCluebaseOtelProvider = async (provider, signal) => {
162
164
  try {
163
165
  await awaitWithAbort(provider.forceFlush(), signal);
164
166
  }
165
- catch {
166
- }
167
+ catch { }
167
168
  };
168
169
  const awaitWithAbort = async (promise, signal) => {
169
170
  if (!signal)
@@ -1,22 +1,26 @@
1
1
  import { TraceManager } from "../context/trace.js";
2
- import { type IngestClient } from "../exporter/client.js";
3
2
  import type { BatchTransport } from "../exporter/batch.js";
3
+ import { type IngestClient } from "../exporter/client.js";
4
4
  import type { InternalMetricsStore } from "../internal/metrics.js";
5
- import type { CluebaseOtelProvider } from "./sdk-otel-pipeline.js";
5
+ import { type CluebaseOtelProvider } from "./sdk-otel-pipeline.js";
6
6
  import type { CaptureModuleContext, CluebaseConsentState, CluebaseInternalLogger, RawCapturedEvent, ResolvedCluebaseConfig } from "./types.js";
7
+ type RuntimeSurfacesObservationContext = {
8
+ anonymousId: string | null;
9
+ userId: string | null;
10
+ organizationId?: string | null;
11
+ sessionId: string | null;
12
+ tabId: string | null;
13
+ };
14
+ type RuntimeSurfacesEventPipeline = {
15
+ getViewId: () => string | null;
16
+ getObservationContext: () => RuntimeSurfacesObservationContext;
17
+ };
7
18
  type ProviderRuntimeSurfacesOptions = {
8
19
  internalMetrics: InternalMetricsStore;
9
20
  logger: CluebaseInternalLogger;
10
21
  enqueueRawEvent: (event: RawCapturedEvent) => void;
11
- getViewId: () => string | null;
22
+ eventPipeline: RuntimeSurfacesEventPipeline;
12
23
  getConsent: () => CluebaseConsentState;
13
- getObservationContext: () => {
14
- anonymousId: string | null;
15
- userId: string | null;
16
- organizationId?: string | null;
17
- sessionId: string | null;
18
- tabId: string | null;
19
- };
20
24
  getTraceManager: () => TraceManager | null;
21
25
  getTransport: () => BatchTransport | null;
22
26
  getTracerProvider: () => CluebaseOtelProvider | null;
@@ -25,9 +29,8 @@ export declare class ProviderRuntimeSurfaces {
25
29
  private readonly internalMetrics;
26
30
  private readonly logger;
27
31
  private readonly enqueueRawEvent;
28
- private readonly getViewId;
32
+ private readonly eventPipeline;
29
33
  private readonly getConsent;
30
- private readonly getObservationContext;
31
34
  private readonly getTraceManager;
32
35
  private readonly getTransport;
33
36
  private readonly getTracerProvider;
@@ -9,6 +9,7 @@ import { startNavigationCapture } from "../instrumentation/navigation.js";
9
9
  import { startNetworkCapture } from "../instrumentation/network.js";
10
10
  import { startPageCapture } from "../instrumentation/page.js";
11
11
  import { startPerformanceCapture } from "../instrumentation/performance.js";
12
+ import { forceFlushCluebaseOtelProvider, } from "./sdk-otel-pipeline.js";
12
13
  const FLUSH_DEBOUNCE_MS = 200;
13
14
  export class ProviderRuntimeSurfaces {
14
15
  constructor(options) {
@@ -19,9 +20,8 @@ export class ProviderRuntimeSurfaces {
19
20
  this.internalMetrics = options.internalMetrics;
20
21
  this.logger = options.logger;
21
22
  this.enqueueRawEvent = options.enqueueRawEvent;
22
- this.getViewId = options.getViewId;
23
+ this.eventPipeline = options.eventPipeline;
23
24
  this.getConsent = options.getConsent;
24
- this.getObservationContext = options.getObservationContext;
25
25
  this.getTraceManager = options.getTraceManager;
26
26
  this.getTransport = options.getTransport;
27
27
  this.getTracerProvider = options.getTracerProvider;
@@ -38,10 +38,9 @@ export class ProviderRuntimeSurfaces {
38
38
  error_code: "capture_module_error",
39
39
  });
40
40
  },
41
- getViewId: () => this.getViewId(),
41
+ getViewId: () => this.eventPipeline.getViewId(),
42
42
  getConsent: () => this.getConsent(),
43
- getObservationContext: () => this.getObservationContext(),
44
- shouldIgnoreElement: () => false,
43
+ getObservationContext: () => this.eventPipeline.getObservationContext(),
45
44
  startInteraction: (input) => {
46
45
  return (this.getTraceManager()?.startInteraction(input) ??
47
46
  input.interactionId ??
@@ -56,6 +55,7 @@ export class ProviderRuntimeSurfaces {
56
55
  return;
57
56
  this.flushDebounceTimer = setTimeout(() => {
58
57
  this.flushDebounceTimer = null;
58
+ void forceFlushCluebaseOtelProvider(this.getTracerProvider());
59
59
  const transport = this.getTransport();
60
60
  if (!transport)
61
61
  return;
@@ -177,12 +177,14 @@ export class ProviderRuntimeSurfaces {
177
177
  }
178
178
  handled = true;
179
179
  onUnloadSessionEnd();
180
+ void forceFlushCluebaseOtelProvider(this.getTracerProvider());
180
181
  this.getTransport()?.flushOnUnload();
181
182
  };
182
183
  const visibilityHandler = () => {
183
184
  if (document.visibilityState !== "hidden") {
184
185
  return;
185
186
  }
187
+ void forceFlushCluebaseOtelProvider(this.getTracerProvider());
186
188
  this.getTransport()?.flushOnUnload();
187
189
  };
188
190
  window.addEventListener("pagehide", handler, { capture: true });
@@ -210,8 +212,7 @@ export class ProviderRuntimeSurfaces {
210
212
  try {
211
213
  dispose();
212
214
  }
213
- catch {
214
- }
215
+ catch { }
215
216
  }
216
217
  this.unloadHandlers = [];
217
218
  }
@@ -7,15 +7,16 @@ import { TraceManager } from "../context/trace.js";
7
7
  import { BatchTransport } from "../exporter/batch.js";
8
8
  import { IngestClient } from "../exporter/client.js";
9
9
  import { DiagnosticStore } from "../exporter/diagnostics.js";
10
- import { detectIdentityPII, hashIdentityValue, isDeniedKey, } from "../exporter/sanitize.js";
10
+ import { detectWholeValuePII, hashIdentityValue, isDeniedKey, } from "../exporter/sanitize.js";
11
+ import { initSdkCoreWasm } from "../exporter/sdk-core-wasm.js";
11
12
  import { InternalMetricsStore } from "../internal/metrics.js";
12
13
  import { isConfigValid, resolveConfig, validateConfig } from "./config.js";
13
14
  import { DEFAULT_BATCH_FLUSH_THRESHOLD_BYTES, DEFAULT_CONSENT, DEFAULT_MAX_BATCH_QUEUE_BYTES, DEFAULT_MAX_BATCH_QUEUE_ITEMS, SDK_VERSION, } from "./constants.js";
14
- import { isValidPublicCustomEventName, normalizeProfileAvatarUrl, normalizePublicIdentityId, toStringOrNull, } from "./sdk-input-normalization.js";
15
+ import { getSdkErrorDetails, reportSdkError } from "./sdk-error.js";
15
16
  import { OFFICIAL_CUSTOM_EVENT_NAME, ProviderEventPipeline, readCurrentLifecycleUrl, } from "./sdk-event-pipeline.js";
17
+ import { isValidPublicCustomEventName, normalizeProfileAvatarUrl, normalizePublicIdentityId, toStringOrNull, } from "./sdk-input-normalization.js";
16
18
  import { createCluebaseOtelPipeline, forceFlushCluebaseOtelProvider, shutdownCluebaseOtelProvider, shutdownCluebaseOtelProviderAsync, } from "./sdk-otel-pipeline.js";
17
19
  import { ProviderRuntimeSurfaces } from "./sdk-runtime-surfaces.js";
18
- import { getSdkErrorDetails, reportSdkError } from "./sdk-error.js";
19
20
  const createNoopLogger = () => {
20
21
  return {
21
22
  debug: () => undefined,
@@ -58,9 +59,8 @@ class CluebaseBrowserSdkImpl {
58
59
  enqueueRawEvent: (event) => {
59
60
  this.enqueueRawEvent(event);
60
61
  },
61
- getViewId: () => this.eventPipeline.getViewId(),
62
+ eventPipeline: this.eventPipeline,
62
63
  getConsent: () => this.consent,
63
- getObservationContext: () => this.eventPipeline.getObservationContext(),
64
64
  getTraceManager: () => this.traceManager,
65
65
  getTransport: () => this.transport,
66
66
  getTracerProvider: () => this.tracerProvider,
@@ -72,6 +72,19 @@ class CluebaseBrowserSdkImpl {
72
72
  getDiagnostics() {
73
73
  return this.diagnostics.snapshot();
74
74
  }
75
+ withActionContext(callback) {
76
+ let snapshot = null;
77
+ try {
78
+ snapshot = this.traceManager?.getCurrentActionContext() ?? null;
79
+ }
80
+ catch (error) {
81
+ reportSdkError("withActionContext", error);
82
+ }
83
+ if (!snapshot || !this.traceManager) {
84
+ return callback();
85
+ }
86
+ return this.traceManager.runWithActionContext(snapshot, callback);
87
+ }
75
88
  init(options) {
76
89
  try {
77
90
  const resolved = resolveConfig(options);
@@ -89,7 +102,6 @@ class CluebaseBrowserSdkImpl {
89
102
  localSetupCheckEndpoint: resolved.localSetupCheckEndpoint,
90
103
  projectKey: resolved.projectKey,
91
104
  producerId: resolved.producerId,
92
- transportProfile: resolved.transportProfile,
93
105
  autocapture: resolved.autocapture,
94
106
  captureNetwork: resolved.captureNetwork,
95
107
  captureErrors: resolved.captureErrors,
@@ -136,6 +148,7 @@ class CluebaseBrowserSdkImpl {
136
148
  client: ingestClient,
137
149
  enabled: effectiveBatch.enabled,
138
150
  flushIntervalMs: effectiveBatch.flushIntervalMs,
151
+ maxSize: effectiveBatch.maxSize,
139
152
  maxPayloadBytes: effectiveBatch.maxPayloadBytes,
140
153
  flushThresholdBytes: DEFAULT_BATCH_FLUSH_THRESHOLD_BYTES,
141
154
  queueMaxBytes: DEFAULT_MAX_BATCH_QUEUE_BYTES,
@@ -166,6 +179,9 @@ class CluebaseBrowserSdkImpl {
166
179
  if (this.consent !== "denied") {
167
180
  this.warmupBrowserToken(ingestClient);
168
181
  }
182
+ void initSdkCoreWasm().catch((error) => {
183
+ reportSdkError("init sdk core wasm", error);
184
+ });
169
185
  this.tracerProvider = createCluebaseOtelPipeline({
170
186
  resolved,
171
187
  getTransport: () => this.transport,
@@ -282,6 +298,44 @@ class CluebaseBrowserSdkImpl {
282
298
  });
283
299
  }
284
300
  }
301
+ linkExternalAccount(namespace, externalId) {
302
+ if (!this.ensureInitializedForPublicCall("linkExternalAccount")) {
303
+ return;
304
+ }
305
+ if (!this.organizationManager) {
306
+ this.warnPublicDrop("linkExternalAccount", "organization manager is unavailable");
307
+ return;
308
+ }
309
+ try {
310
+ const organizationId = this.organizationManager.getContext().organizationId;
311
+ if (!organizationId) {
312
+ this.warnPublicDrop("linkExternalAccount", "setOrganization must be called before linkExternalAccount");
313
+ return;
314
+ }
315
+ const normalizedNamespace = normalizePublicIdentityId(namespace);
316
+ const normalizedExternalId = normalizePublicIdentityId(externalId);
317
+ if (!normalizedNamespace || !normalizedExternalId) {
318
+ this.warnPublicDrop("linkExternalAccount", "namespace and externalId must be non-empty strings");
319
+ return;
320
+ }
321
+ const sanitizedExternalId = this.sanitizeIdentityValue("externalId", normalizedExternalId);
322
+ this.enqueueOfficialCustomEvent(OFFICIAL_CUSTOM_EVENT_NAME.externalAccountLinked, {
323
+ identity_action: "link_external_account",
324
+ external_namespace: normalizedNamespace,
325
+ }, false, {
326
+ link_type: "canonical_subject_to_external",
327
+ organization_id: organizationId,
328
+ external_namespace: normalizedNamespace,
329
+ external_id: sanitizedExternalId,
330
+ });
331
+ this.flushLifecycleEvents();
332
+ }
333
+ catch {
334
+ this.logger.error("linkExternalAccount failed", {
335
+ error_code: "sdk_operation_failed",
336
+ });
337
+ }
338
+ }
285
339
  reset() {
286
340
  if (!this.initialized) {
287
341
  return;
@@ -425,8 +479,7 @@ class CluebaseBrowserSdkImpl {
425
479
  });
426
480
  }
427
481
  }
428
- catch {
429
- }
482
+ catch { }
430
483
  }
431
484
  warnPublicFieldDrop(operation, field, _reason) {
432
485
  this.logger.warn(`Cluebase Frontend SDK ${operation} field dropped`, {
@@ -436,11 +489,13 @@ class CluebaseBrowserSdkImpl {
436
489
  try {
437
490
  if (typeof console !== "undefined" &&
438
491
  typeof console.warn === "function") {
439
- console.warn(`[cluebase] ${operation} field dropped`, { field, error_code: "sdk_field_drop" });
492
+ console.warn(`[cluebase] ${operation} field dropped`, {
493
+ field,
494
+ error_code: "sdk_field_drop",
495
+ });
440
496
  }
441
497
  }
442
- catch {
443
- }
498
+ catch { }
444
499
  }
445
500
  sanitizeIdentifyTraits(traits) {
446
501
  if (!traits) {
@@ -551,7 +606,7 @@ class CluebaseBrowserSdkImpl {
551
606
  const trimmed = raw.trim();
552
607
  if (!trimmed)
553
608
  return trimmed;
554
- const piiCategory = detectIdentityPII(trimmed);
609
+ const piiCategory = detectWholeValuePII(trimmed);
555
610
  if (piiCategory === null)
556
611
  return trimmed;
557
612
  const hashed = hashIdentityValue(trimmed);
@@ -1,5 +1,5 @@
1
- import type { InternalMetricsSnapshot } from "../internal/metrics.js";
2
1
  import type { DiagnosticsSnapshot } from "../exporter/diagnostics.js";
2
+ import type { InternalMetricsSnapshot } from "../internal/metrics.js";
3
3
  import type { FrontendEventName, ParameterCaptureMode, SdkCollectionMode } from "./contracts.js";
4
4
  export type { FrontendEventCategory, FrontendEventName, FrontendEventStatus, ParameterCaptureMode, SdkCollectionMode, } from "./contracts.js";
5
5
  export type CluebaseConsentState = "granted" | "denied" | "unknown";
@@ -19,7 +19,6 @@ export type CluebaseGroupTraits = {
19
19
  } & {
20
20
  [traitName: string]: CanonicalJsonInputValue;
21
21
  };
22
- export type TransportProfile = "standard";
23
22
  export type RequestLifecycleOutcome = "completed" | "failed" | "aborted" | "unknown";
24
23
  export type DiagnosticCollectionConfig = {
25
24
  enabledCollectors?: string[];
@@ -67,7 +66,6 @@ export type ResolvedCluebaseConfig = {
67
66
  localSetupCheckEndpoint: string | null;
68
67
  projectKey: string;
69
68
  producerId: string;
70
- transportProfile: TransportProfile;
71
69
  autocapture: boolean;
72
70
  captureNetwork: boolean;
73
71
  captureErrors: boolean;
@@ -112,6 +110,7 @@ export type CluebaseBrowserSdk = {
112
110
  init(options: CluebaseInitOptions): void;
113
111
  identify(userId: string, traits?: CluebaseSubjectTraits): void;
114
112
  setOrganization(organizationId: string, traits?: CluebaseGroupTraits): void;
113
+ linkExternalAccount(namespace: string, externalId: string): void;
115
114
  logout(): void;
116
115
  reset(): void;
117
116
  track(eventName: string, properties?: CluebaseTrackProperties, metrics?: CluebaseTrackMetrics): void;
@@ -120,6 +119,7 @@ export type CluebaseBrowserSdk = {
120
119
  flush(): Promise<void>;
121
120
  close(): Promise<void>;
122
121
  getDiagnostics(): DiagnosticsSnapshot;
122
+ withActionContext<T>(callback: () => T): T;
123
123
  };
124
124
  export type { CostCapability } from "../_generated/usage-governor-tables.js";
125
125
  import type { CostCapability } from "../_generated/usage-governor-tables.js";
@@ -149,12 +149,14 @@ export type ParameterSnapshotLeaf = {
149
149
  export type ParameterSnapshotValue = ParameterSnapshotLeaf | ParameterSnapshotValue[] | {
150
150
  [key: string]: ParameterSnapshotValue;
151
151
  };
152
- export type SdkIdentityLinkType = "anonymous_to_user" | "user_to_organization" | "logout";
152
+ export type SdkIdentityLinkType = "anonymous_to_user" | "user_to_organization" | "logout" | "canonical_subject_to_external";
153
153
  export type SdkIdentityLinkHint = {
154
154
  link_type: SdkIdentityLinkType;
155
155
  anonymous_id?: string | null;
156
156
  user_id?: string | null;
157
157
  organization_id?: string | null;
158
+ external_namespace?: string | null;
159
+ external_id?: string | null;
158
160
  };
159
161
  export type CluebaseContext = {
160
162
  producer_id: string | null;
@@ -267,7 +269,6 @@ export type CaptureModuleContext = {
267
269
  sessionId: string | null;
268
270
  tabId: string | null;
269
271
  };
270
- shouldIgnoreElement?: (element: Element) => boolean;
271
272
  startInteraction?: (input: {
272
273
  interactionId?: string | null;
273
274
  interactionInitiator?: string | null;
@@ -0,0 +1,41 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export function spanToSdkSignalJson(span_json: string, options_json: string): string;
5
+
6
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
7
+
8
+ export interface InitOutput {
9
+ readonly memory: WebAssembly.Memory;
10
+ readonly spanToSdkSignalJson: (a: number, b: number, c: number, d: number) => [number, number, number, number];
11
+ readonly __wbindgen_exn_store: (a: number) => void;
12
+ readonly __externref_table_alloc: () => number;
13
+ readonly __wbindgen_externrefs: WebAssembly.Table;
14
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
15
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
16
+ readonly __externref_table_dealloc: (a: number) => void;
17
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
18
+ readonly __wbindgen_start: () => void;
19
+ }
20
+
21
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
22
+
23
+ /**
24
+ * Instantiates the given `module`, which can either be bytes or
25
+ * a precompiled `WebAssembly.Module`.
26
+ *
27
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
28
+ *
29
+ * @returns {InitOutput}
30
+ */
31
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
32
+
33
+ /**
34
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
35
+ * for everything else, calls `WebAssembly.instantiate` directly.
36
+ *
37
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
38
+ *
39
+ * @returns {Promise<InitOutput>}
40
+ */
41
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;