userlens-session-recorder 2.0.2 → 2.2.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.
@@ -0,0 +1,61 @@
1
+ export type SessionChange = "none" | "expired" | "rotated";
2
+ /**
3
+ * Owns the (session_uuid, window_id, chunk_seq, last_active) lifecycle.
4
+ *
5
+ * Two storage scopes:
6
+ * - shared (localStorage): session_uuid + last_active — visible to every tab
7
+ * of the same origin so tabs can adopt one logical session and a single
8
+ * idle timeout governs the whole user.
9
+ * - per-tab (sessionStorage): window_id + chunk_seq — independent per tab so
10
+ * concurrent tabs can upload chunks without colliding on chunk_seq.
11
+ *
12
+ * The recorder talks to this class instead of touching storage directly.
13
+ */
14
+ export declare class SessionManager {
15
+ #private;
16
+ private readonly timeoutMs;
17
+ private _sessionUuid;
18
+ private _windowId;
19
+ constructor(timeoutMs: number);
20
+ initialize(): void;
21
+ get sessionUuid(): string;
22
+ get windowId(): string;
23
+ /**
24
+ * Reconciles in-memory session_uuid with whatever shared storage says.
25
+ * Called on every event so cross-tab session changes are picked up quickly.
26
+ *
27
+ * Returns:
28
+ * "expired" — shared session has been idle past timeout; we rotated.
29
+ * "rotated" — another tab rotated the session_uuid; we adopted it.
30
+ * "none" — no change, business as usual.
31
+ *
32
+ * Caller takes a fresh full snapshot on "expired" or "rotated" so this
33
+ * window's first chunk in the new session is replayable on its own.
34
+ */
35
+ syncWithSharedState(now: number): SessionChange;
36
+ /** Bump shared last_active. Call only on real user interactions. */
37
+ bumpActivity(now: number): void;
38
+ /** Read this window's current chunk_seq for a pending upload. */
39
+ currentChunkSeq(): number | null;
40
+ /**
41
+ * Mark a chunk_seq as committed after a successful upload. No-ops if the
42
+ * stored seq has moved on (e.g. a session rotation reset it to 0 mid-flight).
43
+ */
44
+ commitChunkSeq(uploadedSeq: number): void;
45
+ /**
46
+ * Reserve and return the current chunk_seq for a pagehide flush, advancing
47
+ * storage so the next normal upload uses seq+1. Returns null if window state
48
+ * is missing.
49
+ */
50
+ reserveChunkSeq(): number | null;
51
+ /** Hard reset: wipe shared session and start a fresh one. */
52
+ reset(): void;
53
+ /**
54
+ * Called from pagehide. Lets a future reload of the same tab reuse the
55
+ * window_id (because the flag is gone), while a cloned tab still sees the
56
+ * flag set in its inherited sessionStorage and treats itself as a duplicate.
57
+ */
58
+ notifyPageHide(): void;
59
+ /** Full teardown — call on stop(). */
60
+ dispose(): void;
61
+ }
@@ -0,0 +1,10 @@
1
+ import type { SharedSessionState, WindowState } from "./types";
2
+ export declare function readSharedSessionState(): SharedSessionState | null;
3
+ export declare function writeSharedSessionState(state: SharedSessionState): void;
4
+ export declare function clearSharedSessionState(): void;
5
+ export declare function readWindowState(): WindowState | null;
6
+ export declare function writeWindowState(state: WindowState): void;
7
+ export declare function clearWindowState(): void;
8
+ export declare function wasPrimaryWindowFlagAlreadySet(): boolean;
9
+ export declare function markPrimaryWindow(): void;
10
+ export declare function clearPrimaryWindowFlag(): void;
@@ -1,24 +1,47 @@
1
+ import { eventWithTime } from 'rrweb';
2
+
1
3
  type MaskingOption = "passwords" | "all";
4
+ type RecorderMode = "auto" | "manual";
2
5
  interface SessionRecordingOptions {
3
6
  TIMEOUT?: number;
4
7
  BUFFER_SIZE?: number;
5
8
  maskingOptions?: MaskingOption[];
6
9
  recordCrossOriginIframes?: boolean;
7
10
  }
8
- interface SessionRecorderConfig {
11
+ interface EventBatch {
12
+ session_uuid: string;
13
+ window_id: string;
14
+ chunk_seq: number;
15
+ chunk_start_ts: string;
16
+ chunk_end_ts: string;
17
+ events: eventWithTime[];
18
+ keepalive?: boolean;
19
+ }
20
+ type OnEventsCallback = (batch: EventBatch) => void | Promise<void>;
21
+ interface AutoModeConfig {
22
+ mode?: "auto";
9
23
  WRITE_CODE: string;
10
24
  userId: string;
11
25
  recordingOptions?: SessionRecordingOptions;
12
26
  debug?: boolean;
13
27
  }
28
+ interface ManualModeConfig {
29
+ mode: "manual";
30
+ onEvents: OnEventsCallback;
31
+ recordingOptions?: SessionRecordingOptions;
32
+ debug?: boolean;
33
+ }
34
+ type SessionRecorderConfig = AutoModeConfig | ManualModeConfig;
14
35
 
15
36
  declare class SessionRecorder {
16
37
  #private;
38
+ private mode;
17
39
  private userId?;
40
+ private onEvents?;
18
41
  private TIMEOUT;
19
42
  private BUFFER_SIZE;
20
43
  private maskingOptions;
21
- private sessionUuid;
44
+ private sessionManager;
22
45
  private sessionEvents;
23
46
  private bufferBytes;
24
47
  private rrwebStop;
@@ -30,4 +53,4 @@ declare class SessionRecorder {
30
53
  }
31
54
 
32
55
  export { SessionRecorder as default };
33
- export type { MaskingOption, SessionRecorderConfig };
56
+ export type { AutoModeConfig, EventBatch, ManualModeConfig, MaskingOption, OnEventsCallback, RecorderMode, SessionRecorderConfig };