@hangarx/helix-node
Version:
Helix Analytics Node.js SDK for server-side event tracking with enhanced business intelligence capabilities
219 lines • 6.84 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Analytics = exports.HelixAnalytics = void 0;
const axios_1 = __importDefault(require("axios"));
const uuid_1 = require("uuid");
class HelixAnalytics {
constructor(config) {
this.queue = [];
this.apiKey = config.apiKey;
this.batchSize = config.batchSize || 100;
this.flushInterval = config.flushInterval || 10000; // 10 seconds
this.maxRetries = config.maxRetries || 3;
this.debug = config.debug || false;
this.client = axios_1.default.create({
baseURL: config.endpoint || 'https://api.helix.js/v1',
timeout: config.timeout || 30000,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
'User-Agent': '@helix/analytics-node/1.0.0'
}
});
this.startBatchProcessor();
this.setupGracefulShutdown();
}
/**
* Track an event
*/
async track(userId, event, properties) {
const analyticsEvent = {
type: 'track',
userId,
event,
properties: properties || {},
timestamp: new Date().toISOString(),
context: this.getContext()
};
this.enqueue(analyticsEvent);
}
/**
* Identify a user
*/
async identify(userId, traits) {
const analyticsEvent = {
type: 'identify',
userId,
traits: traits || {},
timestamp: new Date().toISOString(),
context: this.getContext()
};
this.enqueue(analyticsEvent);
}
/**
* Track a page view
*/
async page(userId, name, properties) {
const analyticsEvent = {
type: 'page',
userId,
event: name || 'Page View',
properties: {
...properties,
name: name || 'Page View'
},
timestamp: new Date().toISOString(),
context: this.getContext()
};
this.enqueue(analyticsEvent);
}
/**
* Track a screen view (for mobile apps)
*/
async screen(userId, name, properties) {
const analyticsEvent = {
type: 'screen',
userId,
event: name || 'Screen View',
properties: {
...properties,
name: name || 'Screen View'
},
timestamp: new Date().toISOString(),
context: this.getContext()
};
this.enqueue(analyticsEvent);
}
/**
* Manually flush the queue
*/
async flush() {
if (this.queue.length === 0) {
if (this.debug) {
console.log('Helix: Queue is empty, nothing to flush');
}
return;
}
const events = this.queue.splice(0, this.batchSize);
try {
await this.sendBatch(events);
if (this.debug) {
console.log(`Helix: Successfully flushed ${events.length} events`);
}
}
catch (error) {
// Re-queue events on failure
this.queue.unshift(...events);
if (this.debug) {
console.error('Helix: Failed to flush events', error);
}
throw error;
}
}
/**
* Get current queue size
*/
getQueueSize() {
return this.queue.length;
}
/**
* Shutdown the client gracefully
*/
async shutdown() {
if (this.flushTimer) {
clearInterval(this.flushTimer);
}
// Flush remaining events
await this.flush();
if (this.debug) {
console.log('Helix: Client shutdown complete');
}
}
enqueue(event) {
// Add session ID if not present
if (!event.sessionId) {
event.sessionId = this.generateSessionId();
}
this.queue.push(event);
if (this.debug) {
console.log('Helix: Enqueued event', { type: event.type, event: event.event, userId: event.userId });
}
// Auto-flush if batch size reached
if (this.queue.length >= this.batchSize) {
this.flush().catch(error => {
if (this.debug) {
console.error('Helix: Auto-flush failed', error);
}
});
}
}
async sendBatch(events) {
let lastError;
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
try {
const response = await this.client.post('/batch', {
events
});
if (response.data.success) {
return;
}
else {
throw new Error(response.data.error || 'Batch request failed');
}
}
catch (error) {
lastError = error;
if (attempt < this.maxRetries - 1) {
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await this.sleep(delay);
if (this.debug) {
console.log(`Helix: Retry attempt ${attempt + 1} after ${delay}ms`);
}
}
}
}
throw lastError;
}
startBatchProcessor() {
this.flushTimer = setInterval(() => {
this.flush().catch(error => {
if (this.debug) {
console.error('Helix: Scheduled flush failed', error);
}
});
}, this.flushInterval);
}
setupGracefulShutdown() {
const shutdown = () => {
this.shutdown().catch(error => {
console.error('Helix: Shutdown error', error);
});
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
process.on('beforeExit', shutdown);
}
getContext() {
return {
library: {
name: '@helix/analytics-node',
version: '1.0.0'
},
userAgent: process.env.npm_config_user_agent || 'Node.js'
};
}
generateSessionId() {
return `sess_node_${(0, uuid_1.v4)().replace(/-/g, '')}_${Date.now()}`;
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
exports.HelixAnalytics = HelixAnalytics;
exports.Analytics = HelixAnalytics;
// Export for CommonJS compatibility
exports.default = HelixAnalytics;
//# sourceMappingURL=index.js.map