/**
* Static Pricing Loader
*
* Loads domain pricing from static JSON file.
* Falls back to bundled default pricing if file doesn't exist.
*/
import { readFileSync, existsSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import type { JokerPricingResult } from './price-cache.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
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>;
}
/**
* Default pricing data (fallback)
* Updated: 2025-12-11
* Source: Joker.com public pricing
*/
const DEFAULT_PRICING: PricingDatabase = {
last_updated: '2025-12-11T00:00:00.000Z',
source: 'Joker.com default pricing (static)',
pricing: {
'com': { tld: 'com', registration: 12.99, renewal: 14.99, transfer: 12.99, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'net': { tld: 'net', registration: 13.99, renewal: 15.99, transfer: 13.99, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'org': { tld: 'org', registration: 13.99, renewal: 15.99, transfer: 13.99, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'io': { tld: 'io', registration: 35.00, renewal: 39.00, transfer: 35.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'app': { tld: 'app', registration: 18.00, renewal: 20.00, transfer: 18.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'dev': { tld: 'dev', registration: 15.00, renewal: 17.00, transfer: 15.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'co': { tld: 'co', registration: 30.00, renewal: 32.00, transfer: 30.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'me': { tld: 'me', registration: 20.00, renewal: 22.00, transfer: 20.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'ai': { tld: 'ai', registration: 100.00, renewal: 110.00, transfer: 100.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
'tech': { tld: 'tech', registration: 55.00, renewal: 60.00, transfer: 55.00, currency: 'USD', last_updated: '2025-12-11T00:00:00.000Z' },
},
};
/**
* Load pricing database from file or use default
*/
function loadPricingDatabase(): PricingDatabase {
const pricingPath = resolve(__dirname, '../../data/pricing.json');
if (existsSync(pricingPath)) {
try {
const content = readFileSync(pricingPath, 'utf-8');
const database = JSON.parse(content) as PricingDatabase;
console.error(`[Static Pricing] Loaded ${Object.keys(database.pricing).length} TLDs from ${pricingPath}`);
return database;
} catch (error) {
console.error('[Static Pricing] Failed to load pricing.json, using defaults:', error);
return DEFAULT_PRICING;
}
}
console.error('[Static Pricing] No pricing.json found, using default pricing');
console.error('[Static Pricing] Run `pnpm fetch-pricing` to update with current data');
return DEFAULT_PRICING;
}
// Load pricing database once at startup
const pricingDatabase = loadPricingDatabase();
/**
* Extract TLD from domain name
*/
function extractTLD(domain: string): string {
const parts = domain.split('.');
// Handle multi-part TLDs (e.g., co.uk, com.au)
if (parts.length >= 3) {
const secondLevelTLD = `${parts[parts.length - 2]}.${parts[parts.length - 1]}`;
const commonSecondLevel = ['co.uk', 'com.au', 'co.nz', 'co.za', 'org.uk', 'ac.uk'];
if (commonSecondLevel.includes(secondLevelTLD)) {
return secondLevelTLD;
}
}
return parts[parts.length - 1];
}
/**
* Get pricing for a domain from static data
*/
export function getStaticPricing(domain: string): JokerPricingResult {
const normalizedDomain = domain.toLowerCase().trim();
const tld = extractTLD(normalizedDomain);
const entry = pricingDatabase.pricing[tld];
if (!entry) {
return {
domain: normalizedDomain,
available: false,
source_url: 'static://pricing.json',
last_updated: pricingDatabase.last_updated,
error: `No pricing data found for TLD .${tld} in static database`,
};
}
return {
domain: normalizedDomain,
available: false, // Static data doesn't check availability
pricing: {
registration_1yr: entry.registration,
renewal_1yr: entry.renewal,
transfer: entry.transfer,
currency: entry.currency,
},
source_url: 'static://pricing.json',
last_updated: entry.last_updated,
};
}
/**
* Get database metadata
*/
export function getPricingMetadata(): {
last_updated: string;
source: string;
tld_count: number;
} {
return {
last_updated: pricingDatabase.last_updated,
source: pricingDatabase.source,
tld_count: Object.keys(pricingDatabase.pricing).length,
};
}