@tamsensedev/dataclient 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -75,7 +75,10 @@ interface ExcludeEvent {
75
75
  interface RrwebEvent {
76
76
  event: 'rrweb';
77
77
  timestamp: string;
78
- rrwebEvent: unknown;
78
+ rrwebEvent: {
79
+ type: number;
80
+ [key: string]: unknown;
81
+ };
79
82
  }
80
83
  type SceneEvent = SnapshotEvent | MutationEvent | ActionEvent | RrwebEvent | IdentifyEvent | ExcludeEvent;
81
84
  interface Config {
@@ -84,6 +87,7 @@ interface Config {
84
87
  batchSize: number;
85
88
  flushInterval: number;
86
89
  checkpointInterval: number;
90
+ idleTimeout: number;
87
91
  mutationDebounce: number;
88
92
  inputDebounce: number;
89
93
  sessionIdKey: string;
@@ -115,10 +119,16 @@ declare class DataClient {
115
119
  private sender;
116
120
  private trackers;
117
121
  private config;
122
+ private deviceId;
123
+ private idleTimer;
124
+ private userId;
118
125
  constructor(options?: Partial<Config>);
119
126
  setUser(userId: string): void;
120
127
  excludeSession(reason?: string): void;
121
- destroy(): void;
128
+ private onActivity;
129
+ private resetIdleTimer;
130
+ private startSession;
131
+ private stopSession;
122
132
  }
123
133
 
124
134
  export { type ActionEvent, type AttrChange, type Config, DataClient, type ExcludeEvent, type IdentifyEvent, type MutationAdd, type MutationEvent, type Rect, type RrwebEvent, type SceneBatch, type SceneEvent, type SerializedNode, type SnapshotEvent, type TextChange, type Tracker, type Viewport };
@@ -13114,7 +13114,7 @@ var dataclient = (() => {
13114
13114
  flushPromise = Promise.resolve();
13115
13115
  add(event) {
13116
13116
  this.queue.push(event);
13117
- const isRrwebSnapshot = event.event === "rrweb" && event.rrwebEvent?.type === 2;
13117
+ const isRrwebSnapshot = event.event === "rrweb" && event.rrwebEvent.type === 2;
13118
13118
  if (isRrwebSnapshot || this.queue.length >= this.batchSize) {
13119
13119
  this.flush();
13120
13120
  }
@@ -13123,7 +13123,8 @@ var dataclient = (() => {
13123
13123
  this.flushPromise = this.flushPromise.then(() => this.doFlush());
13124
13124
  }
13125
13125
  flushSync() {
13126
- if (this.queue.length === 0) return;
13126
+ if (this.queue.length === 0)
13127
+ return;
13127
13128
  const events = this.queue.splice(0);
13128
13129
  const url = this.buildUrl();
13129
13130
  let chunk = [];
@@ -13149,7 +13150,8 @@ var dataclient = (() => {
13149
13150
  this.flushSync();
13150
13151
  }
13151
13152
  async doFlush() {
13152
- if (this.queue.length === 0) return;
13153
+ if (this.queue.length === 0)
13154
+ return;
13153
13155
  const events = this.queue.splice(0);
13154
13156
  const batch = this.buildBatch(events);
13155
13157
  const json = JSON.stringify(batch);
@@ -13192,7 +13194,8 @@ var dataclient = (() => {
13192
13194
  headers: { "Content-Type": "application/json" },
13193
13195
  body: json
13194
13196
  });
13195
- if (response.ok) return true;
13197
+ if (response.ok)
13198
+ return true;
13196
13199
  } catch {
13197
13200
  }
13198
13201
  if (attempt < MAX_RETRIES) {
@@ -13210,6 +13213,7 @@ var dataclient = (() => {
13210
13213
  batchSize: 5,
13211
13214
  flushInterval: 5e3,
13212
13215
  checkpointInterval: 3e4,
13216
+ idleTimeout: 60 * 60 * 1e3,
13213
13217
  mutationDebounce: 200,
13214
13218
  inputDebounce: 1e3,
13215
13219
  sessionIdKey: "sc2_sid",
@@ -13217,19 +13221,47 @@ var dataclient = (() => {
13217
13221
  apiKey: ""
13218
13222
  };
13219
13223
  var DataClient = class {
13220
- sender;
13224
+ sender = null;
13221
13225
  trackers = [];
13222
13226
  config;
13227
+ deviceId;
13228
+ idleTimer = null;
13229
+ userId = null;
13223
13230
  constructor(options) {
13224
13231
  this.config = { ...defaults, ...options };
13232
+ this.deviceId = getDeviceId(this.config.deviceIdKey);
13233
+ this.startSession();
13234
+ document.addEventListener("click", () => this.onActivity(), true);
13235
+ document.addEventListener("input", () => this.onActivity(), true);
13236
+ document.addEventListener("change", () => this.onActivity(), true);
13237
+ }
13238
+ setUser(userId) {
13239
+ this.userId = userId;
13240
+ this.sender?.add({ event: "identify", timestamp: (/* @__PURE__ */ new Date()).toISOString(), user_id: userId });
13241
+ }
13242
+ excludeSession(reason = "") {
13243
+ this.sender?.add({ event: "exclude", timestamp: (/* @__PURE__ */ new Date()).toISOString(), reason });
13244
+ this.stopSession();
13245
+ }
13246
+ onActivity() {
13247
+ if (!this.sender) {
13248
+ this.startSession();
13249
+ }
13250
+ this.resetIdleTimer();
13251
+ }
13252
+ resetIdleTimer() {
13253
+ if (this.idleTimer)
13254
+ clearTimeout(this.idleTimer);
13255
+ this.idleTimer = setTimeout(() => this.stopSession(), this.config.idleTimeout);
13256
+ }
13257
+ startSession() {
13225
13258
  const sessionId = generateId();
13226
- const deviceId = getDeviceId(this.config.deviceIdKey);
13227
13259
  this.sender = new Sender(
13228
13260
  this.config.endpoint,
13229
13261
  this.config.apiKey,
13230
13262
  this.config.batchSize,
13231
13263
  sessionId,
13232
- deviceId,
13264
+ this.deviceId,
13233
13265
  this.config.flushInterval
13234
13266
  );
13235
13267
  const snapshotTracker = new SnapshotTracker(this.config, this.sender);
@@ -13238,26 +13270,37 @@ var dataclient = (() => {
13238
13270
  const rrwebTracker = new RrwebTracker(this.config, this.sender);
13239
13271
  this.trackers = [snapshotTracker, mutationTracker, actionTracker, rrwebTracker];
13240
13272
  this.trackers.forEach((t) => t.start());
13273
+ if (this.userId) {
13274
+ this.sender.add({ event: "identify", timestamp: (/* @__PURE__ */ new Date()).toISOString(), user_id: this.userId });
13275
+ }
13276
+ this.resetIdleTimer();
13241
13277
  const onLeave = () => {
13242
13278
  this.trackers.forEach((t) => t.beforeUnload?.());
13243
- this.sender.flushSync();
13279
+ this.sender?.flushSync();
13244
13280
  };
13245
13281
  document.addEventListener("visibilitychange", () => {
13246
- if (document.visibilityState === "hidden") onLeave();
13282
+ if (document.visibilityState === "hidden")
13283
+ onLeave();
13247
13284
  });
13248
13285
  window.addEventListener("pagehide", onLeave);
13286
+ if (this.config.debug) {
13287
+ console.log(`[dataclient] Session started: ${sessionId}`);
13288
+ }
13249
13289
  }
13250
- setUser(userId) {
13251
- this.sender.add({ event: "identify", timestamp: (/* @__PURE__ */ new Date()).toISOString(), user_id: userId });
13252
- }
13253
- excludeSession(reason = "") {
13254
- this.sender.add({ event: "exclude", timestamp: (/* @__PURE__ */ new Date()).toISOString(), reason });
13255
- this.destroy();
13256
- }
13257
- destroy() {
13290
+ stopSession() {
13291
+ if (this.idleTimer) {
13292
+ clearTimeout(this.idleTimer);
13293
+ this.idleTimer = null;
13294
+ }
13258
13295
  this.trackers.forEach((t) => t.stop());
13259
13296
  this.trackers = [];
13260
- this.sender.destroy();
13297
+ if (this.sender) {
13298
+ this.sender.destroy();
13299
+ this.sender = null;
13300
+ }
13301
+ if (this.config.debug) {
13302
+ console.log("[dataclient] Session stopped (idle timeout)");
13303
+ }
13261
13304
  }
13262
13305
  };
13263
13306
  return __toCommonJS(index_exports);