UNPKG

easy-currencies

Version:

A tool for easy conversion of currencies.

250 lines (239 loc) 6.61 kB
/** * A map for provider information * * @interface Providers */ export interface Providers { [name: string]: Provider; } /** * Provider error entry * * @export * @interface ProviderErrors */ export interface ProviderErrors { [code: string]: string; } /** * Object that describes a user-defined provider. * * @export * @interface UserDefinedProvider */ export interface UserDefinedProvider { name: string; provider: Provider; } /** * Single provider interface. * Used to store pre-constructed query templates for various currency rate providers. * @export * @interface Provider */ export interface Provider { /** * An API key / Profile ID / Access key for a provider. * * @type {*} * @memberof Provider */ key: any; /** * Endpoint configuration object for a provider: * The base template is the root of the access URL, with a place for access key in the form of %KEY% (if needed) * The single template is used for single currency conversions, requires a %FROM% and a %TO% to be present. * The multiple template is currently unused. * @type {{ base: string; single: string; multiple: string }} * @memberof Provider */ endpoint: { base: string; single: string; multiple: string }; /** * A function that returns a map of currencies from the data object returned by axios (response.data) * * @example * function(data) { //must return {currency1:rate1,curency2:rate2} in reference to the base currency. * return data.rates; * } * * @type {Function} * @memberof Provider */ handler: Function; /** * A map of possible errors and their respective messages * * @type {*} * @memberof Provider */ errors: ProviderErrors; /** * A unique method to resolve errors, if any. * Some APIs return their errors via success responses, others via HTTP failures. * These two modes are mutually exclusive; The data passed to the errorHandler is: * the response.data object, in the case of 'success' failures * the response object, in the case of Axios errors (HTTP failures) * * @type {Function} * @memberof Provider */ errorHandler: (data: any) => number | string | null; } /** * An interface for an object that is used to configure providers * * @export * @interface ProviderReference */ export interface ProviderReference { name: string; key: any; } /** * A function that constructs provider based on raw input data. * * @export * @param {ProviderReference} provider object containing provider name and api key * @returns {Provider} constructed provider */ export function resolveProvider(provider: ProviderReference): Provider { const existentProvider = providers[provider.name]; if (!existentProvider) { throw "No provider with this name. Please use a provider from the supported providers list."; } // attaching key existentProvider.key = provider.key; return existentProvider; } /** * Provider map initialization */ export const providers: Providers = { ExchangeRateAPI: { endpoint: { base: "https://api.exchangerate-api.com/v4/latest/", single: "%FROM%", multiple: "%FROM%" }, key: undefined, handler: function (data: any) { return data.rates; }, errors: { 400: "Malformed query.", 404: "Currency not found" }, errorHandler: function (data: any) { return data.status; } }, ExchangeRatesAPIIO: { endpoint: { base: "http://api.exchangeratesapi.io/latest?access_key=%KEY%", single: "&base=%FROM%&symbols=%TO%", multiple: "&base=%FROM%" }, errors: { 105: "A paid plan is required in order to use other base currencies!", 101: "Invalid API key!", 201: "Invalid base currency." }, key: undefined, handler: function (data: any) { return data.rates; }, errorHandler: function (data: any) { return data.status; } }, CurrencyLayer: { endpoint: { base: "http://apilayer.net/api/live?access_key=%KEY%", single: "&source=%FROM%", multiple: "&source=%FROM%&currencies=%TO%" }, key: undefined, handler: function (data: any) { const map = {} as any; Object.keys(data.quotes).map((key) => { map[key.slice(3)] = data.quotes[key]; }); return map; }, errors: { 105: "A paid plan is required in order to use CurrencyLayer (base currency use not allowed)", 101: "Invalid API key!", 201: "Invalid base currency.", 106: "No results." }, errorHandler: function (data: any) { return data.error ? data.error.code : null; } }, OpenExchangeRates: { endpoint: { base: "https://openexchangerates.org/api/latest.json?app_id=%KEY%", single: "&base=%FROM%", multiple: "&base=%FROM%" }, key: undefined, handler: function (data: any) { return data.rates; }, errors: { 401: "Invalid API key!" }, errorHandler: function (data: any) { return data.status; } }, AlphaVantage: { endpoint: { base: "https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&apikey=%KEY%", single: "&from_currency=%FROM%&to_currency=%TO%", multiple: "" }, key: undefined, handler: function (data: any) { const map = {} as any; const o = data[Object.keys(data)[0]]; map[o["3. To_Currency Code"]] = o["5. Exchange Rate"]; return map; }, errors: { 503: "Invalid API key or Malformed query." }, errorHandler: function (data: any) { if (!data) { return null; } // AlphaVantage does not return error codes in the response, // so we have to check if the response contains error messages // and translate them to error codes if possible. const hasError = data["Error Message"] || data["Information"]; if (hasError?.includes("API rate limit")) { return 429; } if (hasError) { return hasError; } return null; } }, Fixer: { endpoint: { base: "http://data.fixer.io/api/latest?access_key=%KEY%", single: "&base=%FROM%&symbols=%TO%", multiple: "&base=%FROM%" }, key: undefined, handler: function (data: any) { return data.rates; }, errors: { 105: "A paid plan is required in order to use Fixer.io (base currency use not allowed)", 101: "Invalid API key!", 201: "Invalid base currency." }, errorHandler: function (data: any) { return data.error ? data.error.code : null; } } };