UNPKG

voiceai-sdk

Version:

Official SDK for SLNG.AI Voice API - Text-to-Speech, Speech-to-Text, and LLM services

148 lines (126 loc) 4.54 kB
#!/usr/bin/env node /** * Anonymous telemetry for SDK install tracking * Runs on postinstall to help improve the SDK * * Privacy: * - No personal information collected * - User agent hashed for anonymity * - Fails silently with no user impact * - Can be disabled with SLNG_DISABLE_TELEMETRY=1 */ const https = require('https'); const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); // Exit early if telemetry disabled if (process.env.SLNG_DISABLE_TELEMETRY === '1' || process.env.SLNG_DISABLE_TELEMETRY === 'true') { process.exit(0); } // Exit early in CI environments (common CI environment variables) const CI_VARS = ['CI', 'CONTINUOUS_INTEGRATION', 'BUILD_ID', 'GITHUB_ACTIONS', 'GITLAB_CI', 'TRAVIS', 'CIRCLECI']; if (CI_VARS.some(env => process.env[env])) { process.exit(0); } async function trackInstall() { try { // Get package version dynamically const packageJsonPath = path.join(__dirname, '..', 'package.json'); let version = '1.0.0'; // fallback try { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); version = packageJson.version || version; } catch (e) { // Use fallback version if package.json read fails } // Create project fingerprint from user agent and install path const userAgent = process.env.npm_config_user_agent || 'unknown'; const installPath = process.cwd(); const fingerprint = crypto .createHash('sha256') .update(userAgent + installPath) .digest('hex') .substring(0, 16); // Use first 16 chars for brevity // Check if this is a repeat install (simple file-based tracking) const telemetryDir = path.join(__dirname, '..', '.telemetry'); const installMarkerPath = path.join(telemetryDir, 'install.json'); let isFirstInstall = true; let previousInstalls = 0; let firstInstallDate = new Date().toISOString(); try { if (fs.existsSync(installMarkerPath)) { const installData = JSON.parse(fs.readFileSync(installMarkerPath, 'utf8')); isFirstInstall = false; previousInstalls = installData.count || 0; firstInstallDate = installData.firstInstall || firstInstallDate; } } catch (e) { // Treat as first install if marker file is corrupted } // Prepare telemetry payload const payload = { event: 'sdk_install', sdk_version: version, project_id: fingerprint, is_first_install: isFirstInstall, install_count: previousInstalls + 1, first_install_date: firstInstallDate, install_date: new Date().toISOString(), node_version: process.version, platform: process.platform, arch: process.arch, // Basic package manager detection package_manager: userAgent.includes('yarn') ? 'yarn' : userAgent.includes('pnpm') ? 'pnpm' : 'npm' }; // Send telemetry (non-blocking) const postData = JSON.stringify(payload); const options = { hostname: 'app.slng.ai', path: '/api/sdk-install', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData), 'User-Agent': `voiceai-sdk/${version}` }, timeout: 3000 // 3 second timeout }; const req = https.request(options, (res) => { // Consume response to prevent hanging res.on('data', () => {}); res.on('end', () => {}); }); req.on('error', () => { // Fail silently - don't impact user experience }); req.on('timeout', () => { req.destroy(); }); req.write(postData); req.end(); // Update install marker (create directory if needed) try { if (!fs.existsSync(telemetryDir)) { fs.mkdirSync(telemetryDir, { recursive: true }); } const installData = { count: previousInstalls + 1, firstInstall: firstInstallDate, lastInstall: new Date().toISOString(), version: version }; fs.writeFileSync(installMarkerPath, JSON.stringify(installData, null, 2)); } catch (e) { // Fail silently if we can't write marker file } } catch (error) { // Fail silently - telemetry should never break the user's workflow } } // Run telemetry with additional safety setTimeout(() => { trackInstall().catch(() => { // Final safety net - absolutely no errors should escape }); }, 100); // Small delay to ensure npm install completes