UNPKG

@hangarx/helix-node

Version:

Helix Analytics Node.js SDK for server-side event tracking with enhanced business intelligence capabilities

219 lines 6.84 kB
"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