#!/usr/bin/env node
/**
* Fetch current pricing from Joker.com DMAPI and save to static JSON file
*
* Usage:
* 1. Configure .env with Joker.com credentials
* 2. Run: node dist/scripts/fetch-pricing.js
* 3. Pricing data saved to data/pricing.json
*/
import { writeFileSync, mkdirSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import { config } from 'dotenv';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const projectRoot = resolve(__dirname, '../../..');
// Load .env
config({ path: resolve(projectRoot, '.env') });
// Import after dotenv config
const { dmapiRequest } = await import('../dmapi-client.js');
interface PricingEntry {
tld: string;
registration?: number;
renewal?: number;
transfer?: number;
currency: string;
last_updated: string;
}
interface PricingDatabase {
last_updated: string;
source: string;
pricing: Record<string, PricingEntry>;
}
async function main() {
console.log('🔍 Fetching pricing from Joker.com DMAPI...\n');
try {
// Fetch price list
const response = await dmapiRequest('query-price-list');
// Parse TSV response
const lines = response.trim().split('\n');
const pricingMap = new Map<string, PricingEntry>();
for (const line of lines) {
// Skip header
if (line.startsWith('type') || line.startsWith('#')) {
continue;
}
const parts = line.split('\t');
if (parts.length < 13) continue;
const [type, operation, tld, currency, , price] = parts;
if (type !== 'domain') continue;
// Get or create entry for this TLD
if (!pricingMap.has(tld)) {
pricingMap.set(tld, {
tld,
currency,
last_updated: new Date().toISOString(),
});
}
const entry = pricingMap.get(tld)!;
// Map operations to fields
const priceNum = parseFloat(price);
if (operation === 'create') {
entry.registration = priceNum;
} else if (operation === 'renew') {
entry.renewal = priceNum;
} else if (operation === 'transfer') {
entry.transfer = priceNum;
}
}
// Convert to database format
const database: PricingDatabase = {
last_updated: new Date().toISOString(),
source: 'Joker.com DMAPI query-price-list',
pricing: Object.fromEntries(pricingMap),
};
// Save to JSON file
const dataDir = resolve(projectRoot, 'data');
mkdirSync(dataDir, { recursive: true });
const outputPath = resolve(dataDir, 'pricing.json');
writeFileSync(outputPath, JSON.stringify(database, null, 2), 'utf-8');
console.log(`✅ Successfully fetched pricing for ${pricingMap.size} TLDs`);
console.log(`📁 Saved to: ${outputPath}`);
console.log(`📅 Last updated: ${database.last_updated}\n`);
// Show sample
const sampleTLDs = ['com', 'org', 'net', 'io', 'app'].filter(tld => pricingMap.has(tld));
if (sampleTLDs.length > 0) {
console.log('Sample pricing:');
sampleTLDs.forEach(tld => {
const entry = pricingMap.get(tld)!;
console.log(` .${tld}: ${entry.currency} ${entry.registration} (reg) / ${entry.renewal} (renew)`);
});
}
process.exit(0);
} catch (error) {
console.error('❌ Error fetching pricing:', error);
console.error('\nMake sure .env is configured with Joker.com credentials:');
console.error(' MCP_JOKER_API_KEY or MCP_JOKER_USERNAME + MCP_JOKER_PASSWORD');
process.exit(1);
}
}
main();