@amplitude/session-replay-browser 1.45.0-sr-perf-reliability-rc2.0 → 1.45.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 (45) hide show
  1. package/lib/cjs/config/local-config.d.ts +1 -0
  2. package/lib/cjs/config/local-config.d.ts.map +1 -1
  3. package/lib/cjs/config/local-config.js +3 -0
  4. package/lib/cjs/config/local-config.js.map +1 -1
  5. package/lib/cjs/config/types.d.ts +16 -0
  6. package/lib/cjs/config/types.d.ts.map +1 -1
  7. package/lib/cjs/config/types.js.map +1 -1
  8. package/lib/cjs/events/events-manager.js +1 -1
  9. package/lib/cjs/events/events-manager.js.map +1 -1
  10. package/lib/cjs/track-destination.d.ts +5 -3
  11. package/lib/cjs/track-destination.d.ts.map +1 -1
  12. package/lib/cjs/track-destination.js +30 -20
  13. package/lib/cjs/track-destination.js.map +1 -1
  14. package/lib/cjs/version.d.ts +1 -1
  15. package/lib/cjs/version.d.ts.map +1 -1
  16. package/lib/cjs/version.js +1 -1
  17. package/lib/cjs/version.js.map +1 -1
  18. package/lib/cjs/worker/index.js +1 -1
  19. package/lib/esm/config/local-config.d.ts +1 -0
  20. package/lib/esm/config/local-config.d.ts.map +1 -1
  21. package/lib/esm/config/local-config.js +3 -0
  22. package/lib/esm/config/local-config.js.map +1 -1
  23. package/lib/esm/config/types.d.ts +16 -0
  24. package/lib/esm/config/types.d.ts.map +1 -1
  25. package/lib/esm/config/types.js.map +1 -1
  26. package/lib/esm/events/events-manager.js +1 -1
  27. package/lib/esm/events/events-manager.js.map +1 -1
  28. package/lib/esm/track-destination.d.ts +5 -3
  29. package/lib/esm/track-destination.d.ts.map +1 -1
  30. package/lib/esm/track-destination.js +30 -20
  31. package/lib/esm/track-destination.js.map +1 -1
  32. package/lib/esm/version.d.ts +1 -1
  33. package/lib/esm/version.d.ts.map +1 -1
  34. package/lib/esm/version.js +1 -1
  35. package/lib/esm/version.js.map +1 -1
  36. package/lib/esm/worker/index.js +1 -1
  37. package/lib/scripts/index-min.js +1 -1
  38. package/lib/scripts/index-min.js.gz +0 -0
  39. package/lib/scripts/index-min.js.map +1 -1
  40. package/lib/scripts/session-replay-browser-min.js +1 -1
  41. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  42. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  43. package/lib/scripts/worker-min.js +1 -1
  44. package/lib/scripts/worker-min.js.gz +0 -0
  45. package/package.json +4 -4
@@ -21,6 +21,7 @@ export declare class SessionReplayLocalConfig extends Config implements ISession
21
21
  performanceConfig?: SessionReplayPerformanceConfig;
22
22
  useWebWorker?: boolean;
23
23
  enableTransportCompression?: boolean;
24
+ sendTimeoutMs?: number;
24
25
  applyBackgroundColorToBlockedElements?: boolean;
25
26
  enableUrlChangePolling?: boolean;
26
27
  urlChangePollingInterval?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"local-config.d.ts","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAU9F,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAIjB,eAAO,MAAM,gBAAgB;;;;;CAK3B,CAAC;AAEH,qBAAa,wBAAyB,SAAQ,MAAO,YAAW,yBAAyB;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,8BAA8B,CAAC;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;IAC9C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;gBAErB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;CAyF1D"}
1
+ {"version":3,"file":"local-config.d.ts","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAU9F,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAIjB,eAAO,MAAM,gBAAgB;;;;;CAK3B,CAAC;AAEH,qBAAa,wBAAyB,SAAQ,MAAO,YAAW,yBAAyB;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,8BAA8B,CAAC;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;IAC9C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;gBAErB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;CA4F1D"}
@@ -76,6 +76,9 @@ var SessionReplayLocalConfig = /** @class */ (function (_super) {
76
76
  }
77
77
  }
78
78
  _this.enableTransportCompression = (_k = options.enableTransportCompression) !== null && _k !== void 0 ? _k : true;
79
+ // Pass through undefined so the track destination applies its SEND_TIMEOUT_MS default;
80
+ // an explicit 0 is preserved (disables the timeout).
81
+ _this.sendTimeoutMs = options.sendTimeoutMs;
79
82
  _this.captureAdoptedStyleSheets = (_l = options.captureAdoptedStyleSheets) !== null && _l !== void 0 ? _l : true;
80
83
  if (options.crossOriginIframes) {
81
84
  _this.crossOriginIframes = options.crossOriginIframes;
@@ -1 +1 @@
1
- {"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { Config, ILogger, Logger, FetchTransport, LogLevel } from '@amplitude/analytics-core';\nimport {\n DEFAULT_PERFORMANCE_CONFIG,\n DEFAULT_SAMPLE_RATE,\n DEFAULT_SERVER_ZONE,\n DEFAULT_URL_CHANGE_POLLING_INTERVAL,\n MAX_INTERVAL,\n MIN_INTERVAL,\n UNMASK_TEXT_CLASS,\n} from '../constants';\nimport { SessionReplayOptions, StoreType } from '../typings/session-replay';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n CrossOriginIframesConfig,\n FlushIntervalConfig,\n InteractionConfig,\n PrivacyConfig,\n SessionReplayPerformanceConfig,\n SessionReplayVersion,\n} from './types';\nimport { SafeLoggerProvider } from '../logger';\nimport { validateUGCFilterRules } from '../helpers';\n\nexport const getDefaultConfig = () => ({\n flushMaxRetries: 2,\n logLevel: LogLevel.Warn,\n loggerProvider: new Logger(),\n transportProvider: new FetchTransport(),\n});\n\nexport class SessionReplayLocalConfig extends Config implements ISessionReplayLocalConfig {\n apiKey: string;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n interactionConfig?: InteractionConfig;\n debugMode?: boolean;\n configServerUrl?: string;\n trackServerUrl?: string;\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n storeType: StoreType;\n performanceConfig?: SessionReplayPerformanceConfig;\n useWebWorker?: boolean;\n enableTransportCompression?: boolean;\n applyBackgroundColorToBlockedElements?: boolean;\n enableUrlChangePolling?: boolean;\n urlChangePollingInterval?: number;\n captureDocumentTitle?: boolean;\n captureAdoptedStyleSheets?: boolean;\n crossOriginIframes?: CrossOriginIframesConfig;\n fullSnapshotIntervalMs?: number;\n flushIntervalConfig?: FlushIntervalConfig;\n eagerFullSnapshotSend?: boolean;\n captureFullSnapshotOnFocus?: boolean;\n maxPersistedEventsSizeBytes?: number;\n maxSingleEventSizeBytes?: number;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n const defaultConfig = getDefaultConfig();\n super({\n transportProvider: defaultConfig.transportProvider,\n loggerProvider: new SafeLoggerProvider(options.loggerProvider || defaultConfig.loggerProvider),\n ...options,\n apiKey,\n });\n this.flushMaxRetries =\n options.flushMaxRetries !== undefined && options.flushMaxRetries <= defaultConfig.flushMaxRetries\n ? options.flushMaxRetries\n : defaultConfig.flushMaxRetries;\n\n this.apiKey = apiKey;\n this.sampleRate = options.sampleRate || DEFAULT_SAMPLE_RATE;\n this.serverZone = options.serverZone || DEFAULT_SERVER_ZONE;\n this.configServerUrl = options.configServerUrl;\n this.trackServerUrl = options.trackServerUrl;\n this.shouldInlineStylesheet = options.shouldInlineStylesheet;\n this.version = options.version;\n this.performanceConfig = options.performanceConfig || DEFAULT_PERFORMANCE_CONFIG;\n this.storeType = options.storeType ?? 'memory';\n this.applyBackgroundColorToBlockedElements = options.applyBackgroundColorToBlockedElements ?? false;\n this.enableUrlChangePolling = options.enableUrlChangePolling ?? false;\n this.urlChangePollingInterval = options.urlChangePollingInterval ?? DEFAULT_URL_CHANGE_POLLING_INTERVAL;\n this.captureDocumentTitle = options.captureDocumentTitle ?? false;\n if (options.fullSnapshotIntervalMs !== undefined) {\n this.fullSnapshotIntervalMs = options.fullSnapshotIntervalMs;\n }\n if (options.eagerFullSnapshotSend !== undefined) {\n this.eagerFullSnapshotSend = options.eagerFullSnapshotSend;\n }\n if (options.captureFullSnapshotOnFocus !== undefined) {\n this.captureFullSnapshotOnFocus = options.captureFullSnapshotOnFocus;\n }\n if (options.maxPersistedEventsSizeBytes !== undefined) {\n this.maxPersistedEventsSizeBytes = sanitizeByteSize(\n options.maxPersistedEventsSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_PERSISTED_EVENTS_SIZE_CEILING,\n 'maxPersistedEventsSizeBytes',\n this.loggerProvider,\n );\n }\n if (options.maxSingleEventSizeBytes !== undefined) {\n this.maxSingleEventSizeBytes = sanitizeByteSize(\n options.maxSingleEventSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_SINGLE_EVENT_SIZE_CEILING,\n 'maxSingleEventSizeBytes',\n this.loggerProvider,\n );\n }\n\n // Auto-include .amp-unmask as a default unmaskSelector entry so it works\n // symmetrically with amp-mask/amp-block without requiring explicit config (SR-2945).\n this.privacyConfig = {\n ...(options.privacyConfig ?? {}),\n unmaskSelector: Array.from(new Set([`.${UNMASK_TEXT_CLASS}`, ...(options.privacyConfig?.unmaskSelector ?? [])])),\n };\n if (options.interactionConfig) {\n this.interactionConfig = options.interactionConfig;\n\n // validate ugcFilterRules, throw error if invalid - throw error at the beginning of the config\n if (this.interactionConfig.ugcFilterRules) {\n validateUGCFilterRules(this.interactionConfig.ugcFilterRules);\n }\n }\n if (options.debugMode) {\n this.debugMode = options.debugMode;\n }\n // Support both new useWebWorker and legacy experimental.useWebWorker for backwards compatibility\n if (options.useWebWorker !== undefined) {\n this.useWebWorker = options.useWebWorker;\n } else {\n const legacyOptions = options as { experimental?: { useWebWorker?: boolean } };\n if (legacyOptions.experimental?.useWebWorker !== undefined) {\n this.useWebWorker = legacyOptions.experimental.useWebWorker;\n }\n }\n this.enableTransportCompression = options.enableTransportCompression ?? true;\n this.captureAdoptedStyleSheets = options.captureAdoptedStyleSheets ?? true;\n if (options.crossOriginIframes) {\n this.crossOriginIframes = options.crossOriginIframes;\n }\n if (options.flushIntervalConfig) {\n this.flushIntervalConfig = sanitizeFlushIntervalConfig(options.flushIntervalConfig, this.loggerProvider);\n }\n }\n}\n\n// 100ms floor avoids degenerate configs (0/negative) that would split on every event.\n// Customers wanting fewer requests should be raising the value, not lowering it; the floor\n// is just a defensive guard against typos and unsigned-int rollovers.\nconst MIN_FLUSH_INTERVAL_FLOOR_MS = 100;\n\n// Shared 1 KB floor for the byte-size overrides — small enough to exercise splitting/drops\n// while debugging, large enough to avoid a 0/negative config that splits on every event.\nconst MIN_EVENT_BYTE_SIZE = 1_000;\n// Batch cap ceiling: stay under the SR ingest service's 10 MB decompressed split threshold\n// (above which the server splits the batch itself) with headroom for the request wrapper.\nconst MAX_PERSISTED_EVENTS_SIZE_CEILING = 8_000_000;\n// Single-event ceiling: the server rejects a single event above ~10 MB, so never allow an\n// override to exceed that.\nconst MAX_SINGLE_EVENT_SIZE_CEILING = 10_000_000;\n\n// Defensive bounds for the byte-size overrides. Non-finite inputs are ignored (fall back to\n// the SDK default); out-of-range values are clamped and logged so a typo can't silently\n// disable splitting or push past the server's limits.\nfunction sanitizeByteSize(\n raw: number,\n min: number,\n max: number,\n name: string,\n loggerProvider: ILogger,\n): number | undefined {\n if (!Number.isFinite(raw)) {\n loggerProvider.warn(`${name} value is not a finite number (got ${String(raw)}); ignoring.`);\n return undefined;\n }\n if (raw < min) {\n loggerProvider.warn(`${name} ${raw} is below floor ${min}; clamping.`);\n return min;\n }\n if (raw > max) {\n loggerProvider.warn(`${name} ${raw} exceeds ceiling ${max}; clamping.`);\n return max;\n }\n return raw;\n}\n\nfunction sanitizeFlushIntervalConfig(raw: FlushIntervalConfig, loggerProvider: ILogger): FlushIntervalConfig {\n const sanitized: FlushIntervalConfig = {};\n if (raw.minIntervalMs !== undefined) {\n if (!Number.isFinite(raw.minIntervalMs) || raw.minIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs ${raw.minIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.minIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.minIntervalMs = raw.minIntervalMs;\n }\n }\n if (raw.maxIntervalMs !== undefined) {\n // Unlike min, `Infinity` is a meaningful value here: it means \"no upper bound on interval\n // growth\" (Math.min(Infinity, x) === x in BaseEventsStore.shouldSplitEventsList). Reject\n // only NaN and sub-floor values; pass Infinity through.\n if (Number.isNaN(raw.maxIntervalMs) || raw.maxIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs ${raw.maxIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.maxIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.maxIntervalMs = raw.maxIntervalMs;\n }\n }\n // Cross-validate against the SDK's effective defaults so that a partial config (only one of\n // {minIntervalMs, maxIntervalMs}) doesn't get silently clamped by the unspecified default.\n // Concrete failure mode without this: customer sets only `minIntervalMs: 30_000`, the store's\n // `maxInterval` falls back to `MAX_INTERVAL = 10_000`, and `shouldSplitEventsList` then\n // caps the effective interval at 10s — silently negating the customer's tune-up.\n // The user-supplied value always wins; we fill in the other side to match.\n if (sanitized.minIntervalMs !== undefined || sanitized.maxIntervalMs !== undefined) {\n const effectiveMin = sanitized.minIntervalMs ?? MIN_INTERVAL;\n const effectiveMax = sanitized.maxIntervalMs ?? MAX_INTERVAL;\n if (effectiveMax < effectiveMin) {\n if (sanitized.maxIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs (${effectiveMin}) exceeds the default maxIntervalMs (${MAX_INTERVAL}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = effectiveMin;\n } else if (sanitized.minIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${effectiveMax}) is below the default minIntervalMs (${MIN_INTERVAL}); lowering min to match max.`,\n );\n sanitized.minIntervalMs = effectiveMax;\n } else {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${sanitized.maxIntervalMs}) is less than minIntervalMs (${sanitized.minIntervalMs}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = sanitized.minIntervalMs;\n }\n }\n }\n return sanitized;\n}\n"]}
1
+ {"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { Config, ILogger, Logger, FetchTransport, LogLevel } from '@amplitude/analytics-core';\nimport {\n DEFAULT_PERFORMANCE_CONFIG,\n DEFAULT_SAMPLE_RATE,\n DEFAULT_SERVER_ZONE,\n DEFAULT_URL_CHANGE_POLLING_INTERVAL,\n MAX_INTERVAL,\n MIN_INTERVAL,\n UNMASK_TEXT_CLASS,\n} from '../constants';\nimport { SessionReplayOptions, StoreType } from '../typings/session-replay';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n CrossOriginIframesConfig,\n FlushIntervalConfig,\n InteractionConfig,\n PrivacyConfig,\n SessionReplayPerformanceConfig,\n SessionReplayVersion,\n} from './types';\nimport { SafeLoggerProvider } from '../logger';\nimport { validateUGCFilterRules } from '../helpers';\n\nexport const getDefaultConfig = () => ({\n flushMaxRetries: 2,\n logLevel: LogLevel.Warn,\n loggerProvider: new Logger(),\n transportProvider: new FetchTransport(),\n});\n\nexport class SessionReplayLocalConfig extends Config implements ISessionReplayLocalConfig {\n apiKey: string;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n interactionConfig?: InteractionConfig;\n debugMode?: boolean;\n configServerUrl?: string;\n trackServerUrl?: string;\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n storeType: StoreType;\n performanceConfig?: SessionReplayPerformanceConfig;\n useWebWorker?: boolean;\n enableTransportCompression?: boolean;\n sendTimeoutMs?: number;\n applyBackgroundColorToBlockedElements?: boolean;\n enableUrlChangePolling?: boolean;\n urlChangePollingInterval?: number;\n captureDocumentTitle?: boolean;\n captureAdoptedStyleSheets?: boolean;\n crossOriginIframes?: CrossOriginIframesConfig;\n fullSnapshotIntervalMs?: number;\n flushIntervalConfig?: FlushIntervalConfig;\n eagerFullSnapshotSend?: boolean;\n captureFullSnapshotOnFocus?: boolean;\n maxPersistedEventsSizeBytes?: number;\n maxSingleEventSizeBytes?: number;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n const defaultConfig = getDefaultConfig();\n super({\n transportProvider: defaultConfig.transportProvider,\n loggerProvider: new SafeLoggerProvider(options.loggerProvider || defaultConfig.loggerProvider),\n ...options,\n apiKey,\n });\n this.flushMaxRetries =\n options.flushMaxRetries !== undefined && options.flushMaxRetries <= defaultConfig.flushMaxRetries\n ? options.flushMaxRetries\n : defaultConfig.flushMaxRetries;\n\n this.apiKey = apiKey;\n this.sampleRate = options.sampleRate || DEFAULT_SAMPLE_RATE;\n this.serverZone = options.serverZone || DEFAULT_SERVER_ZONE;\n this.configServerUrl = options.configServerUrl;\n this.trackServerUrl = options.trackServerUrl;\n this.shouldInlineStylesheet = options.shouldInlineStylesheet;\n this.version = options.version;\n this.performanceConfig = options.performanceConfig || DEFAULT_PERFORMANCE_CONFIG;\n this.storeType = options.storeType ?? 'memory';\n this.applyBackgroundColorToBlockedElements = options.applyBackgroundColorToBlockedElements ?? false;\n this.enableUrlChangePolling = options.enableUrlChangePolling ?? false;\n this.urlChangePollingInterval = options.urlChangePollingInterval ?? DEFAULT_URL_CHANGE_POLLING_INTERVAL;\n this.captureDocumentTitle = options.captureDocumentTitle ?? false;\n if (options.fullSnapshotIntervalMs !== undefined) {\n this.fullSnapshotIntervalMs = options.fullSnapshotIntervalMs;\n }\n if (options.eagerFullSnapshotSend !== undefined) {\n this.eagerFullSnapshotSend = options.eagerFullSnapshotSend;\n }\n if (options.captureFullSnapshotOnFocus !== undefined) {\n this.captureFullSnapshotOnFocus = options.captureFullSnapshotOnFocus;\n }\n if (options.maxPersistedEventsSizeBytes !== undefined) {\n this.maxPersistedEventsSizeBytes = sanitizeByteSize(\n options.maxPersistedEventsSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_PERSISTED_EVENTS_SIZE_CEILING,\n 'maxPersistedEventsSizeBytes',\n this.loggerProvider,\n );\n }\n if (options.maxSingleEventSizeBytes !== undefined) {\n this.maxSingleEventSizeBytes = sanitizeByteSize(\n options.maxSingleEventSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_SINGLE_EVENT_SIZE_CEILING,\n 'maxSingleEventSizeBytes',\n this.loggerProvider,\n );\n }\n\n // Auto-include .amp-unmask as a default unmaskSelector entry so it works\n // symmetrically with amp-mask/amp-block without requiring explicit config (SR-2945).\n this.privacyConfig = {\n ...(options.privacyConfig ?? {}),\n unmaskSelector: Array.from(new Set([`.${UNMASK_TEXT_CLASS}`, ...(options.privacyConfig?.unmaskSelector ?? [])])),\n };\n if (options.interactionConfig) {\n this.interactionConfig = options.interactionConfig;\n\n // validate ugcFilterRules, throw error if invalid - throw error at the beginning of the config\n if (this.interactionConfig.ugcFilterRules) {\n validateUGCFilterRules(this.interactionConfig.ugcFilterRules);\n }\n }\n if (options.debugMode) {\n this.debugMode = options.debugMode;\n }\n // Support both new useWebWorker and legacy experimental.useWebWorker for backwards compatibility\n if (options.useWebWorker !== undefined) {\n this.useWebWorker = options.useWebWorker;\n } else {\n const legacyOptions = options as { experimental?: { useWebWorker?: boolean } };\n if (legacyOptions.experimental?.useWebWorker !== undefined) {\n this.useWebWorker = legacyOptions.experimental.useWebWorker;\n }\n }\n this.enableTransportCompression = options.enableTransportCompression ?? true;\n // Pass through undefined so the track destination applies its SEND_TIMEOUT_MS default;\n // an explicit 0 is preserved (disables the timeout).\n this.sendTimeoutMs = options.sendTimeoutMs;\n this.captureAdoptedStyleSheets = options.captureAdoptedStyleSheets ?? true;\n if (options.crossOriginIframes) {\n this.crossOriginIframes = options.crossOriginIframes;\n }\n if (options.flushIntervalConfig) {\n this.flushIntervalConfig = sanitizeFlushIntervalConfig(options.flushIntervalConfig, this.loggerProvider);\n }\n }\n}\n\n// 100ms floor avoids degenerate configs (0/negative) that would split on every event.\n// Customers wanting fewer requests should be raising the value, not lowering it; the floor\n// is just a defensive guard against typos and unsigned-int rollovers.\nconst MIN_FLUSH_INTERVAL_FLOOR_MS = 100;\n\n// Shared 1 KB floor for the byte-size overrides — small enough to exercise splitting/drops\n// while debugging, large enough to avoid a 0/negative config that splits on every event.\nconst MIN_EVENT_BYTE_SIZE = 1_000;\n// Batch cap ceiling: stay under the SR ingest service's 10 MB decompressed split threshold\n// (above which the server splits the batch itself) with headroom for the request wrapper.\nconst MAX_PERSISTED_EVENTS_SIZE_CEILING = 8_000_000;\n// Single-event ceiling: the server rejects a single event above ~10 MB, so never allow an\n// override to exceed that.\nconst MAX_SINGLE_EVENT_SIZE_CEILING = 10_000_000;\n\n// Defensive bounds for the byte-size overrides. Non-finite inputs are ignored (fall back to\n// the SDK default); out-of-range values are clamped and logged so a typo can't silently\n// disable splitting or push past the server's limits.\nfunction sanitizeByteSize(\n raw: number,\n min: number,\n max: number,\n name: string,\n loggerProvider: ILogger,\n): number | undefined {\n if (!Number.isFinite(raw)) {\n loggerProvider.warn(`${name} value is not a finite number (got ${String(raw)}); ignoring.`);\n return undefined;\n }\n if (raw < min) {\n loggerProvider.warn(`${name} ${raw} is below floor ${min}; clamping.`);\n return min;\n }\n if (raw > max) {\n loggerProvider.warn(`${name} ${raw} exceeds ceiling ${max}; clamping.`);\n return max;\n }\n return raw;\n}\n\nfunction sanitizeFlushIntervalConfig(raw: FlushIntervalConfig, loggerProvider: ILogger): FlushIntervalConfig {\n const sanitized: FlushIntervalConfig = {};\n if (raw.minIntervalMs !== undefined) {\n if (!Number.isFinite(raw.minIntervalMs) || raw.minIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs ${raw.minIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.minIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.minIntervalMs = raw.minIntervalMs;\n }\n }\n if (raw.maxIntervalMs !== undefined) {\n // Unlike min, `Infinity` is a meaningful value here: it means \"no upper bound on interval\n // growth\" (Math.min(Infinity, x) === x in BaseEventsStore.shouldSplitEventsList). Reject\n // only NaN and sub-floor values; pass Infinity through.\n if (Number.isNaN(raw.maxIntervalMs) || raw.maxIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs ${raw.maxIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.maxIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.maxIntervalMs = raw.maxIntervalMs;\n }\n }\n // Cross-validate against the SDK's effective defaults so that a partial config (only one of\n // {minIntervalMs, maxIntervalMs}) doesn't get silently clamped by the unspecified default.\n // Concrete failure mode without this: customer sets only `minIntervalMs: 30_000`, the store's\n // `maxInterval` falls back to `MAX_INTERVAL = 10_000`, and `shouldSplitEventsList` then\n // caps the effective interval at 10s — silently negating the customer's tune-up.\n // The user-supplied value always wins; we fill in the other side to match.\n if (sanitized.minIntervalMs !== undefined || sanitized.maxIntervalMs !== undefined) {\n const effectiveMin = sanitized.minIntervalMs ?? MIN_INTERVAL;\n const effectiveMax = sanitized.maxIntervalMs ?? MAX_INTERVAL;\n if (effectiveMax < effectiveMin) {\n if (sanitized.maxIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs (${effectiveMin}) exceeds the default maxIntervalMs (${MAX_INTERVAL}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = effectiveMin;\n } else if (sanitized.minIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${effectiveMax}) is below the default minIntervalMs (${MIN_INTERVAL}); lowering min to match max.`,\n );\n sanitized.minIntervalMs = effectiveMax;\n } else {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${sanitized.maxIntervalMs}) is less than minIntervalMs (${sanitized.minIntervalMs}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = sanitized.minIntervalMs;\n }\n }\n }\n return sanitized;\n}\n"]}
@@ -184,6 +184,22 @@ export interface SessionReplayLocalConfig extends IConfig {
184
184
  * @defaultValue true
185
185
  */
186
186
  enableTransportCompression?: boolean;
187
+ /**
188
+ * Milliseconds to wait for a send request before aborting it. `fetch()` has no native
189
+ * timeout, so a request stuck "pending" would block the serial flush loop indefinitely;
190
+ * the SDK aborts after this many ms and routes the abort as a retryable failure.
191
+ *
192
+ * Set to `0` (or a negative value) to disable the timeout entirely — note this
193
+ * reintroduces the head-of-line-blocking risk a wedged request can cause, so it is
194
+ * intended only as a diagnostic/experiment opt-out.
195
+ *
196
+ * Tuning this higher is useful when large, slow-but-succeeding uploads are being aborted
197
+ * at the default and counted as failures (which also triggers a retry, inflating request
198
+ * volume / throttle pressure).
199
+ *
200
+ * @defaultValue 10000
201
+ */
202
+ sendTimeoutMs?: number;
187
203
  userProperties?: {
188
204
  [key: string]: any;
189
205
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":";;;AAwDa,QAAA,kBAAkB,GAAG,QAAQ,CAAC","sourcesContent":["import { IConfig, LogLevel, ILogger } from '@amplitude/analytics-core';\nimport { StoreType, ConsoleLogLevel } from '../typings/session-replay';\nimport { TargetingFlag } from '@amplitude/targeting';\n\nexport interface SamplingConfig {\n sample_rate: number;\n capture_enabled: boolean;\n min_session_duration_ms?: number;\n}\n\nexport interface InteractionConfig {\n trackEveryNms?: number;\n enabled: boolean; // defaults to false\n batch: boolean; // defaults to false\n /**\n * UGC filter rules.\n */\n ugcFilterRules?: UGCFilterRule[];\n}\n\nexport interface LoggingConfig {\n console: {\n enabled: boolean;\n levels: ConsoleLogLevel[];\n };\n network?: {\n enabled: boolean;\n body?: {\n request?: boolean;\n response?: boolean;\n maxBodySizeBytes?: number;\n };\n };\n}\n\nexport type TargetingConfig = TargetingFlag;\n\nexport type SessionReplayRemoteConfig = {\n sr_sampling_config?: SamplingConfig;\n sr_privacy_config?: PrivacyConfig;\n sr_interaction_config?: InteractionConfig;\n sr_logging_config?: LoggingConfig;\n sr_targeting_config?: TargetingConfig;\n};\n\nexport interface SessionReplayRemoteConfigAPIResponse {\n configs: {\n sessionReplay: SessionReplayRemoteConfig;\n };\n}\n\nexport type MaskLevel =\n | 'light' // only mask a subset of inputs that's deemed sensitive - password, credit card, telephone #, email. These are information we never want to capture.\n | 'medium' // mask all form fields (inputs); page text is captured as-is\n | 'conservative'; // mask all inputs and all texts\n\nexport const DEFAULT_MASK_LEVEL = 'medium';\n\n// err on the side of excluding more\nexport type PrivacyConfig = {\n blockSelector?: string | string[]; // exclude in the UI\n defaultMaskLevel?: MaskLevel;\n maskSelector?: string[];\n unmaskSelector?: string[];\n maskAttributes?: string[]; // HTML attribute names to mask (e.g. [\"placeholder\", \"aria-label\"])\n /**\n * Per-URL overrides for `defaultMaskLevel`. Each entry contains a glob pattern (`match`)\n * and a `maskLevel` to apply when the current page URL matches that pattern.\n * Rules are evaluated in order; the first match wins. Remote rules take precedence\n * over local rules (remote entries are prepended before local entries).\n *\n * @example\n * urlMaskLevels: [\n * { match: 'https://example.com/checkout/*', maskLevel: 'conservative' },\n * { match: 'https://example.com/public/*', maskLevel: 'light' },\n * ]\n */\n urlMaskLevels?: Array<{ match: string; maskLevel: MaskLevel }>;\n};\n\n/**\n * UGC filter rule.\n */\nexport type UGCFilterRule = {\n /**\n * The selector of the UGC element.\n */\n selector: string;\n /**\n * The replacement text for the UGC element.\n */\n replacement: string;\n};\n\nexport interface CrossOriginIframesConfig {\n enabled: boolean;\n /**\n * When true (default), the parent SDK sends start/stop signals to child iframes via\n * postMessage, keeping their recording lifecycle in sync with the parent.\n *\n * **Privacy note:** The child page's rrweb instance performs its own DOM serialization,\n * so the parent's privacy config (mask levels, block selectors) does NOT automatically\n * apply inside the iframe. Privacy settings must be configured independently on the child page.\n *\n * **Third-party iframes:** Cannot capture iframes you don't control (e.g. Stripe, Google\n * Maps) — both parent and child pages must load the SDK with `crossOriginIframes.enabled: true`.\n *\n * Set to `false` to skip coordination and manage the child recording lifecycle yourself.\n * @defaultValue true\n */\n coordinateChildren?: boolean;\n}\n\nexport interface SessionReplayLocalConfig extends IConfig {\n apiKey: string;\n loggerProvider: ILogger;\n /**\n * LogLevel.None or LogLevel.Error or LogLevel.Warn or LogLevel.Verbose or LogLevel.Debug.\n * Sets the log level.\n *\n * @defaultValue LogLevel.Warn\n */\n logLevel: LogLevel;\n /**\n * The maximum number of retries allowed for sending replay events.\n * Once this limit is reached, failed events will no longer be sent.\n *\n * @defaultValue 2\n */\n flushMaxRetries: number;\n /**\n * Use this option to control how many sessions to select for replay collection.\n * The number should be a decimal between 0 and 1, for example 0.4, representing\n * the fraction of sessions to have randomly selected for replay collection.\n * Over a large number of sessions, 0.4 would select 40% of those sessions.\n * Sample rates as small as six decimal places (0.000001) are supported.\n *\n * @defaultValue 0\n */\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n /**\n * Adds additional debug event property to help debug instrumentation issues\n * (such as mismatching apps). Only recommended for debugging initial setup,\n * and not recommended for production.\n */\n debugMode?: boolean;\n /**\n * Specifies the endpoint URL to fetch remote configuration.\n * If provided, it overrides the default server zone configuration.\n */\n configServerUrl?: string;\n /**\n * Specifies the endpoint URL for sending session replay data.\n * If provided, it overrides the default server zone configuration.\n */\n trackServerUrl?: string;\n /**\n * If stylesheets are inlined, the contents of the stylesheet will be stored.\n * During replay, the stored stylesheet will be used instead of attempting to fetch it remotely.\n * This prevents replays from appearing broken due to missing stylesheets.\n * Note: Inlining stylesheets may not work in all cases.\n */\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n /**\n * Performance configuration config. If enabled, we will defer compression\n * to be done during the browser's idle periods.\n */\n performanceConfig?: SessionReplayPerformanceConfig;\n /**\n * Specifies how replay events should be stored. `idb` uses IndexedDB to persist replay events\n * when all events cannot be sent during capture. `memory` stores replay events only in memory,\n * meaning events are lost when the page is closed. If IndexedDB is unavailable, the system falls back to `memory`.\n */\n storeType: StoreType;\n\n /**\n * If true, the SDK will compress replay events using a web worker.\n * This offloads compression to a separate thread, improving performance on the main thread.\n *\n * @defaultValue false\n */\n useWebWorker?: boolean;\n\n /**\n * Controls transport-layer gzip compression of session replay request bodies.\n * When true (default), the SDK gzip-compresses the JSON request body via the browser's\n * `CompressionStream` API and sets `Content-Encoding: gzip` on the POST. When false,\n * the SDK sends the raw JSON body with no `Content-Encoding` header.\n *\n * Disabling is intended as a debugging / safety opt-out (e.g. for diagnosing\n * server-side decompression issues); it increases egress bytes and is not\n * recommended for production.\n *\n * Note: This is independent of `useWebWorker` / `performanceConfig`, which control\n * per-event rrweb compression that runs before events are queued.\n *\n * @defaultValue true\n */\n enableTransportCompression?: boolean;\n\n userProperties?: { [key: string]: any };\n\n /**\n * If true, applies a background color to blocked elements in the replay.\n * This helps visualize which elements are blocked from being captured.\n */\n applyBackgroundColorToBlockedElements?: boolean;\n /**\n * Enables URL change polling as a fallback for SPA route tracking.\n * When enabled, the SDK will periodically check for URL changes every second\n * in addition to patching the History API. This is useful for edge cases where\n * route changes might bypass the standard History API methods.\n *\n * @defaultValue false\n */\n enableUrlChangePolling?: boolean;\n /**\n * Specifies the interval in milliseconds for URL change polling when enableUrlChangePolling is true.\n * The SDK will check for URL changes at this interval as a fallback for SPA route tracking.\n *\n * @defaultValue 1000\n */\n urlChangePollingInterval?: number;\n /**\n * Whether to capture document title in URL change events.\n * When disabled, the title field will be empty in URL change events.\n *\n * @defaultValue false\n */\n captureDocumentTitle?: boolean;\n interactionConfig?: InteractionConfig;\n /**\n * When true (default), the CSS rules of any `adoptedStyleSheets` on shadow roots and\n * the document are serialized **inline** within the full snapshot. This makes the snapshot\n * self-contained so that shadow DOM styles are replayed correctly even if subsequent\n * incremental `AdoptedStyleSheet` events are dropped in transit.\n *\n * Set to `false` to revert to the legacy behavior where adopted stylesheet rules are\n * emitted as separate incremental events (which may be lost if delivery is unreliable).\n * Only consider opting out if snapshot payload size is a critical concern.\n *\n * @defaultValue true\n */\n captureAdoptedStyleSheets?: boolean;\n /**\n * Enables recording of cross-origin iframes. Both the parent page and each child iframe\n * page must load the Amplitude Session Replay SDK with this option enabled.\n *\n * When enabled, rrweb uses `postMessage` to relay child DOM events to the parent, which\n * merges them into a single unified event stream.\n */\n crossOriginIframes?: CrossOriginIframesConfig;\n /** Interval in ms at which the SDK takes a full DOM snapshot. Disabled by default — periodic snapshots are expensive. Recommended value: 300000 (5 min). */\n fullSnapshotIntervalMs?: number;\n /**\n * Controls how often the SDK splits buffered rrweb events into a sequence and dispatches\n * the resulting batch to the server. The interval starts at `minIntervalMs` and grows by\n * `minIntervalMs` after each split, capped at `maxIntervalMs`. Lowering values increases\n * replay availability latency improvements at the cost of more requests; raising them\n * reduces request volume (and 200+`X-Session-Replay-Event-Skipped` throttling responses)\n * at the cost of slightly delayed replay availability.\n *\n * Defaults: `{ minIntervalMs: 500, maxIntervalMs: 10_000 }`. Tune up if the server is\n * back-pressuring the SDK on session start.\n */\n flushIntervalConfig?: FlushIntervalConfig;\n /**\n * When true (default), every rrweb full snapshot is flushed to the server immediately so\n * replays become playable as early as possible. Set to `false` to defer full-snapshot\n * sends to the normal interval/size flush cadence instead. The snapshot is still compressed\n * and buffered immediately either way (ordering and page-exit beacon coverage are preserved);\n * only the eager network send is suppressed. Disabling reduces request volume for pages that\n * produce many full snapshots (e.g. focus-driven or `fullSnapshotIntervalMs` checkouts),\n * especially when many SDK instances run on the same page.\n *\n * @defaultValue true\n */\n eagerFullSnapshotSend?: boolean;\n /**\n * When true (default), the window `focus` listener forces a fresh rrweb full snapshot\n * (`takeFullSnapshot`) every time the page regains focus, so the replay reflects any DOM\n * changes that happened while the tab was backgrounded. Set to `false` to skip the\n * on-focus full snapshot entirely (recording simply continues from the existing stream).\n *\n * On pages with heavy focus churn (e.g. embedded iframes, inline editors that repeatedly\n * steal and return focus) this fires constantly, and when combined with\n * `eagerFullSnapshotSend` each focus produces an immediate network send — the primary\n * driver of focus-driven request storms. Disabling removes the snapshot (and therefore the\n * send) at the cost of slightly staler post-focus frames.\n *\n * @defaultValue true\n */\n captureFullSnapshotOnFocus?: boolean;\n /**\n * Raw (uncompressed) UTF-8 byte cap for a single buffered events list before the store\n * splits it into its own request. Larger values produce fewer, larger requests (the primary\n * steady-state lever for request volume); smaller values split sooner. Payloads are gzipped\n * on the wire, so several hundred KB of replay JSON compresses to well under 100 KB.\n *\n * Advanced/debug knob — the default already balances request volume against the server's\n * decompressed-size split threshold. Clamped to a safe range; values outside it are clamped\n * and logged. Defaults to the SDK's internal `MAX_EVENT_LIST_SIZE`.\n *\n * @defaultValue 700000\n */\n maxPersistedEventsSizeBytes?: number;\n /**\n * Raw (uncompressed) UTF-8 byte cap for a single rrweb event. Events larger than this are\n * dropped (with a warning) both at capture time and as a pre-send backstop, because the SR\n * ingest service rejects a single event above ~10 MB. Lower this to exercise drop behavior\n * for large full snapshots while debugging.\n *\n * Advanced/debug knob. Clamped to a safe range; values outside it are clamped and logged.\n * Defaults to the SDK's internal `MAX_SINGLE_EVENT_SIZE`.\n *\n * @defaultValue 9000000\n */\n maxSingleEventSizeBytes?: number;\n}\n\nexport interface FlushIntervalConfig {\n /**\n * Lower bound on the rrweb event-split interval in milliseconds. Also the increment\n * added to the interval after each split. Must be > 0; values are clamped to a 100ms floor.\n *\n * @defaultValue 500\n */\n minIntervalMs?: number;\n /**\n * Upper bound on the rrweb event-split interval in milliseconds. Must be >= `minIntervalMs`.\n *\n * @defaultValue 10000\n */\n maxIntervalMs?: number;\n}\n\nexport interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {\n captureEnabled?: boolean;\n interactionConfig?: InteractionConfig;\n loggingConfig?: LoggingConfig;\n targetingConfig?: TargetingConfig;\n minSessionDurationMs?: number;\n}\n\nexport interface SessionReplayConfigs {\n localConfig: SessionReplayLocalConfig;\n joinedConfig: SessionReplayJoinedConfig;\n remoteConfig: SessionReplayRemoteConfig | undefined;\n}\nexport interface SessionReplayJoinedConfigGenerator {\n generateJoinedConfig: () => Promise<SessionReplayConfigs>;\n}\n\nexport interface SessionReplayMetadata {\n remoteConfig: SessionReplayRemoteConfig | undefined;\n localConfig: SessionReplayLocalConfig;\n joinedConfig: SessionReplayJoinedConfig;\n framework?: {\n name: string;\n version: string;\n };\n sessionId: string | number | undefined;\n hashValue?: number;\n sampleRate: number;\n replaySDKType: string | null;\n replaySDKVersion: string | undefined;\n standaloneSDKType: string;\n standaloneSDKVersion: string | undefined;\n}\n\nexport interface SessionReplayVersion {\n version: string;\n type: SessionReplayType;\n}\n\n/**\n * Configuration options for session replay performance.\n */\nexport interface SessionReplayPerformanceConfig {\n /**\n * If enabled, event compression will be deferred to occur during the browser's idle periods.\n */\n enabled: boolean;\n /**\n * Optional timeout in milliseconds for the `requestIdleCallback` API.\n * If specified, this value will be used to set a maximum time for the browser to wait\n * before executing the deferred compression task, even if the browser is not idle.\n */\n timeout?: number;\n /**\n * If enabled, consecutive mutation events will be merged into a single event before\n * compression, reducing stored event count without changing replay semantics.\n * Defaults to false.\n */\n mergeMutations?: boolean;\n /**\n * Performance configuration for interaction tracking (clicks, scrolls).\n */\n interaction?: InteractionPerformanceConfig;\n}\n\n/**\n * Performance configuration for interaction tracking, specifically for CSS selector generation.\n */\nexport interface InteractionPerformanceConfig {\n /**\n * Maximum time in milliseconds allowed for CSS selector generation.\n * If selector generation takes longer than this, it will throw a timeout error.\n * Default: undefined (no timeout limit)\n */\n timeoutMs?: number;\n /**\n * Maximum number of attempts to optimize/simplify the CSS selector path.\n * Higher values may produce shorter selectors but take longer to compute.\n * Default: 10000\n */\n maxNumberOfTries?: number;\n /**\n * Maximum number of CSS selector combinations to test for uniqueness.\n * If more combinations would be generated, falls back to a simpler strategy.\n * Default: 1000\n */\n threshold?: number;\n}\n\nexport type SessionReplayType = 'standalone' | 'plugin' | 'segment';\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":";;;AAwDa,QAAA,kBAAkB,GAAG,QAAQ,CAAC","sourcesContent":["import { IConfig, LogLevel, ILogger } from '@amplitude/analytics-core';\nimport { StoreType, ConsoleLogLevel } from '../typings/session-replay';\nimport { TargetingFlag } from '@amplitude/targeting';\n\nexport interface SamplingConfig {\n sample_rate: number;\n capture_enabled: boolean;\n min_session_duration_ms?: number;\n}\n\nexport interface InteractionConfig {\n trackEveryNms?: number;\n enabled: boolean; // defaults to false\n batch: boolean; // defaults to false\n /**\n * UGC filter rules.\n */\n ugcFilterRules?: UGCFilterRule[];\n}\n\nexport interface LoggingConfig {\n console: {\n enabled: boolean;\n levels: ConsoleLogLevel[];\n };\n network?: {\n enabled: boolean;\n body?: {\n request?: boolean;\n response?: boolean;\n maxBodySizeBytes?: number;\n };\n };\n}\n\nexport type TargetingConfig = TargetingFlag;\n\nexport type SessionReplayRemoteConfig = {\n sr_sampling_config?: SamplingConfig;\n sr_privacy_config?: PrivacyConfig;\n sr_interaction_config?: InteractionConfig;\n sr_logging_config?: LoggingConfig;\n sr_targeting_config?: TargetingConfig;\n};\n\nexport interface SessionReplayRemoteConfigAPIResponse {\n configs: {\n sessionReplay: SessionReplayRemoteConfig;\n };\n}\n\nexport type MaskLevel =\n | 'light' // only mask a subset of inputs that's deemed sensitive - password, credit card, telephone #, email. These are information we never want to capture.\n | 'medium' // mask all form fields (inputs); page text is captured as-is\n | 'conservative'; // mask all inputs and all texts\n\nexport const DEFAULT_MASK_LEVEL = 'medium';\n\n// err on the side of excluding more\nexport type PrivacyConfig = {\n blockSelector?: string | string[]; // exclude in the UI\n defaultMaskLevel?: MaskLevel;\n maskSelector?: string[];\n unmaskSelector?: string[];\n maskAttributes?: string[]; // HTML attribute names to mask (e.g. [\"placeholder\", \"aria-label\"])\n /**\n * Per-URL overrides for `defaultMaskLevel`. Each entry contains a glob pattern (`match`)\n * and a `maskLevel` to apply when the current page URL matches that pattern.\n * Rules are evaluated in order; the first match wins. Remote rules take precedence\n * over local rules (remote entries are prepended before local entries).\n *\n * @example\n * urlMaskLevels: [\n * { match: 'https://example.com/checkout/*', maskLevel: 'conservative' },\n * { match: 'https://example.com/public/*', maskLevel: 'light' },\n * ]\n */\n urlMaskLevels?: Array<{ match: string; maskLevel: MaskLevel }>;\n};\n\n/**\n * UGC filter rule.\n */\nexport type UGCFilterRule = {\n /**\n * The selector of the UGC element.\n */\n selector: string;\n /**\n * The replacement text for the UGC element.\n */\n replacement: string;\n};\n\nexport interface CrossOriginIframesConfig {\n enabled: boolean;\n /**\n * When true (default), the parent SDK sends start/stop signals to child iframes via\n * postMessage, keeping their recording lifecycle in sync with the parent.\n *\n * **Privacy note:** The child page's rrweb instance performs its own DOM serialization,\n * so the parent's privacy config (mask levels, block selectors) does NOT automatically\n * apply inside the iframe. Privacy settings must be configured independently on the child page.\n *\n * **Third-party iframes:** Cannot capture iframes you don't control (e.g. Stripe, Google\n * Maps) — both parent and child pages must load the SDK with `crossOriginIframes.enabled: true`.\n *\n * Set to `false` to skip coordination and manage the child recording lifecycle yourself.\n * @defaultValue true\n */\n coordinateChildren?: boolean;\n}\n\nexport interface SessionReplayLocalConfig extends IConfig {\n apiKey: string;\n loggerProvider: ILogger;\n /**\n * LogLevel.None or LogLevel.Error or LogLevel.Warn or LogLevel.Verbose or LogLevel.Debug.\n * Sets the log level.\n *\n * @defaultValue LogLevel.Warn\n */\n logLevel: LogLevel;\n /**\n * The maximum number of retries allowed for sending replay events.\n * Once this limit is reached, failed events will no longer be sent.\n *\n * @defaultValue 2\n */\n flushMaxRetries: number;\n /**\n * Use this option to control how many sessions to select for replay collection.\n * The number should be a decimal between 0 and 1, for example 0.4, representing\n * the fraction of sessions to have randomly selected for replay collection.\n * Over a large number of sessions, 0.4 would select 40% of those sessions.\n * Sample rates as small as six decimal places (0.000001) are supported.\n *\n * @defaultValue 0\n */\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n /**\n * Adds additional debug event property to help debug instrumentation issues\n * (such as mismatching apps). Only recommended for debugging initial setup,\n * and not recommended for production.\n */\n debugMode?: boolean;\n /**\n * Specifies the endpoint URL to fetch remote configuration.\n * If provided, it overrides the default server zone configuration.\n */\n configServerUrl?: string;\n /**\n * Specifies the endpoint URL for sending session replay data.\n * If provided, it overrides the default server zone configuration.\n */\n trackServerUrl?: string;\n /**\n * If stylesheets are inlined, the contents of the stylesheet will be stored.\n * During replay, the stored stylesheet will be used instead of attempting to fetch it remotely.\n * This prevents replays from appearing broken due to missing stylesheets.\n * Note: Inlining stylesheets may not work in all cases.\n */\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n /**\n * Performance configuration config. If enabled, we will defer compression\n * to be done during the browser's idle periods.\n */\n performanceConfig?: SessionReplayPerformanceConfig;\n /**\n * Specifies how replay events should be stored. `idb` uses IndexedDB to persist replay events\n * when all events cannot be sent during capture. `memory` stores replay events only in memory,\n * meaning events are lost when the page is closed. If IndexedDB is unavailable, the system falls back to `memory`.\n */\n storeType: StoreType;\n\n /**\n * If true, the SDK will compress replay events using a web worker.\n * This offloads compression to a separate thread, improving performance on the main thread.\n *\n * @defaultValue false\n */\n useWebWorker?: boolean;\n\n /**\n * Controls transport-layer gzip compression of session replay request bodies.\n * When true (default), the SDK gzip-compresses the JSON request body via the browser's\n * `CompressionStream` API and sets `Content-Encoding: gzip` on the POST. When false,\n * the SDK sends the raw JSON body with no `Content-Encoding` header.\n *\n * Disabling is intended as a debugging / safety opt-out (e.g. for diagnosing\n * server-side decompression issues); it increases egress bytes and is not\n * recommended for production.\n *\n * Note: This is independent of `useWebWorker` / `performanceConfig`, which control\n * per-event rrweb compression that runs before events are queued.\n *\n * @defaultValue true\n */\n enableTransportCompression?: boolean;\n\n /**\n * Milliseconds to wait for a send request before aborting it. `fetch()` has no native\n * timeout, so a request stuck \"pending\" would block the serial flush loop indefinitely;\n * the SDK aborts after this many ms and routes the abort as a retryable failure.\n *\n * Set to `0` (or a negative value) to disable the timeout entirely — note this\n * reintroduces the head-of-line-blocking risk a wedged request can cause, so it is\n * intended only as a diagnostic/experiment opt-out.\n *\n * Tuning this higher is useful when large, slow-but-succeeding uploads are being aborted\n * at the default and counted as failures (which also triggers a retry, inflating request\n * volume / throttle pressure).\n *\n * @defaultValue 10000\n */\n sendTimeoutMs?: number;\n\n userProperties?: { [key: string]: any };\n\n /**\n * If true, applies a background color to blocked elements in the replay.\n * This helps visualize which elements are blocked from being captured.\n */\n applyBackgroundColorToBlockedElements?: boolean;\n /**\n * Enables URL change polling as a fallback for SPA route tracking.\n * When enabled, the SDK will periodically check for URL changes every second\n * in addition to patching the History API. This is useful for edge cases where\n * route changes might bypass the standard History API methods.\n *\n * @defaultValue false\n */\n enableUrlChangePolling?: boolean;\n /**\n * Specifies the interval in milliseconds for URL change polling when enableUrlChangePolling is true.\n * The SDK will check for URL changes at this interval as a fallback for SPA route tracking.\n *\n * @defaultValue 1000\n */\n urlChangePollingInterval?: number;\n /**\n * Whether to capture document title in URL change events.\n * When disabled, the title field will be empty in URL change events.\n *\n * @defaultValue false\n */\n captureDocumentTitle?: boolean;\n interactionConfig?: InteractionConfig;\n /**\n * When true (default), the CSS rules of any `adoptedStyleSheets` on shadow roots and\n * the document are serialized **inline** within the full snapshot. This makes the snapshot\n * self-contained so that shadow DOM styles are replayed correctly even if subsequent\n * incremental `AdoptedStyleSheet` events are dropped in transit.\n *\n * Set to `false` to revert to the legacy behavior where adopted stylesheet rules are\n * emitted as separate incremental events (which may be lost if delivery is unreliable).\n * Only consider opting out if snapshot payload size is a critical concern.\n *\n * @defaultValue true\n */\n captureAdoptedStyleSheets?: boolean;\n /**\n * Enables recording of cross-origin iframes. Both the parent page and each child iframe\n * page must load the Amplitude Session Replay SDK with this option enabled.\n *\n * When enabled, rrweb uses `postMessage` to relay child DOM events to the parent, which\n * merges them into a single unified event stream.\n */\n crossOriginIframes?: CrossOriginIframesConfig;\n /** Interval in ms at which the SDK takes a full DOM snapshot. Disabled by default — periodic snapshots are expensive. Recommended value: 300000 (5 min). */\n fullSnapshotIntervalMs?: number;\n /**\n * Controls how often the SDK splits buffered rrweb events into a sequence and dispatches\n * the resulting batch to the server. The interval starts at `minIntervalMs` and grows by\n * `minIntervalMs` after each split, capped at `maxIntervalMs`. Lowering values increases\n * replay availability latency improvements at the cost of more requests; raising them\n * reduces request volume (and 200+`X-Session-Replay-Event-Skipped` throttling responses)\n * at the cost of slightly delayed replay availability.\n *\n * Defaults: `{ minIntervalMs: 500, maxIntervalMs: 10_000 }`. Tune up if the server is\n * back-pressuring the SDK on session start.\n */\n flushIntervalConfig?: FlushIntervalConfig;\n /**\n * When true (default), every rrweb full snapshot is flushed to the server immediately so\n * replays become playable as early as possible. Set to `false` to defer full-snapshot\n * sends to the normal interval/size flush cadence instead. The snapshot is still compressed\n * and buffered immediately either way (ordering and page-exit beacon coverage are preserved);\n * only the eager network send is suppressed. Disabling reduces request volume for pages that\n * produce many full snapshots (e.g. focus-driven or `fullSnapshotIntervalMs` checkouts),\n * especially when many SDK instances run on the same page.\n *\n * @defaultValue true\n */\n eagerFullSnapshotSend?: boolean;\n /**\n * When true (default), the window `focus` listener forces a fresh rrweb full snapshot\n * (`takeFullSnapshot`) every time the page regains focus, so the replay reflects any DOM\n * changes that happened while the tab was backgrounded. Set to `false` to skip the\n * on-focus full snapshot entirely (recording simply continues from the existing stream).\n *\n * On pages with heavy focus churn (e.g. embedded iframes, inline editors that repeatedly\n * steal and return focus) this fires constantly, and when combined with\n * `eagerFullSnapshotSend` each focus produces an immediate network send — the primary\n * driver of focus-driven request storms. Disabling removes the snapshot (and therefore the\n * send) at the cost of slightly staler post-focus frames.\n *\n * @defaultValue true\n */\n captureFullSnapshotOnFocus?: boolean;\n /**\n * Raw (uncompressed) UTF-8 byte cap for a single buffered events list before the store\n * splits it into its own request. Larger values produce fewer, larger requests (the primary\n * steady-state lever for request volume); smaller values split sooner. Payloads are gzipped\n * on the wire, so several hundred KB of replay JSON compresses to well under 100 KB.\n *\n * Advanced/debug knob — the default already balances request volume against the server's\n * decompressed-size split threshold. Clamped to a safe range; values outside it are clamped\n * and logged. Defaults to the SDK's internal `MAX_EVENT_LIST_SIZE`.\n *\n * @defaultValue 700000\n */\n maxPersistedEventsSizeBytes?: number;\n /**\n * Raw (uncompressed) UTF-8 byte cap for a single rrweb event. Events larger than this are\n * dropped (with a warning) both at capture time and as a pre-send backstop, because the SR\n * ingest service rejects a single event above ~10 MB. Lower this to exercise drop behavior\n * for large full snapshots while debugging.\n *\n * Advanced/debug knob. Clamped to a safe range; values outside it are clamped and logged.\n * Defaults to the SDK's internal `MAX_SINGLE_EVENT_SIZE`.\n *\n * @defaultValue 9000000\n */\n maxSingleEventSizeBytes?: number;\n}\n\nexport interface FlushIntervalConfig {\n /**\n * Lower bound on the rrweb event-split interval in milliseconds. Also the increment\n * added to the interval after each split. Must be > 0; values are clamped to a 100ms floor.\n *\n * @defaultValue 500\n */\n minIntervalMs?: number;\n /**\n * Upper bound on the rrweb event-split interval in milliseconds. Must be >= `minIntervalMs`.\n *\n * @defaultValue 10000\n */\n maxIntervalMs?: number;\n}\n\nexport interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {\n captureEnabled?: boolean;\n interactionConfig?: InteractionConfig;\n loggingConfig?: LoggingConfig;\n targetingConfig?: TargetingConfig;\n minSessionDurationMs?: number;\n}\n\nexport interface SessionReplayConfigs {\n localConfig: SessionReplayLocalConfig;\n joinedConfig: SessionReplayJoinedConfig;\n remoteConfig: SessionReplayRemoteConfig | undefined;\n}\nexport interface SessionReplayJoinedConfigGenerator {\n generateJoinedConfig: () => Promise<SessionReplayConfigs>;\n}\n\nexport interface SessionReplayMetadata {\n remoteConfig: SessionReplayRemoteConfig | undefined;\n localConfig: SessionReplayLocalConfig;\n joinedConfig: SessionReplayJoinedConfig;\n framework?: {\n name: string;\n version: string;\n };\n sessionId: string | number | undefined;\n hashValue?: number;\n sampleRate: number;\n replaySDKType: string | null;\n replaySDKVersion: string | undefined;\n standaloneSDKType: string;\n standaloneSDKVersion: string | undefined;\n}\n\nexport interface SessionReplayVersion {\n version: string;\n type: SessionReplayType;\n}\n\n/**\n * Configuration options for session replay performance.\n */\nexport interface SessionReplayPerformanceConfig {\n /**\n * If enabled, event compression will be deferred to occur during the browser's idle periods.\n */\n enabled: boolean;\n /**\n * Optional timeout in milliseconds for the `requestIdleCallback` API.\n * If specified, this value will be used to set a maximum time for the browser to wait\n * before executing the deferred compression task, even if the browser is not idle.\n */\n timeout?: number;\n /**\n * If enabled, consecutive mutation events will be merged into a single event before\n * compression, reducing stored event count without changing replay semantics.\n * Defaults to false.\n */\n mergeMutations?: boolean;\n /**\n * Performance configuration for interaction tracking (clicks, scrolls).\n */\n interaction?: InteractionPerformanceConfig;\n}\n\n/**\n * Performance configuration for interaction tracking, specifically for CSS selector generation.\n */\nexport interface InteractionPerformanceConfig {\n /**\n * Maximum time in milliseconds allowed for CSS selector generation.\n * If selector generation takes longer than this, it will throw a timeout error.\n * Default: undefined (no timeout limit)\n */\n timeoutMs?: number;\n /**\n * Maximum number of attempts to optimize/simplify the CSS selector path.\n * Higher values may produce shorter selectors but take longer to compute.\n * Default: 10000\n */\n maxNumberOfTries?: number;\n /**\n * Maximum number of CSS selector combinations to test for uniqueness.\n * If more combinations would be generated, falls back to a simpler strategy.\n * Default: 1000\n */\n threshold?: number;\n}\n\nexport type SessionReplayType = 'standalone' | 'plugin' | 'segment';\n"]}
@@ -206,7 +206,7 @@ var createEventsManager = function (_a) {
206
206
  return [2 /*return*/];
207
207
  }
208
208
  config.loggerProvider.log("Draining ".concat(sequencesToSend.length, " stored sequence(s) from previous session."));
209
- // SR-4660: these persisted sequences are about to be enqueued back-to-back. Without
209
+ // These persisted sequences are about to be enqueued back-to-back. Without
210
210
  // coalescing they flush as N separate POSTs — a request flood on page load. Mark the
211
211
  // imminent flush to merge same-identity batches (the enqueues below are synchronous, so
212
212
  // the whole backlog lands in the queue before the deferred flush consumes the flag). Skip
@@ -1 +1 @@
1
- {"version":3,"file":"events-manager.js","sourceRoot":"","sources":["../../../src/events/events-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n EventsStore,\n EventType,\n StoreType,\n} from '../typings/session-replay';\n\nimport { SessionReplayJoinedConfig } from '../config/types';\nimport { MAX_SINGLE_EVENT_SIZE } from '../constants';\nimport { getStorageSize } from '../helpers';\nimport { PayloadBatcher, SessionReplayTrackDestination } from '../track-destination';\nimport { SessionReplayEventsIDBStore } from './events-idb-store';\nimport { InMemoryEventsStore } from './events-memory-store';\n\nexport type EventsManagerWithBeacon<Type extends EventType> = AmplitudeSessionReplayEventsManager<Type, string> & {\n /**\n * Returns current pending events (since last flush) for synchronous access on page exit.\n * Used to populate a sendBeacon payload when the page is unloading.\n */\n getBeaconEvents(): string[];\n /**\n * Drops all pending beacon events. Used when the session is decided to be below\n * the min duration threshold so its events don't leak into a later session's beacon.\n */\n dropPendingBeaconEvents(): void;\n trackDestination: SessionReplayTrackDestination;\n};\n\nexport const createEventsManager = async <Type extends EventType>({\n config,\n minInterval,\n maxInterval,\n maxPersistedEventsSize,\n type,\n payloadBatcher,\n storeType,\n trackDestinationWorkerScript,\n shouldSend,\n}: {\n config: SessionReplayJoinedConfig;\n type: Type;\n minInterval?: number;\n maxInterval?: number;\n maxPersistedEventsSize?: number;\n payloadBatcher?: PayloadBatcher;\n storeType: StoreType;\n trackDestinationWorkerScript?: string;\n shouldSend?: () => boolean;\n}): Promise<EventsManagerWithBeacon<Type>> => {\n // Configurable per-single-event drop cap (defaults to MAX_SINGLE_EVENT_SIZE); enforced both\n // here as a pre-send backstop and at capture time in EventCompressor.\n const maxSingleEventSize = config.maxSingleEventSizeBytes ?? MAX_SINGLE_EVENT_SIZE;\n const trackDestination = new SessionReplayTrackDestination({\n ...config,\n loggerProvider: config.loggerProvider,\n payloadBatcher,\n workerScript: trackDestinationWorkerScript,\n });\n\n const getMemoryStore = (): EventsStore<number> => {\n return new InMemoryEventsStore({\n loggerProvider: config.loggerProvider,\n maxInterval,\n minInterval,\n maxPersistedEventsSize,\n });\n };\n\n let lastKnownDeviceId: string | undefined;\n let usingIdbStore = false;\n let store!: EventsStore<number>;\n\n const switchToMemoryStore = async () => {\n if (!usingIdbStore) return;\n usingIdbStore = false;\n config.loggerProvider.warn('IDB store is experiencing repeated failures; falling back to in-memory event store.');\n const sequences = lastKnownDeviceId ? await store.getSequencesToSend() : undefined;\n store = getMemoryStore();\n if (sequences && lastKnownDeviceId) {\n const deviceId = lastKnownDeviceId;\n sequences.forEach((seq) => {\n sendEventsList({ sequenceId: seq.sequenceId, events: seq.events, sessionId: seq.sessionId, deviceId });\n });\n }\n };\n\n const getIdbStoreOrFallback = async (): Promise<EventsStore<number>> => {\n const idb = await SessionReplayEventsIDBStore.new(type, {\n loggerProvider: config.loggerProvider,\n minInterval,\n maxInterval,\n maxPersistedEventsSize,\n apiKey: config.apiKey,\n onPersistentFailure: () => {\n void switchToMemoryStore();\n },\n });\n if (!idb) {\n config.loggerProvider.log('Failed to initialize idb store, falling back to memory store.');\n return getMemoryStore();\n }\n usingIdbStore = true;\n return idb;\n };\n\n store = storeType === 'idb' ? await getIdbStoreOrFallback() : getMemoryStore();\n\n // Beacon buffer: a sliding window of pending (unsent) event strings for synchronous\n // access on page exit. Uses an absolute index counter to correctly handle concurrent\n // async flushes without losing events added between the flush call and its resolution.\n const beaconBuffer: string[] = [];\n let beaconWindowStart = 0; // absolute index of the first element in beaconBuffer\n\n const advanceBeaconWindow = (upToAbsoluteIdx: number) => {\n if (upToAbsoluteIdx <= beaconWindowStart) return;\n const trimCount = Math.min(upToAbsoluteIdx - beaconWindowStart, beaconBuffer.length);\n if (trimCount > 0) {\n beaconBuffer.splice(0, trimCount);\n beaconWindowStart = upToAbsoluteIdx;\n }\n };\n\n /**\n * Immediately sends events to the track destination.\n */\n const sendEventsList = ({\n events: rawEvents,\n sessionId,\n deviceId,\n sequenceId,\n }: {\n events: string[];\n sessionId: string | number;\n deviceId: string;\n sequenceId?: number;\n }) => {\n // Backstop for events that entered IDB before the per-event size guard in\n // addCompressedEventToManager (e.g. stored by a previous SDK version or via\n // storeCurrentSequence/sendStoredEvents which bypass the capture-time check).\n // Compare UTF-8 byte size, not JS char count, to match the server-side limit.\n const sizedEvents = rawEvents.map((e) => ({ event: e, bytes: new Blob([e]).size }));\n const oversized = sizedEvents.filter((s) => s.bytes > maxSingleEventSize);\n if (oversized.length > 0) {\n config.loggerProvider.warn(\n `Dropping ${oversized.length} oversized event(s) from session replay sequence before send. Sizes: ${oversized\n .map((s) => `${Math.round(s.bytes / 1024)} KB`)\n .join(\n ', ',\n )}. If this recurs, please open a GitHub issue at https://github.com/amplitude/Amplitude-TypeScript/issues or contact Amplitude support.`,\n );\n }\n const events =\n oversized.length > 0 ? sizedEvents.filter((s) => s.bytes <= maxSingleEventSize).map((s) => s.event) : rawEvents;\n if (events.length === 0) {\n store.cleanUpSessionEventsStore(sessionId, sequenceId).catch((e) => {\n config.loggerProvider.warn('Failed to clean up session replay events store:', e);\n });\n return;\n }\n\n if (config.debugMode) {\n getStorageSize()\n .then(({ totalStorageSize, percentOfQuota, usageDetails }) => {\n config.loggerProvider.debug(\n `Total storage size: ${totalStorageSize} KB, percentage of quota: ${percentOfQuota}%, usage details: ${usageDetails}`,\n );\n })\n .catch(() => {\n // swallow error\n });\n }\n\n trackDestination.sendEventsList({\n events: events,\n sessionId: sessionId,\n flushMaxRetries: config.flushMaxRetries,\n apiKey: config.apiKey,\n deviceId: deviceId,\n sampleRate: config.sampleRate,\n serverZone: config.serverZone,\n version: config.version,\n type,\n onComplete: async () => {\n await store.cleanUpSessionEventsStore(sessionId, sequenceId);\n return;\n },\n });\n };\n\n const sendCurrentSequenceEvents = ({ sessionId, deviceId }: { sessionId: number; deviceId: string }) => {\n lastKnownDeviceId = deviceId;\n // Evaluate shouldSend synchronously before the async store read. asyncSetSessionId\n // updates sessionStartTime immediately after calling sendEvents(), so by the time\n // storeCurrentSequence resolves the start time would reflect the new session and\n // the elapsed check would compute ~0ms, silently dropping the previous session's events.\n if (shouldSend && !shouldSend()) return;\n // Snapshot the absolute end-index before the async store read so that any events\n // pushed after this point are NOT considered sent and remain in the beacon buffer.\n const snapshotAbsIdx = beaconWindowStart + beaconBuffer.length;\n store\n .storeCurrentSequence(sessionId)\n .then((currentSequence) => {\n if (currentSequence) {\n advanceBeaconWindow(snapshotAbsIdx);\n sendEventsList({\n sequenceId: currentSequence.sequenceId,\n events: currentSequence.events,\n sessionId: currentSequence.sessionId,\n deviceId,\n });\n }\n })\n .catch((e) => {\n config.loggerProvider.warn('Failed to get current sequence of session replay events for session:', e);\n });\n };\n\n const sendStoredEvents = async ({ deviceId }: { deviceId: string }) => {\n lastKnownDeviceId = deviceId;\n const sequencesToSend = await store.getSequencesToSend();\n if (!sequencesToSend?.length) {\n return;\n }\n config.loggerProvider.log(`Draining ${sequencesToSend.length} stored sequence(s) from previous session.`);\n // SR-4660: these persisted sequences are about to be enqueued back-to-back. Without\n // coalescing they flush as N separate POSTs — a request flood on page load. Mark the\n // imminent flush to merge same-identity batches (the enqueues below are synchronous, so\n // the whole backlog lands in the queue before the deferred flush consumes the flag). Skip\n // the single-sequence case where there's nothing to merge.\n if (sequencesToSend.length > 1) {\n trackDestination.markCoalesceNextFlush();\n }\n sequencesToSend.forEach((sequence) => {\n sendEventsList({\n sequenceId: sequence.sequenceId,\n events: sequence.events,\n sessionId: sequence.sessionId,\n deviceId,\n });\n });\n };\n\n const addEvent = ({\n event,\n sessionId,\n deviceId,\n }: {\n event: { type: Type; data: string };\n sessionId: number;\n deviceId: string;\n }) => {\n lastKnownDeviceId = deviceId;\n // Capture shouldSend synchronously before the async store write, for the same\n // reason as sendCurrentSequenceEvents: asyncSetSessionId updates sessionStartTime\n // synchronously, so evaluating inside the .then() would use the new session's\n // start time and compute ~0ms elapsed, silently dropping a valid batch.\n const canSend = !shouldSend || shouldSend();\n // Record the absolute index of this event in the beacon buffer before the async\n // store operation. If a batch split occurs, we advance the window up to (but not\n // including) this event so that it starts the next pending window.\n const absIdx = beaconWindowStart + beaconBuffer.length;\n beaconBuffer.push(event.data);\n store\n .addEventToCurrentSequence(sessionId, event.data)\n .then((sequenceToSend) => {\n if (sequenceToSend) {\n if (!canSend) {\n // The split atomically moved events to sequencesToSend; without cleanup\n // they would be unconditionally replayed on next page load via\n // sendStoredEvents, bypassing the min session duration gate. The split\n // batch must also be dropped from the beacon buffer so it isn't sent\n // via sendBeacon on page unload (potentially attributed to a later session).\n store.cleanUpSessionEventsStore(sequenceToSend.sessionId, sequenceToSend.sequenceId).catch((e) => {\n config.loggerProvider.warn('Failed to clean up dropped session replay sequence:', e);\n });\n advanceBeaconWindow(absIdx);\n return;\n }\n // Events before absIdx belong to the split batch being sent; advance window.\n advanceBeaconWindow(absIdx);\n sendEventsList({\n sequenceId: sequenceToSend.sequenceId,\n events: sequenceToSend.events,\n sessionId: sequenceToSend.sessionId,\n deviceId,\n });\n }\n })\n .catch((e) => {\n config.loggerProvider.warn('Failed to add event to session replay capture:', e);\n });\n };\n\n async function flush(useRetry = false) {\n return trackDestination.flush(useRetry);\n }\n\n const getBeaconEvents = (): string[] => [...beaconBuffer];\n\n const dropPendingBeaconEvents = () => {\n advanceBeaconWindow(beaconWindowStart + beaconBuffer.length);\n };\n\n return {\n sendCurrentSequenceEvents,\n addEvent,\n sendStoredEvents,\n flush,\n getBeaconEvents,\n dropPendingBeaconEvents,\n trackDestination,\n };\n};\n"]}
1
+ {"version":3,"file":"events-manager.js","sourceRoot":"","sources":["../../../src/events/events-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n EventsStore,\n EventType,\n StoreType,\n} from '../typings/session-replay';\n\nimport { SessionReplayJoinedConfig } from '../config/types';\nimport { MAX_SINGLE_EVENT_SIZE } from '../constants';\nimport { getStorageSize } from '../helpers';\nimport { PayloadBatcher, SessionReplayTrackDestination } from '../track-destination';\nimport { SessionReplayEventsIDBStore } from './events-idb-store';\nimport { InMemoryEventsStore } from './events-memory-store';\n\nexport type EventsManagerWithBeacon<Type extends EventType> = AmplitudeSessionReplayEventsManager<Type, string> & {\n /**\n * Returns current pending events (since last flush) for synchronous access on page exit.\n * Used to populate a sendBeacon payload when the page is unloading.\n */\n getBeaconEvents(): string[];\n /**\n * Drops all pending beacon events. Used when the session is decided to be below\n * the min duration threshold so its events don't leak into a later session's beacon.\n */\n dropPendingBeaconEvents(): void;\n trackDestination: SessionReplayTrackDestination;\n};\n\nexport const createEventsManager = async <Type extends EventType>({\n config,\n minInterval,\n maxInterval,\n maxPersistedEventsSize,\n type,\n payloadBatcher,\n storeType,\n trackDestinationWorkerScript,\n shouldSend,\n}: {\n config: SessionReplayJoinedConfig;\n type: Type;\n minInterval?: number;\n maxInterval?: number;\n maxPersistedEventsSize?: number;\n payloadBatcher?: PayloadBatcher;\n storeType: StoreType;\n trackDestinationWorkerScript?: string;\n shouldSend?: () => boolean;\n}): Promise<EventsManagerWithBeacon<Type>> => {\n // Configurable per-single-event drop cap (defaults to MAX_SINGLE_EVENT_SIZE); enforced both\n // here as a pre-send backstop and at capture time in EventCompressor.\n const maxSingleEventSize = config.maxSingleEventSizeBytes ?? MAX_SINGLE_EVENT_SIZE;\n const trackDestination = new SessionReplayTrackDestination({\n ...config,\n loggerProvider: config.loggerProvider,\n payloadBatcher,\n workerScript: trackDestinationWorkerScript,\n });\n\n const getMemoryStore = (): EventsStore<number> => {\n return new InMemoryEventsStore({\n loggerProvider: config.loggerProvider,\n maxInterval,\n minInterval,\n maxPersistedEventsSize,\n });\n };\n\n let lastKnownDeviceId: string | undefined;\n let usingIdbStore = false;\n let store!: EventsStore<number>;\n\n const switchToMemoryStore = async () => {\n if (!usingIdbStore) return;\n usingIdbStore = false;\n config.loggerProvider.warn('IDB store is experiencing repeated failures; falling back to in-memory event store.');\n const sequences = lastKnownDeviceId ? await store.getSequencesToSend() : undefined;\n store = getMemoryStore();\n if (sequences && lastKnownDeviceId) {\n const deviceId = lastKnownDeviceId;\n sequences.forEach((seq) => {\n sendEventsList({ sequenceId: seq.sequenceId, events: seq.events, sessionId: seq.sessionId, deviceId });\n });\n }\n };\n\n const getIdbStoreOrFallback = async (): Promise<EventsStore<number>> => {\n const idb = await SessionReplayEventsIDBStore.new(type, {\n loggerProvider: config.loggerProvider,\n minInterval,\n maxInterval,\n maxPersistedEventsSize,\n apiKey: config.apiKey,\n onPersistentFailure: () => {\n void switchToMemoryStore();\n },\n });\n if (!idb) {\n config.loggerProvider.log('Failed to initialize idb store, falling back to memory store.');\n return getMemoryStore();\n }\n usingIdbStore = true;\n return idb;\n };\n\n store = storeType === 'idb' ? await getIdbStoreOrFallback() : getMemoryStore();\n\n // Beacon buffer: a sliding window of pending (unsent) event strings for synchronous\n // access on page exit. Uses an absolute index counter to correctly handle concurrent\n // async flushes without losing events added between the flush call and its resolution.\n const beaconBuffer: string[] = [];\n let beaconWindowStart = 0; // absolute index of the first element in beaconBuffer\n\n const advanceBeaconWindow = (upToAbsoluteIdx: number) => {\n if (upToAbsoluteIdx <= beaconWindowStart) return;\n const trimCount = Math.min(upToAbsoluteIdx - beaconWindowStart, beaconBuffer.length);\n if (trimCount > 0) {\n beaconBuffer.splice(0, trimCount);\n beaconWindowStart = upToAbsoluteIdx;\n }\n };\n\n /**\n * Immediately sends events to the track destination.\n */\n const sendEventsList = ({\n events: rawEvents,\n sessionId,\n deviceId,\n sequenceId,\n }: {\n events: string[];\n sessionId: string | number;\n deviceId: string;\n sequenceId?: number;\n }) => {\n // Backstop for events that entered IDB before the per-event size guard in\n // addCompressedEventToManager (e.g. stored by a previous SDK version or via\n // storeCurrentSequence/sendStoredEvents which bypass the capture-time check).\n // Compare UTF-8 byte size, not JS char count, to match the server-side limit.\n const sizedEvents = rawEvents.map((e) => ({ event: e, bytes: new Blob([e]).size }));\n const oversized = sizedEvents.filter((s) => s.bytes > maxSingleEventSize);\n if (oversized.length > 0) {\n config.loggerProvider.warn(\n `Dropping ${oversized.length} oversized event(s) from session replay sequence before send. Sizes: ${oversized\n .map((s) => `${Math.round(s.bytes / 1024)} KB`)\n .join(\n ', ',\n )}. If this recurs, please open a GitHub issue at https://github.com/amplitude/Amplitude-TypeScript/issues or contact Amplitude support.`,\n );\n }\n const events =\n oversized.length > 0 ? sizedEvents.filter((s) => s.bytes <= maxSingleEventSize).map((s) => s.event) : rawEvents;\n if (events.length === 0) {\n store.cleanUpSessionEventsStore(sessionId, sequenceId).catch((e) => {\n config.loggerProvider.warn('Failed to clean up session replay events store:', e);\n });\n return;\n }\n\n if (config.debugMode) {\n getStorageSize()\n .then(({ totalStorageSize, percentOfQuota, usageDetails }) => {\n config.loggerProvider.debug(\n `Total storage size: ${totalStorageSize} KB, percentage of quota: ${percentOfQuota}%, usage details: ${usageDetails}`,\n );\n })\n .catch(() => {\n // swallow error\n });\n }\n\n trackDestination.sendEventsList({\n events: events,\n sessionId: sessionId,\n flushMaxRetries: config.flushMaxRetries,\n apiKey: config.apiKey,\n deviceId: deviceId,\n sampleRate: config.sampleRate,\n serverZone: config.serverZone,\n version: config.version,\n type,\n onComplete: async () => {\n await store.cleanUpSessionEventsStore(sessionId, sequenceId);\n return;\n },\n });\n };\n\n const sendCurrentSequenceEvents = ({ sessionId, deviceId }: { sessionId: number; deviceId: string }) => {\n lastKnownDeviceId = deviceId;\n // Evaluate shouldSend synchronously before the async store read. asyncSetSessionId\n // updates sessionStartTime immediately after calling sendEvents(), so by the time\n // storeCurrentSequence resolves the start time would reflect the new session and\n // the elapsed check would compute ~0ms, silently dropping the previous session's events.\n if (shouldSend && !shouldSend()) return;\n // Snapshot the absolute end-index before the async store read so that any events\n // pushed after this point are NOT considered sent and remain in the beacon buffer.\n const snapshotAbsIdx = beaconWindowStart + beaconBuffer.length;\n store\n .storeCurrentSequence(sessionId)\n .then((currentSequence) => {\n if (currentSequence) {\n advanceBeaconWindow(snapshotAbsIdx);\n sendEventsList({\n sequenceId: currentSequence.sequenceId,\n events: currentSequence.events,\n sessionId: currentSequence.sessionId,\n deviceId,\n });\n }\n })\n .catch((e) => {\n config.loggerProvider.warn('Failed to get current sequence of session replay events for session:', e);\n });\n };\n\n const sendStoredEvents = async ({ deviceId }: { deviceId: string }) => {\n lastKnownDeviceId = deviceId;\n const sequencesToSend = await store.getSequencesToSend();\n if (!sequencesToSend?.length) {\n return;\n }\n config.loggerProvider.log(`Draining ${sequencesToSend.length} stored sequence(s) from previous session.`);\n // These persisted sequences are about to be enqueued back-to-back. Without\n // coalescing they flush as N separate POSTs — a request flood on page load. Mark the\n // imminent flush to merge same-identity batches (the enqueues below are synchronous, so\n // the whole backlog lands in the queue before the deferred flush consumes the flag). Skip\n // the single-sequence case where there's nothing to merge.\n if (sequencesToSend.length > 1) {\n trackDestination.markCoalesceNextFlush();\n }\n sequencesToSend.forEach((sequence) => {\n sendEventsList({\n sequenceId: sequence.sequenceId,\n events: sequence.events,\n sessionId: sequence.sessionId,\n deviceId,\n });\n });\n };\n\n const addEvent = ({\n event,\n sessionId,\n deviceId,\n }: {\n event: { type: Type; data: string };\n sessionId: number;\n deviceId: string;\n }) => {\n lastKnownDeviceId = deviceId;\n // Capture shouldSend synchronously before the async store write, for the same\n // reason as sendCurrentSequenceEvents: asyncSetSessionId updates sessionStartTime\n // synchronously, so evaluating inside the .then() would use the new session's\n // start time and compute ~0ms elapsed, silently dropping a valid batch.\n const canSend = !shouldSend || shouldSend();\n // Record the absolute index of this event in the beacon buffer before the async\n // store operation. If a batch split occurs, we advance the window up to (but not\n // including) this event so that it starts the next pending window.\n const absIdx = beaconWindowStart + beaconBuffer.length;\n beaconBuffer.push(event.data);\n store\n .addEventToCurrentSequence(sessionId, event.data)\n .then((sequenceToSend) => {\n if (sequenceToSend) {\n if (!canSend) {\n // The split atomically moved events to sequencesToSend; without cleanup\n // they would be unconditionally replayed on next page load via\n // sendStoredEvents, bypassing the min session duration gate. The split\n // batch must also be dropped from the beacon buffer so it isn't sent\n // via sendBeacon on page unload (potentially attributed to a later session).\n store.cleanUpSessionEventsStore(sequenceToSend.sessionId, sequenceToSend.sequenceId).catch((e) => {\n config.loggerProvider.warn('Failed to clean up dropped session replay sequence:', e);\n });\n advanceBeaconWindow(absIdx);\n return;\n }\n // Events before absIdx belong to the split batch being sent; advance window.\n advanceBeaconWindow(absIdx);\n sendEventsList({\n sequenceId: sequenceToSend.sequenceId,\n events: sequenceToSend.events,\n sessionId: sequenceToSend.sessionId,\n deviceId,\n });\n }\n })\n .catch((e) => {\n config.loggerProvider.warn('Failed to add event to session replay capture:', e);\n });\n };\n\n async function flush(useRetry = false) {\n return trackDestination.flush(useRetry);\n }\n\n const getBeaconEvents = (): string[] => [...beaconBuffer];\n\n const dropPendingBeaconEvents = () => {\n advanceBeaconWindow(beaconWindowStart + beaconBuffer.length);\n };\n\n return {\n sendCurrentSequenceEvents,\n addEvent,\n sendStoredEvents,\n flush,\n getBeaconEvents,\n dropPendingBeaconEvents,\n trackDestination,\n };\n};\n"]}
@@ -13,6 +13,7 @@ export declare class SessionReplayTrackDestination implements AmplitudeSessionRe
13
13
  trackServerUrl?: string;
14
14
  retryTimeout: number;
15
15
  private enableTransportCompression;
16
+ private sendTimeoutMs;
16
17
  private scheduled;
17
18
  payloadBatcher: PayloadBatcher;
18
19
  queue: SessionReplayDestinationContext[];
@@ -25,12 +26,13 @@ export declare class SessionReplayTrackDestination implements AmplitudeSessionRe
25
26
  private coalesceNextFlush;
26
27
  private mergeLogFiredThisPause;
27
28
  private killedSessions;
28
- constructor({ trackServerUrl, loggerProvider, payloadBatcher, workerScript, enableTransportCompression, }: {
29
+ constructor({ trackServerUrl, loggerProvider, payloadBatcher, workerScript, enableTransportCompression, sendTimeoutMs, }: {
29
30
  trackServerUrl?: string;
30
31
  loggerProvider: ILogger;
31
32
  payloadBatcher?: PayloadBatcher;
32
33
  workerScript?: string;
33
34
  enableTransportCompression?: boolean;
35
+ sendTimeoutMs?: number;
34
36
  });
35
37
  sendEventsList(destinationData: SessionReplayDestination): void;
36
38
  /**
@@ -39,7 +41,7 @@ export declare class SessionReplayTrackDestination implements AmplitudeSessionRe
39
41
  * sequences replayed back-to-back on init via sendStoredEvents). Because those enqueues are
40
42
  * synchronous and the flush is deferred to the next tick via schedule(0), the whole backlog
41
43
  * lands in the queue before the flag is consumed — collapsing N small POSTs into far fewer
42
- * and avoiding the request flood observed on page load (SR-4660). Steady-state live capture
44
+ * and avoiding the request flood observed on page load. Steady-state live capture
43
45
  * never sets this flag, so its sending behavior is unchanged.
44
46
  *
45
47
  * Schedules a flush so the flag is always consumed by the next flush, even when every
@@ -72,7 +74,7 @@ export declare class SessionReplayTrackDestination implements AmplitudeSessionRe
72
74
  */
73
75
  private mergeQueueAfterThrottle;
74
76
  /**
75
- * Page-load backlog drain path (SR-4660): on init the SDK replays every persisted sequence
77
+ * Page-load backlog drain path: on init the SDK replays every persisted sequence
76
78
  * from a prior session via sendStoredEvents. Enqueued back-to-back they would flush as N
77
79
  * separate POSTs — a request flood on page load that feeds volume spikes and throttling.
78
80
  * Reuses the exact same identity-grouped merge as the post-throttle path so the backlog
@@ -1 +1 @@
1
- {"version":3,"file":"track-destination.d.ts","sourceRoot":"","sources":["../../src/track-destination.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"track-destination.d.ts","sourceRoot":"","sources":["../../src/track-destination.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@ var MAX_KILLED_SESSIONS = 256;
17
17
  var MAX_TIMED_OUT_WORKER_REQUESTS = 256;
18
18
  var SessionReplayTrackDestination = /** @class */ (function () {
19
19
  function SessionReplayTrackDestination(_a) {
20
- var trackServerUrl = _a.trackServerUrl, loggerProvider = _a.loggerProvider, payloadBatcher = _a.payloadBatcher, workerScript = _a.workerScript, enableTransportCompression = _a.enableTransportCompression;
20
+ var trackServerUrl = _a.trackServerUrl, loggerProvider = _a.loggerProvider, payloadBatcher = _a.payloadBatcher, workerScript = _a.workerScript, enableTransportCompression = _a.enableTransportCompression, sendTimeoutMs = _a.sendTimeoutMs;
21
21
  var _this = this;
22
22
  this.storageKey = '';
23
23
  this.retryTimeout = 1000;
@@ -41,7 +41,7 @@ var SessionReplayTrackDestination = /** @class */ (function () {
41
41
  // count, so collapsing N queued batches into one POST directly reduces throttle pressure.
42
42
  this.mergeOnNextFlush = false;
43
43
  // Set by markCoalesceNextFlush() before the page-load backlog is enqueued; consumed by
44
- // flush() to coalesce the drained persisted sequences (SR-4660). Distinct from
44
+ // flush() to coalesce the drained persisted sequences. Distinct from
45
45
  // mergeOnNextFlush so the drain isn't conflated with a throttle pause for logging.
46
46
  this.coalesceNextFlush = false;
47
47
  // Gates the merge log to once per throttle pause window — mirroring the throttle log's
@@ -52,6 +52,7 @@ var SessionReplayTrackDestination = /** @class */ (function () {
52
52
  this.payloadBatcher = payloadBatcher ? payloadBatcher : function (payload) { return payload; };
53
53
  this.trackServerUrl = trackServerUrl;
54
54
  this.enableTransportCompression = enableTransportCompression !== null && enableTransportCompression !== void 0 ? enableTransportCompression : true;
55
+ this.sendTimeoutMs = sendTimeoutMs !== null && sendTimeoutMs !== void 0 ? sendTimeoutMs : constants_1.SEND_TIMEOUT_MS;
55
56
  if (workerScript) {
56
57
  try {
57
58
  var blob = new Blob([workerScript], { type: 'application/javascript' });
@@ -160,7 +161,7 @@ var SessionReplayTrackDestination = /** @class */ (function () {
160
161
  * sequences replayed back-to-back on init via sendStoredEvents). Because those enqueues are
161
162
  * synchronous and the flush is deferred to the next tick via schedule(0), the whole backlog
162
163
  * lands in the queue before the flag is consumed — collapsing N small POSTs into far fewer
163
- * and avoiding the request flood observed on page load (SR-4660). Steady-state live capture
164
+ * and avoiding the request flood observed on page load. Steady-state live capture
164
165
  * never sets this flag, so its sending behavior is unchanged.
165
166
  *
166
167
  * Schedules a flush so the flag is always consumed by the next flush, even when every
@@ -351,7 +352,7 @@ var SessionReplayTrackDestination = /** @class */ (function () {
351
352
  return merged;
352
353
  };
353
354
  /**
354
- * Page-load backlog drain path (SR-4660): on init the SDK replays every persisted sequence
355
+ * Page-load backlog drain path: on init the SDK replays every persisted sequence
355
356
  * from a prior session via sendStoredEvents. Enqueued back-to-back they would flush as N
356
357
  * separate POSTs — a request flood on page load that feeds volume spikes and throttling.
357
358
  * Reuses the exact same identity-grouped merge as the post-throttle path so the backlog
@@ -552,18 +553,23 @@ var SessionReplayTrackDestination = /** @class */ (function () {
552
553
  // completeRequest: like the worker-crash path above, the events were never confirmed
553
554
  // delivered, so onComplete must not fire and the IDB/memory store must stay intact for
554
555
  // recovery by sendStoredEvents.
555
- var timeout = setTimeout(function () {
556
- var pending = _this.pendingWorkerRequests.get(id);
557
- if (!pending)
558
- return;
559
- _this.pendingWorkerRequests.delete(id);
560
- // Retain the context so a *late* worker complete/payload_too_large can still settle the
561
- // store record (see timedOutWorkerRequests). Without this, a worker that ultimately
562
- // delivers after we stopped awaiting would leave the record behind → duplicate upload.
563
- _this.rememberTimedOutRequest(id, pending.context);
564
- _this.loggerProvider.warn("Session replay worker send timed out after ".concat(constants_1.SEND_TIMEOUT_MS, "ms; leaving events for retry"));
565
- pending.resolve();
566
- }, constants_1.SEND_TIMEOUT_MS);
556
+ // sendTimeoutMs <= 0 disables the wait timer entirely: we then rely solely on the
557
+ // worker's own complete/payload_too_large message to settle. This reintroduces the
558
+ // hang risk this timer guards against, so it is an explicit experiment opt-out.
559
+ var timeout = _this.sendTimeoutMs > 0
560
+ ? setTimeout(function () {
561
+ var pending = _this.pendingWorkerRequests.get(id);
562
+ if (!pending)
563
+ return;
564
+ _this.pendingWorkerRequests.delete(id);
565
+ // Retain the context so a *late* worker complete/payload_too_large can still settle the
566
+ // store record (see timedOutWorkerRequests). Without this, a worker that ultimately
567
+ // delivers after we stopped awaiting would leave the record behind → duplicate upload.
568
+ _this.rememberTimedOutRequest(id, pending.context);
569
+ _this.loggerProvider.warn("Session replay worker send timed out after ".concat(_this.sendTimeoutMs, "ms; leaving events for retry"));
570
+ pending.resolve();
571
+ }, _this.sendTimeoutMs)
572
+ : undefined;
567
573
  _this.pendingWorkerRequests.set(id, { context: context, resolve: resolve, timeout: timeout });
568
574
  worker.postMessage({
569
575
  type: 'send',
@@ -584,6 +590,7 @@ var SessionReplayTrackDestination = /** @class */ (function () {
584
590
  currentUrl: (0, helpers_1.getCurrentUrl)(),
585
591
  sdkVersion: version_1.VERSION,
586
592
  enableTransportCompression: _this.enableTransportCompression,
593
+ sendTimeoutMs: _this.sendTimeoutMs,
587
594
  },
588
595
  });
589
596
  })];
@@ -664,9 +671,11 @@ var SessionReplayTrackDestination = /** @class */ (function () {
664
671
  this.completeRequest({ context: context });
665
672
  return [2 /*return*/];
666
673
  }
667
- sendTimeout = setTimeout(function () {
668
- controller_1.abort();
669
- }, constants_1.SEND_TIMEOUT_MS);
674
+ sendTimeout = this.sendTimeoutMs > 0
675
+ ? setTimeout(function () {
676
+ controller_1.abort();
677
+ }, this.sendTimeoutMs)
678
+ : undefined;
670
679
  res = void 0;
671
680
  _k.label = 5;
672
681
  case 5:
@@ -678,7 +687,8 @@ var SessionReplayTrackDestination = /** @class */ (function () {
678
687
  case 7:
679
688
  // Clear on success and on error alike so a settled request never leaves an armed
680
689
  // timer that would abort a later reused controller or fire a stray callback.
681
- clearTimeout(sendTimeout);
690
+ if (sendTimeout)
691
+ clearTimeout(sendTimeout);
682
692
  return [7 /*endfinally*/];
683
693
  case 8:
684
694
  if (res === null) {