/** * Session Recording Types * * Type definitions for rrweb session recording. * Based on PostHog's implementation. */ import type { blockClass, eventWithTime, hooksParam, KeepIframeSrcFn, maskTextClass, PackFn, RecordPlugin, SamplingStrategy } from "@rrweb/types"; /** Mask options for input elements */ export type MaskInputOptions = Partial<{ color: boolean; date: boolean; "datetime-local": boolean; email: boolean; month: boolean; number: boolean; range: boolean; search: boolean; tel: boolean; text: boolean; time: boolean; url: boolean; week: boolean; textarea: boolean; select: boolean; password: boolean; }>; /** Function to mask input values */ export type MaskInputFn = (text: string, element: HTMLElement) => string; /** Function to mask text content */ export type MaskTextFn = (text: string, element: HTMLElement | null) => string; /** Options for slim DOM mode */ export type SlimDOMOptions = Partial<{ script: boolean; comment: boolean; headFavicon: boolean; headWhitespace: boolean; headMetaDescKeywords: boolean; headMetaSocial: boolean; headMetaRobots: boolean; headMetaHttpEquiv: boolean; headMetaAuthorship: boolean; headMetaVerification: boolean; headTitleMutations: boolean; }>; /** Options for data URL generation */ export type DataURLOptions = Partial<{ type: string; quality: number; }>; /** Error handler type */ export type ErrorHandler = (error: unknown) => void | boolean; /** rrweb record options */ export interface RecordOptions { emit?: (e: eventWithTime, isCheckout?: boolean) => void; checkoutEveryNth?: number; checkoutEveryNms?: number; blockClass?: blockClass; blockSelector?: string; ignoreClass?: string; ignoreSelector?: string; maskTextClass?: maskTextClass; maskTextSelector?: string; maskAllInputs?: boolean; maskInputOptions?: MaskInputOptions; maskInputFn?: MaskInputFn; maskTextFn?: MaskTextFn; slimDOMOptions?: SlimDOMOptions | "all" | true; ignoreCSSAttributes?: Set; inlineStylesheet?: boolean; hooks?: hooksParam; packFn?: PackFn; sampling?: SamplingStrategy; dataURLOptions?: DataURLOptions; recordDOM?: boolean; recordCanvas?: boolean; recordCrossOriginIframes?: boolean; recordAfter?: "DOMContentLoaded" | "load"; userTriggeredOnInput?: boolean; collectFonts?: boolean; inlineImages?: boolean; plugins?: RecordPlugin[]; mousemoveWait?: number; keepIframeSrcFn?: KeepIframeSrcFn; errorHandler?: ErrorHandler; } /** rrweb record function type */ export interface RRWebRecord { (options: RecordOptions): () => void; addCustomEvent: (tag: string, payload: unknown) => void; takeFullSnapshot: () => void; mirror: { getId(n: Node | undefined | null): number; getNode(id: number): Node | null; }; } /** Canvas recording configuration */ export interface CanvasRecordingConfig { enabled: boolean; fps: number; quality: number; } /** Network payload capture configuration */ export interface NetworkPayloadCaptureConfig { recordHeaders?: boolean; recordBody?: boolean; recordPerformance?: boolean; } /** Masking configuration */ export interface MaskingConfig { maskAllInputs?: boolean; maskTextSelector?: string; blockSelector?: string; } /** Session recording configuration */ export interface SessionRecordingConfig { /** Enable session recording */ enabled?: boolean; /** Sample rate (0-1, where 1 = 100%) */ sampleRate?: number; /** Minimum session duration in ms before sending */ minimumDurationMs?: number; /** Session idle threshold in ms */ sessionIdleThresholdMs?: number; /** Full snapshot interval in ms */ fullSnapshotIntervalMs?: number; /** Enable console log capture */ captureConsole?: boolean; /** Enable network request capture */ captureNetwork?: boolean; /** Canvas recording settings */ captureCanvas?: { recordCanvas?: boolean; canvasFps?: number; canvasQuality?: number; }; /** Masking settings */ masking?: MaskingConfig; /** Block class for elements to hide */ blockClass?: string; /** Block selector for elements to hide */ blockSelector?: string; /** * When `true`, do not merge built-in selectors for off-screen / template DOM * (`.sr-only`, Webflow `w-condition-invisible`, etc.). Default `false`. */ skipDefaultInvisibleBlocking?: boolean; /** Ignore class for input masking */ ignoreClass?: string; /** Mask text class */ maskTextClass?: string; /** Mask text selector */ maskTextSelector?: string; /** Mask all inputs */ maskAllInputs?: boolean; /** Mask input options */ maskInputOptions?: MaskInputOptions; /** Record headers in network requests */ recordHeaders?: boolean; /** Record body in network requests */ recordBody?: boolean; /** Gzip-compress the request body before sending (transport-level) */ compressEvents?: boolean; /** Internal: Mutation throttler refill rate */ __mutationThrottlerRefillRate?: number; /** Internal: Mutation throttler bucket size */ __mutationThrottlerBucketSize?: number; } /** Recording status values */ export type SessionRecordingStatus = "disabled" | "buffering" | "active" | "paused" | "sampled" | "trigger_pending"; /** Recording start reason */ export type SessionStartReason = "recording_initialized" | "session_id_changed" | "linked_flag_matched" | "linked_flag_overridden" | "sampling_overridden" | "url_trigger_matched" | "event_trigger_matched" | "sampled" | "config_updated" | "remote_config"; /** Trigger type for starting recording */ export type TriggerType = "url" | "event"; /** Buffer for snapshot events */ export interface SnapshotBuffer { size: number; data: eventWithTime[]; sessionId: string; windowId: string; /** Distinct id at the time events were appended (not live at send). */ distinctId: string; } /** Remote configuration for session recording */ export interface SessionRecordingRemoteConfig { enabled?: boolean; endpoint?: string; sampleRate?: string; minimumDurationMilliseconds?: number; consoleLogRecordingEnabled?: boolean; networkPayloadCapture?: { recordHeaders?: boolean; recordBody?: boolean; capturePerformance?: boolean; }; masking?: MaskingConfig; recordCanvas?: boolean; canvasFps?: number; canvasQuality?: number; scriptConfig?: { script?: string; }; triggerMatchType?: "any" | "all"; urlTriggers?: Array<{ url: string; matching: "regex" | "exact" | "contains"; }>; urlBlocklist?: Array<{ url: string; matching: "regex" | "exact" | "contains"; }>; eventTriggers?: string[]; } /** Queued rrweb method call */ export interface QueuedRRWebEvent { rrwebMethod: () => void; attempt: number; enqueuedAt: number; }