@trynova-ai/shadow-js
Version:
A TypeScript library for user session tracking.
125 lines (124 loc) • 4.19 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Shadow = void 0;
const uuid_1 = require("uuid");
const browser_1 = require("./plugins/browser");
class Shadow {
constructor(options) {
var _a;
this.eventBuffer = [];
this.url = options.url;
this.headers = options.headers || {};
this.sessionId = options.sessionProvider ? options.sessionProvider() : this.getStoredSessionId();
this.plugins = options.plugins || [new browser_1.BrowserPlugin()];
this.bufferConfig = options.buffer || { enabled: false };
const sampleRate = (_a = options.sampleRate) !== null && _a !== void 0 ? _a : 0.1; // Default to 10% if not provided
this.isClientEnabled = Math.random() < sampleRate;
if (this.isClientEnabled && this.bufferConfig.enabled) {
try {
this.startFlushInterval();
}
catch (error) {
console.error('Error starting flush interval:', error);
}
}
if (this.isClientEnabled) {
try {
this.setupPlugins();
}
catch (error) {
console.error('Error setting up plugins:', error);
}
}
}
static init(options) {
try {
return new Shadow(options);
}
catch (error) {
console.error('Error initializing Shadow:', error);
throw error; // re-throw if needed
}
}
getStoredSessionId() {
try {
let sessionId = localStorage.getItem('session-id');
if (!sessionId) {
sessionId = (0, uuid_1.v4)();
localStorage.setItem('session-id', sessionId);
}
return sessionId;
}
catch (error) {
console.error('Error getting or storing session ID:', error);
return (0, uuid_1.v4)(); // fallback to a new UUID if there's an issue
}
}
setupPlugins() {
this.plugins.forEach(plugin => plugin.setup(this));
}
capture(event) {
if (!this.isClientEnabled)
return;
try {
const payload = Object.assign(Object.assign({}, event), { sessionId: this.sessionId });
if (this.bufferConfig.enabled) {
this.eventBuffer.push(payload);
if (this.eventBuffer.length >= (this.bufferConfig.maxEvents || 10)) {
this.flushEvents();
}
}
else {
this.sendEvent(this.url + '/session', payload);
}
}
catch (error) {
console.error('Error capturing event:', error);
}
}
flushEvents() {
try {
if (this.eventBuffer.length > 0) {
const bulkPayload = [...this.eventBuffer];
this.eventBuffer = [];
this.sendEvent(this.url + '/sessions', bulkPayload);
}
}
catch (error) {
console.error('Error flushing events:', error);
}
}
startFlushInterval() {
try {
this.flushTimeout = setInterval(() => {
this.flushEvents();
}, this.bufferConfig.flushInterval || 5000);
}
catch (error) {
console.error('Error starting flush interval:', error);
}
}
sendEvent(endpoint, payload) {
try {
const headers = Object.assign(Object.assign({}, this.headers), { 'Content-Type': 'application/json' });
fetch(endpoint, {
method: 'POST',
headers: headers,
body: JSON.stringify(payload),
keepalive: true
}).catch(error => console.error('Error sending session events:', error));
}
catch (error) {
console.error('Error in sendEvent:', error);
}
}
stopFlushInterval() {
try {
clearInterval(this.flushTimeout);
}
catch (error) {
console.error('Error stopping flush interval:', error);
}
}
}
exports.Shadow = Shadow;