UNPKG

mdsaad-cli

Version:

🚀 A powerful CLI toolkit with 20+ commands: AI chat, weather, math calculations, ASCII art, currency conversion, and more - all without API keys required!

1,140 lines (1,016 loc) 30.3 kB
/** * Convert Command * Handles currency and unit conversions with support for 150+ currencies * and various unit types (length, weight, temperature) */ const { Command } = require('commander'); const chalk = require('chalk'); const Table = require('cli-table3'); const loggerService = require('../services/logger'); const configService = require('../services/config'); const cacheService = require('../services/cache'); const i18nService = require('../services/i18n'); const outputFormatter = require('../services/output-formatter'); const errorHandler = require('../services/error-handler'); const debugService = require('../services/debug-service'); class ConvertCommand { constructor() { this.apiKeys = {}; this.isInitialized = false; this.cacheTtl = 1800; // 30 minutes for exchange rates } /** * Initialize the convert service */ async initialize() { if (this.isInitialized) { return; } try { // Load API keys from configuration this.apiKeys = { fixer: configService.getApiKey('fixer'), 'fixer-io': configService.getApiKey('fixer-io'), 'exchangerate-api': configService.getApiKey('exchangerate-api') || 'ef49ea934522c581d0e31254', }; this.isInitialized = true; loggerService.info('Convert service initialized successfully'); } catch (error) { loggerService.error( 'Failed to initialize convert service:', error.message ); throw error; } } /** * Create the convert command */ createCommand() { const convertCmd = new Command('convert') .alias('conv') .description(i18nService.t('commands.convert.description')) .argument('<amount>', 'Amount to convert') .argument('<from>', 'Source unit/currency') .argument('<to>', 'Target unit/currency') .option('-v, --verbose', 'Show detailed conversion information') .option( '-h, --historical [date]', 'Use historical exchange rates (YYYY-MM-DD)' ) .option('-r, --rates', 'Show current exchange rates') .option('-f, --favorites', 'Show favorite conversion pairs') .option('-a, --add-favorite', 'Add this conversion to favorites') .option('-b, --batch <file>', 'Process batch conversions from file') .action(async (amount, from, to, options) => { await this.execute(amount, from, to, options); }); return convertCmd; } /** * Execute the convert command */ async execute(amount, from, to, options = {}) { try { debugService.markPerformance('convert_command', 'start'); debugService.debug( 'Executing convert command', { amount, from, to, options }, 'convert' ); await this.initialize(); // Handle special commands first (no amount/from/to required) if (options.rates) { await this.showExchangeRates(); debugService.markPerformance('convert_command', 'end'); return; } if (options.favorites) { await this.showFavorites(); debugService.markPerformance('convert_command', 'end'); return; } if (options.batch) { await this.processBatchConversions(options.batch); debugService.markPerformance('convert_command', 'end'); return; } // Validate required arguments for conversion if (!amount || !from || !to) { console.log(chalk.cyan('💱 MDSAAD Currency & Unit Converter')); console.log(); console.log(chalk.yellow('Usage Examples:')); console.log(chalk.gray(' Currency:'), 'mdsaad convert 100 USD EUR'); console.log(chalk.gray(' Temperature:'), 'mdsaad convert 32 F C'); console.log(chalk.gray(' Length:'), 'mdsaad convert 10 KM MI'); console.log(chalk.gray(' Weight:'), 'mdsaad convert 5 KG LB'); console.log(); console.log(chalk.yellow('Special Options:')); console.log(chalk.gray(' Exchange rates:'), 'mdsaad convert --rates'); console.log(chalk.gray(' Favorites:'), 'mdsaad convert --favorites'); console.log( chalk.gray(' Verbose:'), 'mdsaad convert 100 C F --verbose' ); console.log(); return; } // Parse amount const numericAmount = parseFloat(amount); if (isNaN(numericAmount)) { throw new Error( `Invalid amount: ${amount}. Please provide a numeric value.` ); } // Normalize currency/unit codes const fromCode = from.toUpperCase(); const toCode = to.toUpperCase(); // Determine conversion type (currency vs unit) const conversionType = this.getConversionType(fromCode, toCode); let result; if (conversionType === 'currency') { result = await this.convertCurrency( numericAmount, fromCode, toCode, options ); } else if (conversionType === 'unit') { result = this.convertUnit(numericAmount, fromCode, toCode); } else { // Provide helpful suggestions console.log( chalk.red('❌ Unsupported conversion:'), `${fromCode} to ${toCode}` ); console.log(); console.log(chalk.yellow('💡 Supported conversions:')); console.log( chalk.gray(' Currencies:'), 'USD, EUR, GBP, JPY, CAD, AUD, etc.' ); console.log( chalk.gray(' Temperature:'), 'C, F, K, R (Celsius, Fahrenheit, Kelvin, Rankine)' ); console.log(chalk.gray(' Length:'), 'M, FT, IN, KM, MI, CM, MM, YD'); console.log(chalk.gray(' Weight:'), 'KG, LB, G, OZ, TON'); console.log(chalk.gray(' Volume:'), 'L, GAL, ML, FL_OZ, CUP'); console.log(chalk.gray(' Time:'), 'S, MIN, H, D, WK, YR'); console.log(); return; } // Display result await this.displayConversionResult(result, options); // Add to favorites if requested if (options.addFavorite) { await this.addToFavorites(fromCode, toCode); } debugService.markPerformance('convert_command', 'end'); debugService.debug('Convert command completed successfully'); } catch (error) { debugService.markPerformance('convert_command', 'end'); const result = await errorHandler.handleError(error, { command: 'convert', context: { amount, from, to, options }, userFriendly: true, }); if (result.action === 'retry' && result.context?.fallbackRate) { debugService.debug('Using fallback conversion rate'); const fallbackResult = amount * result.context.fallbackRate; console.log(outputFormatter.warning('⚠️ Using fallback exchange rate')); console.log( outputFormatter.success( `💱 ${amount} ${from}${fallbackResult.toFixed(4)} ${to} (approximate)` ) ); } } } /** * Determine if this is a currency or unit conversion */ getConversionType(from, to) { const currencies = this.getSupportedCurrencies(); // Check if both are currencies (requires API) const fromIsCurrency = currencies.includes(from); const toIsCurrency = currencies.includes(to); if (fromIsCurrency && toIsCurrency) { return 'currency'; } // Check if both are units (local calculation) const unitCategory = this.findUnitCategory(from, to); if (unitCategory) { return 'unit'; } return 'unknown'; } /** * Find which category both units belong to (if any) */ findUnitCategory(from, to) { const units = this.getSupportedUnits(); for (const [categoryName, categoryUnits] of Object.entries(units)) { if ( categoryUnits[from] !== undefined && categoryUnits[to] !== undefined ) { return categoryName; } } return null; } /** * Convert currency using exchange rates */ async convertCurrency(amount, fromCurrency, toCurrency, options = {}) { // Check cache first const cacheKey = `exchange_rate:${fromCurrency}:${toCurrency}:${options.historical || 'latest'}`; try { const cached = await cacheService.get('currency', cacheKey); if (cached && cached.data && !options.historical) { const rate = cached.data.rate; const convertedAmount = amount * rate; return { amount: amount, fromCurrency: fromCurrency, toCurrency: toCurrency, rate: rate, convertedAmount: convertedAmount, cached: true, timestamp: cached.timestamp, }; } } catch (cacheError) { loggerService.warn('Cache retrieval failed:', cacheError.message); } // Fetch exchange rate from API const exchangeData = await this.fetchExchangeRate( fromCurrency, toCurrency, options ); const rate = exchangeData.rate; const convertedAmount = amount * rate; // Cache the exchange rate try { await cacheService.set( 'currency', cacheKey, { rate: rate, date: exchangeData.date, provider: exchangeData.provider, }, this.cacheTtl ); } catch (cacheError) { loggerService.warn('Cache storage failed:', cacheError.message); } return { amount: amount, fromCurrency: fromCurrency, toCurrency: toCurrency, rate: rate, convertedAmount: convertedAmount, date: exchangeData.date, provider: exchangeData.provider, cached: false, }; } /** * Fetch exchange rate from API */ async fetchExchangeRate(fromCurrency, toCurrency, options = {}) { const providers = [ { name: 'ExchangeRate-API', method: 'fetchFromExchangeRateAPI' }, { name: 'Fixer.io', method: 'fetchFromFixerIO' }, ]; for (const provider of providers) { try { const result = await this[provider.method]( fromCurrency, toCurrency, options ); if (result) { return { ...result, provider: provider.name, }; } } catch (error) { loggerService.warn( `${provider.name} exchange rate fetch failed:`, error.message ); continue; } } throw new Error('All exchange rate providers failed'); } /** * Fetch from ExchangeRate-API (with API key) */ async fetchFromExchangeRateAPI(fromCurrency, toCurrency, options = {}) { const axios = require('axios'); const apiKey = this.apiKeys['exchangerate-api']; let url; if (apiKey) { // Use v6 API with API key for better rates and limits if (options.historical) { url = `https://v6.exchangerate-api.com/v6/${apiKey}/history/${fromCurrency}/${options.historical}`; } else { url = `https://v6.exchangerate-api.com/v6/${apiKey}/latest/${fromCurrency}`; } } else { // Fallback to v4 API without key (limited) if (options.historical) { url = `https://api.exchangerate-api.com/v4/history/${fromCurrency}/${options.historical}`; } else { url = `https://api.exchangerate-api.com/v4/latest/${fromCurrency}`; } } const response = await axios.get(url, { timeout: 10000, headers: { 'User-Agent': 'MDSAAD-CLI/1.0.0', }, }); if ( response.data && response.data.conversion_rates && response.data.conversion_rates[toCurrency] ) { // v6 API format return { rate: response.data.conversion_rates[toCurrency], date: response.data.time_last_update_utc ? response.data.time_last_update_utc.split(' ')[0] : new Date().toISOString().split('T')[0], }; } else if ( response.data && response.data.rates && response.data.rates[toCurrency] ) { // v4 API format return { rate: response.data.rates[toCurrency], date: response.data.date, }; } throw new Error( `Exchange rate not found for ${fromCurrency} to ${toCurrency}` ); } /** * Fetch from Fixer.io (requires API key) */ async fetchFromFixerIO(fromCurrency, toCurrency, options = {}) { const apiKey = this.apiKeys.fixer || this.apiKeys['fixer-io']; if (!apiKey) { throw new Error('Fixer.io API key not configured'); } const axios = require('axios'); let url; if (options.historical) { url = `https://api.fixer.io/${options.historical}?access_key=${apiKey}&base=${fromCurrency}&symbols=${toCurrency}`; } else { url = `https://api.fixer.io/latest?access_key=${apiKey}&base=${fromCurrency}&symbols=${toCurrency}`; } const response = await axios.get(url, { timeout: 10000, }); if ( response.data && response.data.rates && response.data.rates[toCurrency] ) { return { rate: response.data.rates[toCurrency], date: response.data.date, }; } throw new Error( `Exchange rate not found for ${fromCurrency} to ${toCurrency}` ); } /** * Convert units (length, weight, temperature) - ALL LOCAL CALCULATIONS */ convertUnit(amount, fromUnit, toUnit) { // Find the conversion category const category = this.findUnitCategory(fromUnit, toUnit); if (!category) { throw new Error( `Cannot convert ${fromUnit} to ${toUnit}. Units must be from the same category.` ); } // Handle temperature conversions (special formulas) if (category === 'temperature') { return this.convertTemperature(amount, fromUnit, toUnit); } // Handle length, weight, volume conversions (factor-based) return this.convertWithFactors(amount, fromUnit, toUnit, category); } /** * Convert using multiplication factors (length, weight, volume, etc.) */ convertWithFactors(amount, fromUnit, toUnit, category) { const conversions = this.getUnitConversions(); const categoryUnits = conversions[category]; const fromFactor = categoryUnits[fromUnit]; const toFactor = categoryUnits[toUnit]; if (fromFactor === undefined || toFactor === undefined) { throw new Error( `Conversion factors not found for ${fromUnit} to ${toUnit}` ); } // Convert to base unit, then to target unit const baseAmount = amount * fromFactor; const convertedAmount = baseAmount / toFactor; return { amount: amount, fromUnit: fromUnit, toUnit: toUnit, convertedAmount: convertedAmount, category: category, formula: `${amount} ${fromUnit} × ${fromFactor} ÷ ${toFactor} = ${convertedAmount.toFixed(6)} ${toUnit}`, calculation: `Base: ${baseAmount} → Result: ${convertedAmount}`, }; } /** * Convert temperature (LOCAL CALCULATION - special formulas for C, F, K, R) */ convertTemperature(amount, fromUnit, toUnit) { // Normalize unit names const from = this.normalizeTemperatureUnit(fromUnit); const to = this.normalizeTemperatureUnit(toUnit); if (!from || !to) { throw new Error( `Unknown temperature unit. Supported: C, F, K, R (Celsius, Fahrenheit, Kelvin, Rankine)` ); } let result; let formula; // Direct conversion formulas (no intermediate step for better accuracy) const conversionKey = `${from}_${to}`; switch (conversionKey) { // Celsius conversions case 'C_F': result = (amount * 9) / 5 + 32; formula = `(${amount}°C × 9/5) + 32`; break; case 'C_K': result = amount + 273.15; formula = `${amount}°C + 273.15`; break; case 'C_R': result = ((amount + 273.15) * 9) / 5; formula = `(${amount}°C + 273.15) × 9/5`; break; case 'C_C': result = amount; formula = `${amount}°C`; break; // Fahrenheit conversions case 'F_C': result = ((amount - 32) * 5) / 9; formula = `(${amount}°F - 32) × 5/9`; break; case 'F_K': result = ((amount - 32) * 5) / 9 + 273.15; formula = `((${amount}°F - 32) × 5/9) + 273.15`; break; case 'F_R': result = amount + 459.67; formula = `${amount}°F + 459.67`; break; case 'F_F': result = amount; formula = `${amount}°F`; break; // Kelvin conversions case 'K_C': result = amount - 273.15; formula = `${amount}K - 273.15`; break; case 'K_F': result = ((amount - 273.15) * 9) / 5 + 32; formula = `(${amount}K - 273.15) × 9/5 + 32`; break; case 'K_R': result = (amount * 9) / 5; formula = `${amount}K × 9/5`; break; case 'K_K': result = amount; formula = `${amount}K`; break; // Rankine conversions case 'R_C': result = ((amount - 491.67) * 5) / 9; formula = `(${amount}°R - 491.67) × 5/9`; break; case 'R_F': result = amount - 459.67; formula = `${amount}°R - 459.67`; break; case 'R_K': result = (amount * 5) / 9; formula = `${amount}°R × 5/9`; break; case 'R_R': result = amount; formula = `${amount}°R`; break; default: throw new Error(`Unsupported temperature conversion: ${from} to ${to}`); } return { amount: amount, fromUnit: fromUnit, toUnit: toUnit, convertedAmount: result, category: 'temperature', formula: `${formula} = ${result.toFixed(4)}°${to}`, calculation: `Direct conversion using temperature formula`, }; } /** * Normalize temperature unit names */ normalizeTemperatureUnit(unit) { const normalized = unit.toUpperCase(); if (['C', 'CELSIUS', '°C'].includes(normalized)) return 'C'; if (['F', 'FAHRENHEIT', '°F'].includes(normalized)) return 'F'; if (['K', 'KELVIN'].includes(normalized)) return 'K'; if (['R', 'RANKINE', '°R'].includes(normalized)) return 'R'; return null; } /** * Get temperature conversion formula */ getTemperatureFormula(from, to, input, output) { const formulas = { C_F: `(${input}°C × 9/5) + 32 = ${output.toFixed(2)}°F`, F_C: `(${input}°F - 32) × 5/9 = ${output.toFixed(2)}°C`, C_K: `${input}°C + 273.15 = ${output.toFixed(2)}K`, K_C: `${input}K - 273.15 = ${output.toFixed(2)}°C`, F_K: `((${input}°F - 32) × 5/9) + 273.15 = ${output.toFixed(2)}K`, K_F: `(${input}K - 273.15) × 9/5 + 32 = ${output.toFixed(2)}°F`, }; const key = `${from.charAt(0)}_${to.charAt(0)}`; return formulas[key] || `${input} ${from} = ${output.toFixed(2)} ${to}`; } /** * Display conversion result */ async displayConversionResult(result, options = {}) { console.log(); if (result.category) { // Unit conversion result (LOCAL CALCULATION) console.log(chalk.cyan(`🔄 Unit Conversion (${result.category})`)); console.log(); // Format number display based on category let precision = 6; if (result.category === 'temperature') precision = 4; if (result.category === 'length' && result.convertedAmount > 1000) precision = 2; console.log( chalk.green( `${result.amount} ${result.fromUnit} = ${chalk.bold(result.convertedAmount.toFixed(precision))} ${result.toUnit}` ) ); if (options.verbose) { console.log(); if (result.formula) { console.log(chalk.gray('Formula:'), result.formula); } if (result.calculation) { console.log(chalk.gray('Method:'), result.calculation); } console.log(chalk.gray('Type:'), 'Local calculation (no API required)'); } } else { // Currency conversion result (API REQUIRED) console.log(chalk.cyan('💱 Currency Conversion')); console.log(); console.log( chalk.green( `${result.amount} ${result.fromCurrency} = ${chalk.bold(result.convertedAmount.toFixed(2))} ${result.toCurrency}` ) ); console.log(); console.log( chalk.gray('Exchange Rate:'), `1 ${result.fromCurrency} = ${result.rate} ${result.toCurrency}` ); if (result.date) { console.log(chalk.gray('Date:'), result.date); } if (result.provider) { console.log(chalk.gray('Provider:'), result.provider); } if (result.cached) { console.log(chalk.yellow('📦 Data from cache')); } else { console.log(chalk.blue('🌐 Live data from API')); } if (options.verbose) { console.log(); console.log( chalk.gray('Calculation:'), `${result.amount} × ${result.rate} = ${result.convertedAmount.toFixed(2)}` ); console.log( chalk.gray('Type:'), 'Dynamic exchange rate (API required)' ); } } console.log(); } /** * Show current exchange rates */ async showExchangeRates() { console.log(chalk.cyan('💱 Current Exchange Rates (USD Base)')); console.log(); const majorCurrencies = [ 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY', 'INR', ]; try { const table = new Table({ head: [chalk.cyan('Currency'), chalk.cyan('Rate'), chalk.cyan('Name')], colWidths: [12, 15, 30], }); for (const currency of majorCurrencies) { try { const result = await this.fetchExchangeRate('USD', currency); const rate = result.rate; const name = this.getCurrencyName(currency); table.push([currency, rate.toFixed(4), name]); } catch (error) { table.push([currency, 'N/A', this.getCurrencyName(currency)]); } } console.log(table.toString()); } catch (error) { console.log( chalk.red('❌ Failed to fetch exchange rates:'), error.message ); } } /** * Show favorite conversion pairs */ async showFavorites() { try { const favorites = await configService.get('convert.favorites', []); if (favorites.length === 0) { console.log(chalk.yellow('📋 No favorite conversions saved')); console.log( chalk.gray('Add conversions to favorites using --add-favorite') ); return; } console.log(chalk.cyan('⭐ Favorite Conversions')); console.log(); const table = new Table({ head: [ chalk.cyan('#'), chalk.cyan('From'), chalk.cyan('To'), chalk.cyan('Type'), ], colWidths: [5, 10, 10, 15], }); favorites.forEach((fav, index) => { table.push([(index + 1).toString(), fav.from, fav.to, fav.type]); }); console.log(table.toString()); } catch (error) { console.log(chalk.red('❌ Failed to load favorites:'), error.message); } } /** * Add conversion to favorites */ async addToFavorites(from, to) { try { const favorites = await configService.get('convert.favorites', []); const type = this.getConversionType(from, to); // Check if already exists const exists = favorites.some(fav => fav.from === from && fav.to === to); if (exists) { console.log(chalk.yellow('⭐ Conversion already in favorites')); return; } favorites.push({ from: from, to: to, type: type, addedAt: new Date().toISOString(), }); await configService.set('convert.favorites', favorites); console.log(chalk.green('⭐ Added to favorites')); } catch (error) { console.log(chalk.red('❌ Failed to add to favorites:'), error.message); } } /** * Process batch conversions from file */ async processBatchConversions(filePath) { const fs = require('fs-extra'); try { console.log(chalk.cyan('📄 Processing batch conversions...')); const content = await fs.readFile(filePath, 'utf8'); const lines = content.split('\n').filter(line => line.trim()); console.log(); for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (!line || line.startsWith('#')) continue; const parts = line.split(/\s+/); if (parts.length !== 3) { console.log(chalk.red(`❌ Invalid format on line ${i + 1}: ${line}`)); continue; } const [amount, from, to] = parts; console.log( chalk.blue(`${i + 1}. Converting ${amount} ${from} to ${to}:`) ); try { await this.execute(amount, from, to); } catch (error) { console.log(chalk.red(` Error: ${error.message}`)); } console.log(); } } catch (error) { console.log(chalk.red('❌ Failed to process batch file:'), error.message); } } /** * Get supported currencies */ getSupportedCurrencies() { return [ 'USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY', 'INR', 'KRW', 'BRL', 'MXN', 'SGD', 'HKD', 'NOK', 'SEK', 'DKK', 'PLN', 'CZK', 'HUF', 'RON', 'BGN', 'HRK', 'RUB', 'TRY', 'ZAR', 'THB', 'MYR', 'IDR', 'PHP', 'NZD', 'ILS', 'EGP', 'AED', 'SAR', 'QAR', 'KWD', 'BHD', 'OMR', 'JOD', 'LBP', 'PKR', 'BDT', 'LKR', 'NPR', 'AFN', 'IRR', 'IQD', 'SYP', 'YER', ]; } /** * Get supported units with conversion factors (ALL LOCAL CALCULATIONS) */ getSupportedUnits() { return { // Length conversions (base: meters) length: { // Metric MM: 0.001, MILLIMETER: 0.001, MILLIMETERS: 0.001, CM: 0.01, CENTIMETER: 0.01, CENTIMETERS: 0.01, M: 1, METER: 1, METERS: 1, KM: 1000, KILOMETER: 1000, KILOMETERS: 1000, // Imperial IN: 0.0254, INCH: 0.0254, INCHES: 0.0254, FT: 0.3048, FOOT: 0.3048, FEET: 0.3048, YD: 0.9144, YARD: 0.9144, YARDS: 0.9144, MI: 1609.344, MILE: 1609.344, MILES: 1609.344, // Nautical NM: 1852, NAUTICAL_MILE: 1852, NAUTICAL_MILES: 1852, }, // Weight conversions (base: grams) weight: { // Metric MG: 0.001, MILLIGRAM: 0.001, MILLIGRAMS: 0.001, G: 1, GRAM: 1, GRAMS: 1, KG: 1000, KILOGRAM: 1000, KILOGRAMS: 1000, TONNE: 1000000, TONNES: 1000000, MT: 1000000, // Imperial OZ: 28.3495231, OUNCE: 28.3495231, OUNCES: 28.3495231, LB: 453.59237, LBS: 453.59237, POUND: 453.59237, POUNDS: 453.59237, ST: 6350.29318, STONE: 6350.29318, STONES: 6350.29318, TON: 907184.74, TONS: 907184.74, SHORT_TON: 907184.74, }, // Volume conversions (base: liters) volume: { // Metric ML: 0.001, MILLILITER: 0.001, MILLILITERS: 0.001, L: 1, LITER: 1, LITERS: 1, LITRE: 1, LITRES: 1, // US Liquid FL_OZ: 0.0295735, FLUID_OUNCE: 0.0295735, FLUID_OUNCES: 0.0295735, CUP: 0.236588, CUPS: 0.236588, PINT: 0.473176, PINTS: 0.473176, PT: 0.473176, QUART: 0.946353, QUARTS: 0.946353, QT: 0.946353, GALLON: 3.78541, GALLONS: 3.78541, GAL: 3.78541, // Imperial IMP_FL_OZ: 0.0284131, IMP_PINT: 0.568261, IMP_QUART: 1.13652, IMP_GALLON: 4.54609, }, // Area conversions (base: square meters) area: { // Metric SQ_MM: 0.000001, SQ_CM: 0.0001, SQ_M: 1, SQ_KM: 1000000, HECTARE: 10000, HA: 10000, // Imperial SQ_IN: 0.00064516, SQ_FT: 0.092903, SQ_YD: 0.836127, ACRE: 4046.86, ACRES: 4046.86, SQ_MILE: 2589988.11, }, // Temperature (special handling - no conversion factors) temperature: { C: 1, CELSIUS: 1, '°C': 1, F: 1, FAHRENHEIT: 1, '°F': 1, K: 1, KELVIN: 1, R: 1, RANKINE: 1, '°R': 1, }, // Time conversions (base: seconds) time: { MS: 0.001, MILLISECOND: 0.001, MILLISECONDS: 0.001, S: 1, SEC: 1, SECOND: 1, SECONDS: 1, MIN: 60, MINUTE: 60, MINUTES: 60, H: 3600, HR: 3600, HOUR: 3600, HOURS: 3600, D: 86400, DAY: 86400, DAYS: 86400, WK: 604800, WEEK: 604800, WEEKS: 604800, YR: 31536000, YEAR: 31536000, YEARS: 31536000, }, }; } /** * Get unit conversions object */ getUnitConversions() { return this.getSupportedUnits(); } /** * Get currency name */ getCurrencyName(code) { const names = { USD: 'US Dollar', EUR: 'Euro', GBP: 'British Pound', JPY: 'Japanese Yen', CAD: 'Canadian Dollar', AUD: 'Australian Dollar', CHF: 'Swiss Franc', CNY: 'Chinese Yuan', INR: 'Indian Rupee', KRW: 'South Korean Won', BRL: 'Brazilian Real', MXN: 'Mexican Peso', SGD: 'Singapore Dollar', HKD: 'Hong Kong Dollar', NOK: 'Norwegian Krone', SEK: 'Swedish Krona', DKK: 'Danish Krone', PLN: 'Polish Złoty', CZK: 'Czech Koruna', }; return names[code] || code; } } module.exports = new ConvertCommand();