From 85583e6c5a6f45930160da8e366fa45190d734a0 Mon Sep 17 00:00:00 2001 From: Michael Latman Date: Wed, 4 Dec 2024 11:02:29 -0500 Subject: [PATCH] feat: implement user preferences for analytics consent and installation tracking - Added functions to manage user preferences for analytics, including reading and writing preferences to a JSON file. - Implemented a prompt to ask users for consent to share anonymous installation analytics. - Integrated analytics tracking into the package installation process, allowing for tracking of installations based on user consent. - Enhanced the overall user experience by providing options for analytics participation during package installation. These changes improve user engagement and provide valuable insights into package usage. --- src/utils/package-management.ts | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/utils/package-management.ts b/src/utils/package-management.ts index d9d0ff9..8c8c6e9 100644 --- a/src/utils/package-management.ts +++ b/src/utils/package-management.ts @@ -9,9 +9,84 @@ import path from 'path'; import fs from 'fs'; import { dirname } from 'path'; import { fileURLToPath } from 'url'; +import os from 'os'; + +declare function fetch(url: string, init?: any): Promise<{ ok: boolean; statusText: string }>; const execAsync = promisify(exec); +interface MCPPreferences { + allowAnalytics?: boolean; +} + +function getPreferencesPath(): string { + if (process.platform === 'win32') { + const appData = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'); + return path.join(appData, 'mcp-get', 'preferences.json'); + } + + // Unix-like systems (Linux, macOS) + const homeDir = os.homedir(); + return path.join(homeDir, '.mcp-get', 'preferences.json'); +} + +function readPreferences(): MCPPreferences { + const prefsPath = getPreferencesPath(); + if (!fs.existsSync(prefsPath)) { + return {}; + } + try { + return JSON.parse(fs.readFileSync(prefsPath, 'utf8')); + } catch (error) { + return {}; + } +} + +function writePreferences(prefs: MCPPreferences): void { + const prefsPath = getPreferencesPath(); + const prefsDir = path.dirname(prefsPath); + + if (!fs.existsSync(prefsDir)) { + fs.mkdirSync(prefsDir, { recursive: true }); + } + + fs.writeFileSync(prefsPath, JSON.stringify(prefs, null, 2)); +} + +async function checkAnalyticsConsent(): Promise { + const prefs = readPreferences(); + + if (typeof prefs.allowAnalytics === 'boolean') { + return prefs.allowAnalytics; + } + + const { allowAnalytics } = await inquirer.prompt<{ allowAnalytics: boolean }>([{ + type: 'confirm', + name: 'allowAnalytics', + message: 'Would you like to help improve mcp-get by sharing anonymous installation analytics?', + default: true + }]); + + writePreferences({ ...prefs, allowAnalytics }); + return allowAnalytics; +} + +async function trackInstallation(packageName: string): Promise { + try { + const response = await fetch(`https://mcp-get.com/api/packages/${packageName}/install`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + if (!response.ok) { + throw new Error(`Failed to track installation: ${response.statusText}`); + } + } catch (error) { + console.warn('Failed to track package installation'); + } +} + async function promptForEnvVars(packageName: string): Promise | undefined> { const helpers = packageHelpers[packageName]; if (!helpers?.requiredEnvVars) { @@ -171,6 +246,13 @@ export async function installPackage(pkg: Package): Promise { await installMCPServer(pkg.name, envVars, pkg.runtime); console.log('Updated Claude desktop configuration'); + + // Check analytics consent and track if allowed + const analyticsAllowed = await checkAnalyticsConsent(); + if (analyticsAllowed) { + await trackInstallation(pkg.name); + } + await promptForRestart(); } catch (error) { console.error('Failed to install package:', error);