@tamtamchik/exchanger
Version:
Simple and free npm library to get realtime currency exchange rates.
94 lines (92 loc) • 3.1 kB
JavaScript
// src/errors.ts
var ApplicationError = class extends Error {
constructor(errorType, errorMessage) {
super(errorMessage);
this.name = errorType;
this.captureStackTrace();
}
captureStackTrace() {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
};
var NetworkError = class extends ApplicationError {
constructor(message) {
super("NetworkError", message);
}
};
var ServerError = class extends ApplicationError {
constructor(message) {
super("ServerError", message);
}
};
var DataError = class extends ApplicationError {
constructor(message) {
super("DataError", message);
}
};
// src/index.ts
var YAHOO_FINANCE_BASE_URL = "https://query1.finance.yahoo.com/v8/finance/chart/";
var YAHOO_FINANCE_QUERY_PARAMS = "=X?region=US&lang=en-US&includePrePost=false&interval=2m&useYfid=true&range=1d&corsDomain=finance.yahoo.com&.tsrc=finance";
var rateCache = /* @__PURE__ */ new Map();
function buildRateUrl(fromCurrency, toCurrency) {
return `${YAHOO_FINANCE_BASE_URL}${fromCurrency.toUpperCase()}${toCurrency.toUpperCase()}${YAHOO_FINANCE_QUERY_PARAMS}`;
}
function isCacheValid(cachedRate, cacheDurationMs) {
return Date.now() - cachedRate.timestamp < cacheDurationMs;
}
function getCachedRate(fromCurrency, toCurrency, cacheDurationMs) {
if (!cacheDurationMs) return null;
const cacheKey = `${fromCurrency}-${toCurrency}`;
const cachedRate = rateCache.get(cacheKey);
return cachedRate && isCacheValid(cachedRate, cacheDurationMs) ? cachedRate.value : null;
}
async function fetchExchangeRateResponse(rateUrl) {
const response = await fetch(rateUrl);
if (!response.ok) {
throw new ServerError(`HTTP ${response.status}: ${response.statusText}`);
}
return response;
}
function extractRateFromResponse(response) {
const rate = response.chart?.result[0]?.meta?.regularMarketPrice;
if (typeof rate !== "number" || isNaN(rate)) {
throw new DataError('Invalid or missing "regularMarketPrice" in response.');
}
return rate;
}
async function fetchExchangeRate(rateUrl) {
try {
const response = await fetchExchangeRateResponse(rateUrl);
const responseData = await response.json();
return extractRateFromResponse(responseData);
} catch (error) {
if (error instanceof ServerError || error instanceof DataError) {
throw error;
}
throw new NetworkError(
`Failed to fetch exchange rate: ${error instanceof Error ? error.message : String(error)}`
);
}
}
async function getExchangeRate(fromCurrency, toCurrency, options = {}) {
const { cacheDurationMs } = options;
const cachedRate = getCachedRate(fromCurrency, toCurrency, cacheDurationMs);
if (cachedRate !== null) {
return cachedRate;
}
const rateUrl = buildRateUrl(fromCurrency, toCurrency);
const rate = await fetchExchangeRate(rateUrl);
if (cacheDurationMs) {
const cacheKey = `${fromCurrency}-${toCurrency}`;
rateCache.set(cacheKey, { value: rate, timestamp: Date.now() });
}
return rate;
}
export {
DataError,
NetworkError,
ServerError,
getExchangeRate
};