mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-06 13:33:11 +00:00
chore: add pre-built dist folder for npx usage
This commit is contained in:
committed by
Romuald Członkowski
parent
a70d96a373
commit
5057481e70
289
dist/telemetry/config-manager.js
vendored
Normal file
289
dist/telemetry/config-manager.js
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TelemetryConfigManager = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const os_1 = require("os");
|
||||
const crypto_1 = require("crypto");
|
||||
const os_2 = require("os");
|
||||
class TelemetryConfigManager {
|
||||
constructor() {
|
||||
this.config = null;
|
||||
this.configDir = (0, path_1.join)((0, os_1.homedir)(), '.n8n-mcp');
|
||||
this.configPath = (0, path_1.join)(this.configDir, 'telemetry.json');
|
||||
}
|
||||
static getInstance() {
|
||||
if (!TelemetryConfigManager.instance) {
|
||||
TelemetryConfigManager.instance = new TelemetryConfigManager();
|
||||
}
|
||||
return TelemetryConfigManager.instance;
|
||||
}
|
||||
generateUserId() {
|
||||
if (process.env.IS_DOCKER === 'true' || this.isCloudEnvironment()) {
|
||||
return this.generateDockerStableId();
|
||||
}
|
||||
const machineId = `${(0, os_2.hostname)()}-${(0, os_2.platform)()}-${(0, os_2.arch)()}-${(0, os_1.homedir)()}`;
|
||||
return (0, crypto_1.createHash)('sha256').update(machineId).digest('hex').substring(0, 16);
|
||||
}
|
||||
generateDockerStableId() {
|
||||
const bootId = this.readBootId();
|
||||
if (bootId) {
|
||||
const fingerprint = `${bootId}-${(0, os_2.platform)()}-${(0, os_2.arch)()}`;
|
||||
return (0, crypto_1.createHash)('sha256').update(fingerprint).digest('hex').substring(0, 16);
|
||||
}
|
||||
const combinedFingerprint = this.generateCombinedFingerprint();
|
||||
if (combinedFingerprint) {
|
||||
return combinedFingerprint;
|
||||
}
|
||||
const genericId = `docker-${(0, os_2.platform)()}-${(0, os_2.arch)()}`;
|
||||
return (0, crypto_1.createHash)('sha256').update(genericId).digest('hex').substring(0, 16);
|
||||
}
|
||||
readBootId() {
|
||||
try {
|
||||
const bootIdPath = '/proc/sys/kernel/random/boot_id';
|
||||
if (!(0, fs_1.existsSync)(bootIdPath)) {
|
||||
return null;
|
||||
}
|
||||
const bootId = (0, fs_1.readFileSync)(bootIdPath, 'utf-8').trim();
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
if (!uuidRegex.test(bootId)) {
|
||||
return null;
|
||||
}
|
||||
return bootId;
|
||||
}
|
||||
catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
generateCombinedFingerprint() {
|
||||
try {
|
||||
const signals = [];
|
||||
if ((0, fs_1.existsSync)('/proc/cpuinfo')) {
|
||||
const cpuinfo = (0, fs_1.readFileSync)('/proc/cpuinfo', 'utf-8');
|
||||
const cores = (cpuinfo.match(/processor\s*:/g) || []).length;
|
||||
if (cores > 0) {
|
||||
signals.push(`cores:${cores}`);
|
||||
}
|
||||
}
|
||||
if ((0, fs_1.existsSync)('/proc/meminfo')) {
|
||||
const meminfo = (0, fs_1.readFileSync)('/proc/meminfo', 'utf-8');
|
||||
const totalMatch = meminfo.match(/MemTotal:\s+(\d+)/);
|
||||
if (totalMatch) {
|
||||
signals.push(`mem:${totalMatch[1]}`);
|
||||
}
|
||||
}
|
||||
if ((0, fs_1.existsSync)('/proc/version')) {
|
||||
const version = (0, fs_1.readFileSync)('/proc/version', 'utf-8');
|
||||
const kernelMatch = version.match(/Linux version ([\d.]+)/);
|
||||
if (kernelMatch) {
|
||||
signals.push(`kernel:${kernelMatch[1]}`);
|
||||
}
|
||||
}
|
||||
signals.push((0, os_2.platform)(), (0, os_2.arch)());
|
||||
if (signals.length < 3) {
|
||||
return null;
|
||||
}
|
||||
const fingerprint = signals.join('-');
|
||||
return (0, crypto_1.createHash)('sha256').update(fingerprint).digest('hex').substring(0, 16);
|
||||
}
|
||||
catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
isCloudEnvironment() {
|
||||
return !!(process.env.RAILWAY_ENVIRONMENT ||
|
||||
process.env.RENDER ||
|
||||
process.env.FLY_APP_NAME ||
|
||||
process.env.HEROKU_APP_NAME ||
|
||||
process.env.AWS_EXECUTION_ENV ||
|
||||
process.env.KUBERNETES_SERVICE_HOST ||
|
||||
process.env.GOOGLE_CLOUD_PROJECT ||
|
||||
process.env.AZURE_FUNCTIONS_ENVIRONMENT);
|
||||
}
|
||||
loadConfig() {
|
||||
if (this.config) {
|
||||
return this.config;
|
||||
}
|
||||
if (!(0, fs_1.existsSync)(this.configPath)) {
|
||||
const version = this.getPackageVersion();
|
||||
const envDisabled = this.isDisabledByEnvironment();
|
||||
this.config = {
|
||||
enabled: !envDisabled,
|
||||
userId: this.generateUserId(),
|
||||
firstRun: new Date().toISOString(),
|
||||
version
|
||||
};
|
||||
this.saveConfig();
|
||||
if (!envDisabled) {
|
||||
this.showFirstRunNotice();
|
||||
}
|
||||
return this.config;
|
||||
}
|
||||
try {
|
||||
const rawConfig = (0, fs_1.readFileSync)(this.configPath, 'utf-8');
|
||||
this.config = JSON.parse(rawConfig);
|
||||
if (!this.config.userId) {
|
||||
this.config.userId = this.generateUserId();
|
||||
this.saveConfig();
|
||||
}
|
||||
return this.config;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to load telemetry config, using defaults:', error);
|
||||
this.config = {
|
||||
enabled: false,
|
||||
userId: this.generateUserId()
|
||||
};
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
saveConfig() {
|
||||
if (!this.config)
|
||||
return;
|
||||
try {
|
||||
if (!(0, fs_1.existsSync)(this.configDir)) {
|
||||
(0, fs_1.mkdirSync)(this.configDir, { recursive: true });
|
||||
}
|
||||
this.config.lastModified = new Date().toISOString();
|
||||
(0, fs_1.writeFileSync)(this.configPath, JSON.stringify(this.config, null, 2));
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to save telemetry config:', error);
|
||||
}
|
||||
}
|
||||
isEnabled() {
|
||||
if (this.isDisabledByEnvironment()) {
|
||||
return false;
|
||||
}
|
||||
const config = this.loadConfig();
|
||||
return config.enabled;
|
||||
}
|
||||
isDisabledByEnvironment() {
|
||||
const envVars = [
|
||||
'N8N_MCP_TELEMETRY_DISABLED',
|
||||
'TELEMETRY_DISABLED',
|
||||
'DISABLE_TELEMETRY'
|
||||
];
|
||||
for (const varName of envVars) {
|
||||
const value = process.env[varName];
|
||||
if (value !== undefined) {
|
||||
const normalized = value.toLowerCase().trim();
|
||||
if (!['true', 'false', '1', '0', ''].includes(normalized)) {
|
||||
console.warn(`⚠️ Invalid telemetry environment variable value: ${varName}="${value}"\n` +
|
||||
` Use "true" to disable or "false" to enable telemetry.`);
|
||||
}
|
||||
if (normalized === 'true' || normalized === '1') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
getUserId() {
|
||||
const config = this.loadConfig();
|
||||
return config.userId;
|
||||
}
|
||||
isFirstRun() {
|
||||
return !(0, fs_1.existsSync)(this.configPath);
|
||||
}
|
||||
enable() {
|
||||
const config = this.loadConfig();
|
||||
config.enabled = true;
|
||||
this.config = config;
|
||||
this.saveConfig();
|
||||
console.log('✓ Anonymous telemetry enabled');
|
||||
}
|
||||
disable() {
|
||||
const config = this.loadConfig();
|
||||
config.enabled = false;
|
||||
this.config = config;
|
||||
this.saveConfig();
|
||||
console.log('✓ Anonymous telemetry disabled');
|
||||
}
|
||||
getStatus() {
|
||||
const config = this.loadConfig();
|
||||
const envDisabled = this.isDisabledByEnvironment();
|
||||
let status = config.enabled ? 'ENABLED' : 'DISABLED';
|
||||
if (envDisabled) {
|
||||
status = 'DISABLED (via environment variable)';
|
||||
}
|
||||
return `
|
||||
Telemetry Status: ${status}
|
||||
Anonymous ID: ${config.userId}
|
||||
First Run: ${config.firstRun || 'Unknown'}
|
||||
Config Path: ${this.configPath}
|
||||
|
||||
To opt-out: npx n8n-mcp telemetry disable
|
||||
To opt-in: npx n8n-mcp telemetry enable
|
||||
|
||||
For Docker: Set N8N_MCP_TELEMETRY_DISABLED=true
|
||||
`;
|
||||
}
|
||||
showFirstRunNotice() {
|
||||
console.log(`
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ Anonymous Usage Statistics ║
|
||||
╠════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ n8n-mcp collects anonymous usage data to improve the ║
|
||||
║ tool and understand how it's being used. ║
|
||||
║ ║
|
||||
║ We track: ║
|
||||
║ • Which MCP tools are used (no parameters) ║
|
||||
║ • Workflow structures (sanitized, no sensitive data) ║
|
||||
║ • Error patterns (hashed, no details) ║
|
||||
║ • Performance metrics (timing, success rates) ║
|
||||
║ ║
|
||||
║ We NEVER collect: ║
|
||||
║ • URLs, API keys, or credentials ║
|
||||
║ • Workflow content or actual data ║
|
||||
║ • Personal or identifiable information ║
|
||||
║ • n8n instance details or locations ║
|
||||
║ ║
|
||||
║ Your anonymous ID: ${this.config?.userId || 'generating...'} ║
|
||||
║ ║
|
||||
║ This helps me understand usage patterns and improve ║
|
||||
║ n8n-mcp for everyone. Thank you for your support! ║
|
||||
║ ║
|
||||
║ To opt-out at any time: ║
|
||||
║ npx n8n-mcp telemetry disable ║
|
||||
║ ║
|
||||
║ Data deletion requests: ║
|
||||
║ Email romuald@n8n-mcp.com with your anonymous ID ║
|
||||
║ ║
|
||||
║ Learn more: ║
|
||||
║ https://github.com/czlonkowski/n8n-mcp/blob/main/PRIVACY.md ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
`);
|
||||
}
|
||||
getPackageVersion() {
|
||||
try {
|
||||
const possiblePaths = [
|
||||
(0, path_1.resolve)(__dirname, '..', '..', 'package.json'),
|
||||
(0, path_1.resolve)(process.cwd(), 'package.json'),
|
||||
(0, path_1.resolve)(__dirname, '..', '..', '..', 'package.json')
|
||||
];
|
||||
for (const packagePath of possiblePaths) {
|
||||
if ((0, fs_1.existsSync)(packagePath)) {
|
||||
const packageJson = JSON.parse((0, fs_1.readFileSync)(packagePath, 'utf-8'));
|
||||
if (packageJson.version) {
|
||||
return packageJson.version;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const packageJson = require('../../package.json');
|
||||
return packageJson.version || 'unknown';
|
||||
}
|
||||
catch {
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
catch (error) {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.TelemetryConfigManager = TelemetryConfigManager;
|
||||
//# sourceMappingURL=config-manager.js.map
|
||||
Reference in New Issue
Block a user