228 lines
9.4 KiB
JavaScript
228 lines
9.4 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* Compare endpoints from JSON export with NPMplus configuration
|
||
|
|
* Identifies missing domains, mismatches, and discrepancies
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { readFileSync } from 'fs';
|
||
|
|
import { join, dirname } from 'path';
|
||
|
|
import { fileURLToPath } from 'url';
|
||
|
|
|
||
|
|
const __filename = fileURLToPath(import.meta.url);
|
||
|
|
const __dirname = dirname(__filename);
|
||
|
|
const PROJECT_ROOT = join(__dirname, '..');
|
||
|
|
|
||
|
|
// Load endpoints JSON
|
||
|
|
const endpointsData = JSON.parse(
|
||
|
|
readFileSync(join(PROJECT_ROOT, 'reports', 'endpoints-export.json'), 'utf8')
|
||
|
|
);
|
||
|
|
|
||
|
|
// NPMplus configuration from configure-npmplus-domains.js
|
||
|
|
const NPMPLUS_DOMAINS = [
|
||
|
|
// sankofa.nexus zone (placeholder - routes to Blockscout)
|
||
|
|
{ domain: 'sankofa.nexus', target: 'http://192.168.11.140:80', websocket: false },
|
||
|
|
{ domain: 'phoenix.sankofa.nexus', target: 'http://192.168.11.140:80', websocket: false },
|
||
|
|
{ domain: 'the-order.sankofa.nexus', target: 'http://192.168.11.140:80', websocket: false },
|
||
|
|
|
||
|
|
// d-bis.org zone - RPC endpoints (UPDATED IPs)
|
||
|
|
{ domain: 'explorer.d-bis.org', target: 'http://192.168.11.140:4000', websocket: false },
|
||
|
|
{ domain: 'rpc-http-pub.d-bis.org', target: 'http://192.168.11.221:8545', websocket: true },
|
||
|
|
{ domain: 'rpc-ws-pub.d-bis.org', target: 'http://192.168.11.221:8546', websocket: true },
|
||
|
|
{ domain: 'rpc-http-prv.d-bis.org', target: 'http://192.168.11.211:8545', websocket: true },
|
||
|
|
{ domain: 'rpc-ws-prv.d-bis.org', target: 'http://192.168.11.211:8546', websocket: true },
|
||
|
|
{ domain: 'dbis-admin.d-bis.org', target: 'http://192.168.11.130:80', websocket: false },
|
||
|
|
{ domain: 'dbis-api.d-bis.org', target: 'http://192.168.11.155:3000', websocket: false },
|
||
|
|
{ domain: 'dbis-api-2.d-bis.org', target: 'http://192.168.11.156:3000', websocket: false },
|
||
|
|
{ domain: 'secure.d-bis.org', target: 'http://192.168.11.130:80', websocket: false },
|
||
|
|
|
||
|
|
// mim4u.org zone
|
||
|
|
{ domain: 'mim4u.org', target: 'http://192.168.11.36:80', websocket: false },
|
||
|
|
{ domain: 'secure.mim4u.org', target: 'http://192.168.11.36:80', websocket: false },
|
||
|
|
{ domain: 'training.mim4u.org', target: 'http://192.168.11.36:80', websocket: false },
|
||
|
|
|
||
|
|
// defi-oracle.io zone - ThirdWeb RPC
|
||
|
|
{ domain: 'rpc.public-0138.defi-oracle.io', target: 'https://192.168.11.240:443', websocket: true },
|
||
|
|
{ domain: 'rpc.defi-oracle.io', target: 'https://192.168.11.240:443', websocket: true },
|
||
|
|
{ domain: 'wss.defi-oracle.io', target: 'https://192.168.11.240:443', websocket: true },
|
||
|
|
];
|
||
|
|
|
||
|
|
// Extract domains from endpoints JSON
|
||
|
|
const endpointDomains = new Map();
|
||
|
|
|
||
|
|
for (const endpoint of endpointsData) {
|
||
|
|
if (endpoint.domain && endpoint.domain.trim() !== '') {
|
||
|
|
const domains = endpoint.domain.split(',').map(d => d.trim());
|
||
|
|
for (const domain of domains) {
|
||
|
|
if (!endpointDomains.has(domain)) {
|
||
|
|
endpointDomains.set(domain, []);
|
||
|
|
}
|
||
|
|
endpointDomains.get(domain).push({
|
||
|
|
vmid: endpoint.vmid,
|
||
|
|
ip: endpoint.ip,
|
||
|
|
port: endpoint.port,
|
||
|
|
protocol: endpoint.protocol,
|
||
|
|
service: endpoint.service,
|
||
|
|
status: endpoint.status,
|
||
|
|
endpoint: endpoint.endpoint
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Parse NPMplus targets
|
||
|
|
const npmplusMap = new Map();
|
||
|
|
for (const config of NPMPLUS_DOMAINS) {
|
||
|
|
const url = new URL(config.target);
|
||
|
|
npmplusMap.set(config.domain, {
|
||
|
|
target: config.target,
|
||
|
|
ip: url.hostname,
|
||
|
|
port: url.port || (url.protocol === 'https:' ? '443' : '80'),
|
||
|
|
protocol: url.protocol.replace(':', ''),
|
||
|
|
websocket: config.websocket
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Compare
|
||
|
|
const comparison = {
|
||
|
|
matches: [],
|
||
|
|
mismatches: [],
|
||
|
|
missingInNPMplus: [],
|
||
|
|
missingInEndpoints: [],
|
||
|
|
notes: []
|
||
|
|
};
|
||
|
|
|
||
|
|
// Check domains from endpoints
|
||
|
|
for (const [domain, endpoints] of endpointDomains) {
|
||
|
|
const npmplusConfig = npmplusMap.get(domain);
|
||
|
|
|
||
|
|
if (!npmplusConfig) {
|
||
|
|
comparison.missingInNPMplus.push({
|
||
|
|
domain,
|
||
|
|
endpoints
|
||
|
|
});
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Find matching endpoint
|
||
|
|
const matchingEndpoint = endpoints.find(ep =>
|
||
|
|
ep.ip === npmplusConfig.ip &&
|
||
|
|
ep.port === npmplusConfig.port
|
||
|
|
);
|
||
|
|
|
||
|
|
if (matchingEndpoint) {
|
||
|
|
comparison.matches.push({
|
||
|
|
domain,
|
||
|
|
npmplus: npmplusConfig,
|
||
|
|
endpoint: matchingEndpoint
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
comparison.mismatches.push({
|
||
|
|
domain,
|
||
|
|
npmplus: npmplusConfig,
|
||
|
|
endpoints: endpoints,
|
||
|
|
issue: `IP/Port mismatch: NPMplus targets ${npmplusConfig.ip}:${npmplusConfig.port}, but endpoints show ${endpoints.map(e => `${e.ip}:${e.port}`).join(', ')}`
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check domains in NPMplus but not in endpoints
|
||
|
|
for (const [domain, config] of npmplusMap) {
|
||
|
|
if (!endpointDomains.has(domain)) {
|
||
|
|
comparison.missingInEndpoints.push({
|
||
|
|
domain,
|
||
|
|
npmplus: config
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate report
|
||
|
|
console.log('');
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('📊 Endpoints vs NPMplus Comparison Report');
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|
||
|
|
|
||
|
|
console.log(`📋 Summary:`);
|
||
|
|
console.log(` ✅ Matches: ${comparison.matches.length}`);
|
||
|
|
console.log(` ⚠️ Mismatches: ${comparison.mismatches.length}`);
|
||
|
|
console.log(` ❌ Missing in NPMplus: ${comparison.missingInNPMplus.length}`);
|
||
|
|
console.log(` ❌ Missing in Endpoints: ${comparison.missingInEndpoints.length}`);
|
||
|
|
console.log('');
|
||
|
|
|
||
|
|
// Matches
|
||
|
|
if (comparison.matches.length > 0) {
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log(`✅ MATCHES (${comparison.matches.length})`);
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|
||
|
|
for (const match of comparison.matches) {
|
||
|
|
console.log(` ${match.domain}`);
|
||
|
|
console.log(` NPMplus: ${match.npmplus.target} ${match.npmplus.websocket ? '(WebSocket ✓)' : ''}`);
|
||
|
|
console.log(` Endpoint: ${match.endpoint.endpoint} (VMID ${match.endpoint.vmid}, ${match.endpoint.service})`);
|
||
|
|
console.log('');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Mismatches
|
||
|
|
if (comparison.mismatches.length > 0) {
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log(`⚠️ MISMATCHES (${comparison.mismatches.length})`);
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|
||
|
|
for (const mismatch of comparison.mismatches) {
|
||
|
|
console.log(` ${mismatch.domain}`);
|
||
|
|
console.log(` NPMplus: ${mismatch.npmplus.target}`);
|
||
|
|
console.log(` Issue: ${mismatch.issue}`);
|
||
|
|
console.log(` Available endpoints:`);
|
||
|
|
for (const ep of mismatch.endpoints) {
|
||
|
|
console.log(` - ${ep.endpoint} (VMID ${ep.vmid}, ${ep.service}, ${ep.status})`);
|
||
|
|
}
|
||
|
|
console.log('');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Missing in NPMplus
|
||
|
|
if (comparison.missingInNPMplus.length > 0) {
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log(`❌ MISSING IN NPMPLUS (${comparison.missingInNPMplus.length})`);
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|
||
|
|
console.log(' These domains exist in endpoints but are not configured in NPMplus:');
|
||
|
|
console.log('');
|
||
|
|
for (const missing of comparison.missingInNPMplus) {
|
||
|
|
console.log(` ${missing.domain}`);
|
||
|
|
for (const ep of missing.endpoints) {
|
||
|
|
console.log(` - ${ep.endpoint} (VMID ${ep.vmid}, ${ep.service}, ${ep.status})`);
|
||
|
|
}
|
||
|
|
console.log('');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Missing in Endpoints
|
||
|
|
if (comparison.missingInEndpoints.length > 0) {
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log(`❌ MISSING IN ENDPOINTS (${comparison.missingInEndpoints.length})`);
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|
||
|
|
console.log(' These domains are configured in NPMplus but not found in endpoints:');
|
||
|
|
console.log('');
|
||
|
|
for (const missing of comparison.missingInEndpoints) {
|
||
|
|
console.log(` ${missing.domain}`);
|
||
|
|
console.log(` NPMplus target: ${missing.npmplus.target}`);
|
||
|
|
console.log('');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Export JSON
|
||
|
|
const fs = await import('fs');
|
||
|
|
const comparisonFile = join(PROJECT_ROOT, 'reports', 'endpoints-npmplus-comparison.json');
|
||
|
|
fs.writeFileSync(
|
||
|
|
comparisonFile,
|
||
|
|
JSON.stringify(comparison, null, 2)
|
||
|
|
);
|
||
|
|
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log(`📄 Detailed comparison saved to: reports/endpoints-npmplus-comparison.json`);
|
||
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
|
|
console.log('');
|