ropods-cashify
Version:
Modern, lightweight currency conversion library with real-time exchange rates, INR support, and free API integration. Production-ready TypeScript library for RoPods organization with zero dependencies and comprehensive testing.
174 lines • 5.8 kB
JavaScript
/**
* RoPods Rate Fetcher Service
* Fetches latest exchange rates from multiple sources
*/
export class RoPodsRateFetcher {
static instance;
cache = new Map();
cacheTimeout = 5 * 60 * 1000; // 5 minutes cache
sources = [
{
name: 'ExchangeRate-API',
url: 'https://api.exchangerate-api.com/v4/latest/',
},
{
name: 'Fixer.io',
url: 'http://data.fixer.io/api/latest',
apiKey: process.env['FIXER_API_KEY'],
},
{
name: 'CurrencyAPI',
url: 'https://api.currencyapi.com/v3/latest',
apiKey: process.env['CURRENCY_API_KEY'],
},
];
static getInstance() {
if (!RoPodsRateFetcher.instance) {
RoPodsRateFetcher.instance = new RoPodsRateFetcher();
}
return RoPodsRateFetcher.instance;
}
/**
* Get latest exchange rates for RoPods
* @param base Base currency (default: USD)
* @param currencies Array of currencies to fetch
* @returns Promise<ExchangeRates>
*/
async getLatestRates(base = 'USD', currencies = ['EUR', 'GBP', 'INR', 'JPY', 'CAD', 'AUD', 'CHF']) {
const cacheKey = `${base}-${currencies.join(',')}`;
const cached = this.cache.get(cacheKey);
if (cached && this.isCacheValid(cached)) {
console.log('[RoPods Cashify] Using cached rates');
return cached;
}
try {
const rates = await this.fetchFromSources(base, currencies);
this.cache.set(cacheKey, rates);
console.log('[RoPods Cashify] Fetched fresh rates from', rates.source);
return rates;
}
catch (error) {
console.warn('[RoPods Cashify] Failed to fetch rates, using fallback');
return this.getFallbackRates(base);
}
}
/**
* Get RoPods specific currency rates (INR, USD focus)
*/
async getRoPodsRates() {
const ropodsCurrencies = ['INR', 'USD', 'EUR', 'GBP', 'AED', 'SGD', 'JPY'];
return this.getLatestRates('USD', ropodsCurrencies);
}
async fetchFromSources(base, currencies) {
for (const source of this.sources) {
try {
const rates = await this.fetchFromSource(source, base, currencies);
if (rates)
return rates;
}
catch (error) {
console.warn(`[RoPods Cashify] Failed to fetch from ${source.name}:`, error);
continue;
}
}
throw new Error('All rate sources failed');
}
async fetchFromSource(source, base, currencies) {
let url = source.url;
if (source.name === 'ExchangeRate-API') {
url = `${source.url}${base}`;
}
else if (source.name === 'Fixer.io' && source.apiKey) {
url = `${source.url}?access_key=${source.apiKey}&base=${base}&symbols=${currencies.join(',')}`;
}
else if (source.name === 'CurrencyAPI' && source.apiKey) {
url = `${source.url}?apikey=${source.apiKey}&base_currency=${base}¤cies=${currencies.join(',')}`;
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
if (source.name === 'ExchangeRate-API') {
return {
base: data.base,
rates: this.filterRates(data.rates, currencies),
lastUpdated: new Date().toISOString(),
source: source.name,
};
}
if (source.name === 'Fixer.io') {
return {
base: data.base,
rates: this.filterRates(data.rates, currencies),
lastUpdated: data.date || new Date().toISOString(),
source: source.name,
};
}
return null;
}
filterRates(allRates, currencies) {
const filtered = {};
for (const currency of currencies) {
if (allRates[currency]) {
filtered[currency] = allRates[currency];
}
}
return filtered;
}
isCacheValid(cached) {
const cacheTime = new Date(cached.lastUpdated).getTime();
return Date.now() - cacheTime < this.cacheTimeout;
}
getFallbackRates(base) {
// Fallback rates updated as of January 2025 (approximate)
const fallbackRates = {
USD: {
EUR: 0.95,
GBP: 0.82,
INR: 85.20,
JPY: 157.50,
CAD: 1.44,
AUD: 1.62,
CHF: 0.92,
AED: 3.67,
SGD: 1.37,
},
EUR: {
USD: 1.05,
GBP: 0.86,
INR: 89.60,
JPY: 165.40,
CAD: 1.51,
AUD: 1.70,
CHF: 0.97,
},
};
return {
base,
rates: fallbackRates[base] || fallbackRates['USD'] || {},
lastUpdated: new Date().toISOString(),
source: 'RoPods Fallback',
};
}
/**
* Clear cache to force fresh fetch
*/
clearCache() {
this.cache.clear();
console.log('[RoPods Cashify] Cache cleared');
}
/**
* Get cache status
*/
getCacheInfo() {
return Array.from(this.cache.entries()).map(([key, value]) => ({
key,
lastUpdated: value.lastUpdated,
source: value.source,
}));
}
}
// Export singleton instance
export const ropodsRateFetcher = RoPodsRateFetcher.getInstance();
//# sourceMappingURL=rate-fetcher.js.map