@neroom/nevision 0.1.7 → 0.1.8
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.js +33 -56
- package/dist/index.mjs +33 -56
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
var import_react = require("react");
|
|
39
39
|
var DEFAULT_API_URL = "https://api.ne-room.io";
|
|
40
|
-
var CHUNK_INTERVAL =
|
|
40
|
+
var CHUNK_INTERVAL = 2e3;
|
|
41
41
|
var MAX_EVENTS_PER_CHUNK = 100;
|
|
42
42
|
var DB_NAME = "nevision_recordings";
|
|
43
43
|
var STORE_NAME = "pending_events";
|
|
@@ -173,7 +173,6 @@ function NevisionRecorder({
|
|
|
173
173
|
const recordConfig = {
|
|
174
174
|
emit: (event) => {
|
|
175
175
|
eventsBufferRef.current.push(event);
|
|
176
|
-
persistEventsToStorage();
|
|
177
176
|
},
|
|
178
177
|
sampling: currentSampling ? {
|
|
179
178
|
mousemove: currentSampling.mousemove,
|
|
@@ -211,44 +210,30 @@ function NevisionRecorder({
|
|
|
211
210
|
endSession(apiUrl, sessionIdRef.current);
|
|
212
211
|
}
|
|
213
212
|
};
|
|
214
|
-
|
|
213
|
+
const handleVisibilityChange = () => {
|
|
215
214
|
if (document.visibilityState === "hidden") {
|
|
216
215
|
handleFinalSync(false);
|
|
217
216
|
}
|
|
218
|
-
}
|
|
219
|
-
|
|
217
|
+
};
|
|
218
|
+
const handleBeforeUnload = () => {
|
|
220
219
|
handleFinalSync(true);
|
|
221
|
-
}
|
|
222
|
-
|
|
220
|
+
};
|
|
221
|
+
const handlePageHide = (e) => {
|
|
223
222
|
handleFinalSync(!e.persisted);
|
|
224
|
-
}
|
|
223
|
+
};
|
|
224
|
+
const handleWindowBlur = () => {
|
|
225
|
+
if (eventsBufferRef.current.length > 0 && sessionIdRef.current) {
|
|
226
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
230
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
231
|
+
window.addEventListener("pagehide", handlePageHide);
|
|
232
|
+
window.addEventListener("blur", handleWindowBlur);
|
|
225
233
|
} catch (error) {
|
|
226
234
|
onErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
|
|
227
235
|
}
|
|
228
236
|
};
|
|
229
|
-
let persistTimeout = null;
|
|
230
|
-
const persistEventsToStorage = () => {
|
|
231
|
-
if (persistTimeout) return;
|
|
232
|
-
persistTimeout = setTimeout(async () => {
|
|
233
|
-
persistTimeout = null;
|
|
234
|
-
if (!sessionIdRef.current || !eventStoreRef.current) return;
|
|
235
|
-
if (eventsBufferRef.current.length === 0) return;
|
|
236
|
-
const events = [...eventsBufferRef.current];
|
|
237
|
-
const chunkId = `${sessionIdRef.current}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
238
|
-
try {
|
|
239
|
-
await eventStoreRef.current.saveChunk({
|
|
240
|
-
id: chunkId,
|
|
241
|
-
sessionId: sessionIdRef.current,
|
|
242
|
-
siteId,
|
|
243
|
-
apiKey,
|
|
244
|
-
events,
|
|
245
|
-
chunkIndex: chunkIndexRef.current,
|
|
246
|
-
timestamp: Date.now()
|
|
247
|
-
});
|
|
248
|
-
} catch {
|
|
249
|
-
}
|
|
250
|
-
}, 1e3);
|
|
251
|
-
};
|
|
252
237
|
const retrySendPendingChunks = async (url) => {
|
|
253
238
|
if (!eventStoreRef.current) return;
|
|
254
239
|
try {
|
|
@@ -277,23 +262,8 @@ function NevisionRecorder({
|
|
|
277
262
|
};
|
|
278
263
|
const sendChunk = async (url, sessionId, isBeacon = false) => {
|
|
279
264
|
if (eventsBufferRef.current.length === 0) return;
|
|
280
|
-
const events = eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
265
|
+
const events = isBeacon ? eventsBufferRef.current.splice(0) : eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
281
266
|
const chunkIndex = chunkIndexRef.current++;
|
|
282
|
-
const chunkId = `${sessionId}_${chunkIndex}_${Date.now()}`;
|
|
283
|
-
if (eventStoreRef.current) {
|
|
284
|
-
try {
|
|
285
|
-
await eventStoreRef.current.saveChunk({
|
|
286
|
-
id: chunkId,
|
|
287
|
-
sessionId,
|
|
288
|
-
siteId,
|
|
289
|
-
apiKey,
|
|
290
|
-
events,
|
|
291
|
-
chunkIndex,
|
|
292
|
-
timestamp: Date.now()
|
|
293
|
-
});
|
|
294
|
-
} catch {
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
267
|
const payload = JSON.stringify({
|
|
298
268
|
sessionId,
|
|
299
269
|
siteId,
|
|
@@ -302,15 +272,26 @@ function NevisionRecorder({
|
|
|
302
272
|
chunkIndex
|
|
303
273
|
});
|
|
304
274
|
if (isBeacon && navigator.sendBeacon) {
|
|
305
|
-
|
|
275
|
+
navigator.sendBeacon(
|
|
306
276
|
`${url}/public/recordings/chunk`,
|
|
307
277
|
new Blob([payload], { type: "application/json" })
|
|
308
278
|
);
|
|
309
|
-
if (sent && eventStoreRef.current) {
|
|
310
|
-
eventStoreRef.current.deleteChunk(chunkId).catch(() => {
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
279
|
} else {
|
|
280
|
+
const chunkId = `${sessionId}_${chunkIndex}_${Date.now()}`;
|
|
281
|
+
if (eventStoreRef.current) {
|
|
282
|
+
try {
|
|
283
|
+
await eventStoreRef.current.saveChunk({
|
|
284
|
+
id: chunkId,
|
|
285
|
+
sessionId,
|
|
286
|
+
siteId,
|
|
287
|
+
apiKey,
|
|
288
|
+
events,
|
|
289
|
+
chunkIndex,
|
|
290
|
+
timestamp: Date.now()
|
|
291
|
+
});
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
}
|
|
314
295
|
try {
|
|
315
296
|
const response = await fetch(`${url}/public/recordings/chunk`, {
|
|
316
297
|
method: "POST",
|
|
@@ -339,10 +320,6 @@ function NevisionRecorder({
|
|
|
339
320
|
isActive = false;
|
|
340
321
|
clearInterval(intervalId);
|
|
341
322
|
stopFnRef.current?.();
|
|
342
|
-
if (sessionIdRef.current) {
|
|
343
|
-
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
344
|
-
endSession(apiUrl, sessionIdRef.current);
|
|
345
|
-
}
|
|
346
323
|
sessionIdRef.current = null;
|
|
347
324
|
chunkIndexRef.current = 0;
|
|
348
325
|
eventsBufferRef.current = [];
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.tsx
|
|
4
4
|
import { useEffect, useRef } from "react";
|
|
5
5
|
var DEFAULT_API_URL = "https://api.ne-room.io";
|
|
6
|
-
var CHUNK_INTERVAL =
|
|
6
|
+
var CHUNK_INTERVAL = 2e3;
|
|
7
7
|
var MAX_EVENTS_PER_CHUNK = 100;
|
|
8
8
|
var DB_NAME = "nevision_recordings";
|
|
9
9
|
var STORE_NAME = "pending_events";
|
|
@@ -139,7 +139,6 @@ function NevisionRecorder({
|
|
|
139
139
|
const recordConfig = {
|
|
140
140
|
emit: (event) => {
|
|
141
141
|
eventsBufferRef.current.push(event);
|
|
142
|
-
persistEventsToStorage();
|
|
143
142
|
},
|
|
144
143
|
sampling: currentSampling ? {
|
|
145
144
|
mousemove: currentSampling.mousemove,
|
|
@@ -177,44 +176,30 @@ function NevisionRecorder({
|
|
|
177
176
|
endSession(apiUrl, sessionIdRef.current);
|
|
178
177
|
}
|
|
179
178
|
};
|
|
180
|
-
|
|
179
|
+
const handleVisibilityChange = () => {
|
|
181
180
|
if (document.visibilityState === "hidden") {
|
|
182
181
|
handleFinalSync(false);
|
|
183
182
|
}
|
|
184
|
-
}
|
|
185
|
-
|
|
183
|
+
};
|
|
184
|
+
const handleBeforeUnload = () => {
|
|
186
185
|
handleFinalSync(true);
|
|
187
|
-
}
|
|
188
|
-
|
|
186
|
+
};
|
|
187
|
+
const handlePageHide = (e) => {
|
|
189
188
|
handleFinalSync(!e.persisted);
|
|
190
|
-
}
|
|
189
|
+
};
|
|
190
|
+
const handleWindowBlur = () => {
|
|
191
|
+
if (eventsBufferRef.current.length > 0 && sessionIdRef.current) {
|
|
192
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
196
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
197
|
+
window.addEventListener("pagehide", handlePageHide);
|
|
198
|
+
window.addEventListener("blur", handleWindowBlur);
|
|
191
199
|
} catch (error) {
|
|
192
200
|
onErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
|
|
193
201
|
}
|
|
194
202
|
};
|
|
195
|
-
let persistTimeout = null;
|
|
196
|
-
const persistEventsToStorage = () => {
|
|
197
|
-
if (persistTimeout) return;
|
|
198
|
-
persistTimeout = setTimeout(async () => {
|
|
199
|
-
persistTimeout = null;
|
|
200
|
-
if (!sessionIdRef.current || !eventStoreRef.current) return;
|
|
201
|
-
if (eventsBufferRef.current.length === 0) return;
|
|
202
|
-
const events = [...eventsBufferRef.current];
|
|
203
|
-
const chunkId = `${sessionIdRef.current}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
204
|
-
try {
|
|
205
|
-
await eventStoreRef.current.saveChunk({
|
|
206
|
-
id: chunkId,
|
|
207
|
-
sessionId: sessionIdRef.current,
|
|
208
|
-
siteId,
|
|
209
|
-
apiKey,
|
|
210
|
-
events,
|
|
211
|
-
chunkIndex: chunkIndexRef.current,
|
|
212
|
-
timestamp: Date.now()
|
|
213
|
-
});
|
|
214
|
-
} catch {
|
|
215
|
-
}
|
|
216
|
-
}, 1e3);
|
|
217
|
-
};
|
|
218
203
|
const retrySendPendingChunks = async (url) => {
|
|
219
204
|
if (!eventStoreRef.current) return;
|
|
220
205
|
try {
|
|
@@ -243,23 +228,8 @@ function NevisionRecorder({
|
|
|
243
228
|
};
|
|
244
229
|
const sendChunk = async (url, sessionId, isBeacon = false) => {
|
|
245
230
|
if (eventsBufferRef.current.length === 0) return;
|
|
246
|
-
const events = eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
231
|
+
const events = isBeacon ? eventsBufferRef.current.splice(0) : eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
247
232
|
const chunkIndex = chunkIndexRef.current++;
|
|
248
|
-
const chunkId = `${sessionId}_${chunkIndex}_${Date.now()}`;
|
|
249
|
-
if (eventStoreRef.current) {
|
|
250
|
-
try {
|
|
251
|
-
await eventStoreRef.current.saveChunk({
|
|
252
|
-
id: chunkId,
|
|
253
|
-
sessionId,
|
|
254
|
-
siteId,
|
|
255
|
-
apiKey,
|
|
256
|
-
events,
|
|
257
|
-
chunkIndex,
|
|
258
|
-
timestamp: Date.now()
|
|
259
|
-
});
|
|
260
|
-
} catch {
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
233
|
const payload = JSON.stringify({
|
|
264
234
|
sessionId,
|
|
265
235
|
siteId,
|
|
@@ -268,15 +238,26 @@ function NevisionRecorder({
|
|
|
268
238
|
chunkIndex
|
|
269
239
|
});
|
|
270
240
|
if (isBeacon && navigator.sendBeacon) {
|
|
271
|
-
|
|
241
|
+
navigator.sendBeacon(
|
|
272
242
|
`${url}/public/recordings/chunk`,
|
|
273
243
|
new Blob([payload], { type: "application/json" })
|
|
274
244
|
);
|
|
275
|
-
if (sent && eventStoreRef.current) {
|
|
276
|
-
eventStoreRef.current.deleteChunk(chunkId).catch(() => {
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
245
|
} else {
|
|
246
|
+
const chunkId = `${sessionId}_${chunkIndex}_${Date.now()}`;
|
|
247
|
+
if (eventStoreRef.current) {
|
|
248
|
+
try {
|
|
249
|
+
await eventStoreRef.current.saveChunk({
|
|
250
|
+
id: chunkId,
|
|
251
|
+
sessionId,
|
|
252
|
+
siteId,
|
|
253
|
+
apiKey,
|
|
254
|
+
events,
|
|
255
|
+
chunkIndex,
|
|
256
|
+
timestamp: Date.now()
|
|
257
|
+
});
|
|
258
|
+
} catch {
|
|
259
|
+
}
|
|
260
|
+
}
|
|
280
261
|
try {
|
|
281
262
|
const response = await fetch(`${url}/public/recordings/chunk`, {
|
|
282
263
|
method: "POST",
|
|
@@ -305,10 +286,6 @@ function NevisionRecorder({
|
|
|
305
286
|
isActive = false;
|
|
306
287
|
clearInterval(intervalId);
|
|
307
288
|
stopFnRef.current?.();
|
|
308
|
-
if (sessionIdRef.current) {
|
|
309
|
-
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
310
|
-
endSession(apiUrl, sessionIdRef.current);
|
|
311
|
-
}
|
|
312
289
|
sessionIdRef.current = null;
|
|
313
290
|
chunkIndexRef.current = 0;
|
|
314
291
|
eventsBufferRef.current = [];
|