currency-converter-lt
Advanced tools
Comparing version
293
index.js
const cheerio = require("cheerio") | ||
const got = require("got") | ||
const request = require("request") | ||
@@ -19,3 +19,3 @@ class CurrencyConverter { | ||
"BDT": "Bangladeshi Taka", | ||
"BYR": "Belarusian Ruble", | ||
"BYN": "Belarusian Ruble", | ||
"BZD": "Belize Dollar", | ||
@@ -26,3 +26,4 @@ "BMD": "Bermudan Dollar", | ||
"BAM": "Bosnia-Herzegovina Convertible Mark", | ||
"BWP": "Botswanan Pula", "BRL": "Brazilian Real", | ||
"BWP": "Botswanan Pula", | ||
"BRL": "Brazilian Real", | ||
"BND": "Brunei Dollar", | ||
@@ -157,137 +158,209 @@ "BGN": "Bulgarian Lev", | ||
} | ||
currencyCode = ["AFN", "ALL", "DZD", "AOA", "ARS", "AMD", "AWG", "AUD", "AZN", "BSD", "BHD", "BBD", "BDT", "BYR", "BZD", "BMD", "BTN", "XBT", "BOB", "BAM", "BWP", "BRL", "BND", "BGN", "BIF", "XPF", "KHR", "CAD", "CVE", "KYD", "FCFA", "CLP", "CLF", "CNY", "CNY", "COP", "CF", "CDF", "CRC", "HRK", "CUC", "CZK", "DKK", "DJF", "DOP", "XCD", "EGP", "ETB", "FJD", "GMD", "GBP", "GEL", "GHS", "GTQ", "GNF", "GYD", "HTG", "HNL", "HKD", "HUF", "ISK", "INR", "IDR", "IRR", "IQD", "ILS", "JMD", "JPY", "JOD", "KZT", "KES", "KWD", "KGS", "LAK", "LBP", "LSL", "LRD", "LYD", "MOP", "MKD", "MGA" , "MWK", "MYR", "MVR", "MRO", "MUR", "MXN", "MDL", "MAD", "MZN", "MMK", "NAD", "NPR", "ANG", "NZD", "NIO", "NGN", "NOK", "OMR", "PKR", "PAB", "PGK", "PYG", "PHP", "PLN", "QAR", "RON", "RUB", "RWF", "SVC", "SAR", "RSD", "SCR", "SLL", "SGD", "SBD", "SOS", "ZAR", "KRW", "VES", "LKR", "SDG", "SRD", "SZL", "SEK", "CHF", "TJS", "TZS", "THB", "TOP", "TTD", "TND", "TRY" , "TMT", "UGX", "UAH", "AED", "USD", "UYU", "UZS", "VND", "XOF", "YER", "ZMW", "ETH", "EUR", "LTC", "TWD", "PEN"] | ||
currencyCode = ["AFN", "ALL", "DZD", "AOA", "ARS", "AMD", "AWG", "AUD", "AZN", "BSD", "BHD", "BBD", "BDT", "BYN", "BZD", "BMD", "BTN", "XBT", "BOB", "BAM", "BWP", "BRL", "BND", "BGN", "BIF", "XPF", "KHR", "CAD", "CVE", "KYD", "FCFA", "CLP", "CLF", "CNY", "CNY", "COP", "CF", "CDF", "CRC", "HRK", "CUC", "CZK", "DKK", "DJF", "DOP", "XCD", "EGP", "ETB", "FJD", "GMD", "GBP", "GEL", "GHS", "GTQ", "GNF", "GYD", "HTG", "HNL", "HKD", "HUF", "ISK", "INR", "IDR", "IRR", "IQD", "ILS", "JMD", "JPY", "JOD", "KZT", "KES", "KWD", "KGS", "LAK", "LBP", "LSL", "LRD", "LYD", "MOP", "MKD", "MGA" , "MWK", "MYR", "MVR", "MRO", "MUR", "MXN", "MDL", "MAD", "MZN", "MMK", "NAD", "NPR", "ANG", "NZD", "NIO", "NGN", "NOK", "OMR", "PKR", "PAB", "PGK", "PYG", "PHP", "PLN", "QAR", "RON", "RUB", "RWF", "SVC", "SAR", "RSD", "SCR", "SLL", "SGD", "SBD", "SOS", "ZAR", "KRW", "VES", "LKR", "SDG", "SRD", "SZL", "SEK", "CHF", "TJS", "TZS", "THB", "TOP", "TTD", "TND", "TRY" , "TMT", "UGX", "UAH", "AED", "USD", "UYU", "UZS", "VND", "XOF", "YER", "ZMW", "ETH", "EUR", "LTC", "TWD", "PEN"] | ||
constructor(params) { | ||
this.currencyFrom = "" | ||
this.currencyTo = "" | ||
this.currencyAmount = 1 | ||
this.convertedValue = 0 | ||
this.isDecimalComma = false | ||
constructor(params) { | ||
this.currencyFrom = "" | ||
this.currencyTo = "" | ||
this.currencyAmount = 1 | ||
this.convertedValue = 0 | ||
this.isDecimalComma = false; | ||
this.isRatesCaching = false; | ||
this.ratesCacheDuration = 0; | ||
this.ratesCache = {}; | ||
if(params != undefined){ | ||
if(params["from"] !== undefined) | ||
this.from(params["from"]) | ||
if (params != undefined) { | ||
if (params["from"] !== undefined) | ||
this.from(params["from"]) | ||
if(params["to"] !== undefined) | ||
this.to(params["to"]) | ||
if(params["amount"] !== undefined) | ||
this.amount(params["amount"]) | ||
if (params["to"] !== undefined) | ||
this.to(params["to"]) | ||
if(params["isDecimalComma"] !== undefined) | ||
this.setDecimalComma(params["isDecimalComma"]) | ||
} | ||
} | ||
from (currencyFrom) { | ||
if(typeof currencyFrom !== "string") | ||
throw new TypeError("currency code should be a string") | ||
if(!this.currencyCode.includes(currencyFrom.toUpperCase())) | ||
throw new Error(`${currencyFrom} is not a valid currency code`) | ||
if (params["amount"] !== undefined) | ||
this.amount(params["amount"]) | ||
this.currencyFrom = currencyFrom.toUpperCase() | ||
return this | ||
if (params["isDecimalComma"] !== undefined) | ||
this.setDecimalComma(params["isDecimalComma"]) | ||
} | ||
to (currencyTo) { | ||
if(typeof currencyTo !== "string") | ||
throw new TypeError("currency code should be a string") | ||
} | ||
from(currencyFrom) { | ||
if (typeof currencyFrom !== "string") | ||
throw new TypeError("currency code should be a string") | ||
if(!this.currencyCode.includes(currencyTo.toUpperCase())) | ||
throw new Error(`${currencyTo} is not a valid currency code`) | ||
if (!this.currencyCode.includes(currencyFrom.toUpperCase())) | ||
throw new Error(`${currencyFrom} is not a valid currency code`) | ||
this.currencyTo = currencyTo | ||
return this | ||
} | ||
amount (currencyAmount){ | ||
if(typeof currencyAmount !== "number") | ||
throw new TypeError("amount should be a number") | ||
this.currencyFrom = currencyFrom.toUpperCase() | ||
return this | ||
} | ||
to(currencyTo) { | ||
if (typeof currencyTo !== "string") | ||
throw new TypeError("currency code should be a string") | ||
if(currencyAmount <= 0) | ||
throw new Error("amount should be a positive number") | ||
this.currencyAmount = currencyAmount | ||
return this | ||
} | ||
if (!this.currencyCode.includes(currencyTo.toUpperCase())) | ||
throw new Error(`${currencyTo} is not a valid currency code`) | ||
setDecimalComma (isDecimalComma){ | ||
if(typeof isDecimalComma !== "boolean") | ||
throw new TypeError("isDecimalComma should be a boolean") | ||
this.isDecimalComma = isDecimalComma | ||
return this | ||
this.currencyTo = currencyTo | ||
return this | ||
} | ||
amount(currencyAmount) { | ||
if (typeof currencyAmount !== "number") | ||
throw new TypeError("amount should be a number") | ||
if (currencyAmount <= 0) | ||
throw new Error("amount should be a positive number") | ||
this.currencyAmount = currencyAmount | ||
return this | ||
} | ||
setDecimalComma(isDecimalComma) { | ||
if (typeof isDecimalComma !== "boolean") | ||
throw new TypeError("isDecimalComma should be a boolean") | ||
this.isDecimalComma = isDecimalComma | ||
return this | ||
} | ||
replaceAll(text, queryString, replaceString) { | ||
let text_ = "" | ||
for (let i = 0; i < text.length; i++) { | ||
if (text[i] === queryString) { | ||
text_ += replaceString | ||
} else { | ||
text_ += text[i] | ||
} | ||
} | ||
return text_ | ||
} | ||
replaceAll(text, queryString, replaceString) { | ||
let text_ = "" | ||
for (let i = 0; i < text.length; i++) { | ||
if (text[i] === queryString){ | ||
text_ += replaceString | ||
setupRatesCache(ratesCacheOptions) { | ||
if (typeof ratesCacheOptions != "object") | ||
throw new TypeError("ratesCacheOptions should be an object") | ||
if (ratesCacheOptions.isRatesCaching === undefined) | ||
throw new Error(`ratesCacheOptions should have a property called isRatesCaching`) | ||
if (typeof ratesCacheOptions.isRatesCaching != "boolean") | ||
throw new TypeError("ratesCacheOptions.isRatesCaching should be a boolean") | ||
if (typeof ratesCacheOptions.ratesCacheDuration != "number") | ||
throw new TypeError("ratesCacheOptions.ratesCacheDuration should be a number") | ||
if (ratesCacheOptions.ratesCacheDuration <= 0) | ||
throw new Error("ratesCacheOptions.ratesCacheDuration should be a positive number of seconds") | ||
this.isRatesCaching = ratesCacheOptions.isRatesCaching; | ||
if (ratesCacheOptions.ratesCacheDuration === undefined) | ||
this.ratesCacheDuration = 3600; // Defaults to 3600 seconds (1 hour) | ||
else | ||
this.ratesCacheDuration = ratesCacheOptions.ratesCacheDuration; | ||
return this | ||
} | ||
rates() { | ||
if (this.currencyFrom === this.currencyTo) { | ||
return new Promise((resolve, _) => { | ||
resolve(1) | ||
}) | ||
} else { | ||
let currencyPair = this.currencyFrom.toUpperCase() + this.currencyTo.toUpperCase(); | ||
let now = new Date(); | ||
if (currencyPair in this.ratesCache && now < this.ratesCache[currencyPair].expiryDate) { | ||
return new Promise((resolve, _) => { | ||
resolve(this.ratesCache[currencyPair].rate); | ||
}); | ||
} else { | ||
return new Promise((resolve, reject) => { | ||
request(`https://www.google.com/search?q=${this.currencyFrom}+to+${this.currencyTo}+&hl=en`, function(error, response, body) { | ||
if (error) { | ||
return reject(error); | ||
} else { | ||
resolve(body); | ||
} | ||
}); | ||
}).then((body) => { | ||
return cheerio.load(body) | ||
}) | ||
.then(($) => { | ||
return $(".iBp4i").text().split(" ")[0] | ||
}) | ||
.then((rates) => { | ||
if (this.isDecimalComma) { | ||
if (rates.includes(".")) | ||
rates = this.replaceAll(rates, ".", "") | ||
if (rates.includes(",")) | ||
rates = this.replaceAll(rates, ",", ".") | ||
} else { | ||
if (rates.includes(",")) | ||
rates = this.replaceAll(rates, ",", "") | ||
} | ||
else{ | ||
text_ += text[i] | ||
if (this.isRatesCaching) { | ||
this.addRateToRatesCache(currencyPair, parseFloat(rates)); | ||
} | ||
} | ||
return text_ | ||
return parseFloat(rates) | ||
}) | ||
} | ||
} | ||
} | ||
rates(){ | ||
if(this.currencyFrom === this.currencyTo) | ||
return new Promise((resolve, _) => {resolve(this.currencyAmount) }) | ||
else | ||
return got(`https://www.google.co.in/search?q=${this.currencyAmount}+${this.currencyFrom}+to+${this.currencyTo}+&hl=en`) | ||
.then((html) => { | ||
return cheerio.load(html.body)}) | ||
.then(($) => {return $(".iBp4i").text().split(" ")[0]}) | ||
.then((rates) => { | ||
if(this.isDecimalComma){ | ||
if(rates.includes(".")) | ||
rates = this.replaceAll(rates, ".", "") | ||
if(rates.includes(",")) | ||
rates = this.replaceAll(rates, ",", ".") | ||
} | ||
else{ | ||
if(rates.includes(",")) | ||
rates = this.replaceAll(rates, ",", "") | ||
} | ||
return parseFloat(rates) | ||
}) | ||
convert(currencyAmount) { | ||
if (currencyAmount !== undefined) { | ||
this.amount(currencyAmount) | ||
} | ||
convert(currencyAmount){ | ||
if(currencyAmount !== undefined){ | ||
this.amount(currencyAmount) | ||
} | ||
if (this.currencyFrom == "") | ||
throw new Error("currency code cannot be an empty string") | ||
if(this.currencyFrom == "") | ||
throw new Error("currency code cannot be an empty string") | ||
if (this.currencyTo == "") | ||
throw new Error("currency code cannot be an empty string") | ||
if(this.currencyTo == "") | ||
throw new Error("currency code cannot be an empty string") | ||
if (this.currencyAmount == 0) | ||
throw new Error("currency amount should be a positive value") | ||
if(this.currencyAmount == 0) | ||
throw new Error("currency amount should be a positive value") | ||
return this.rates().then((rates) => { | ||
this.convertedValue = rates * this.currencyAmount | ||
return this.convertedValue | ||
}) | ||
} | ||
return this.rates().then((rates) =>{ | ||
// this.convertedValue = rates * this.currencyAmount | ||
currencyName(currencyCode_) { | ||
if (typeof currencyCode_ != "string") | ||
throw new TypeError("currency code should be a string") | ||
// as the google result now sends the exact converted | ||
// currency, multiplying the rates with currencyAmount | ||
// makes it redundant. | ||
this.convertedValue = rates * 1 | ||
return this.convertedValue | ||
}) | ||
} | ||
if (!this.currencyCode.includes(currencyCode_.toUpperCase())) | ||
throw new Error(`${currencyCode_} is not a valid currency code`) | ||
currencyName(currencyCode_){ | ||
if(typeof currencyCode_ != "string") | ||
throw new TypeError("currency code should be a string") | ||
if(!this.currencyCode.includes(currencyCode_.toUpperCase())) | ||
throw new Error(`${currencyCode_} is not a valid currency code`) | ||
return this.currencies[currencyCode_] | ||
} | ||
return this.currencies[currencyCode_] | ||
addRateToRatesCache(currencyPair, rate_) { | ||
if (typeof currencyPair != "string") | ||
throw new TypeError("currency pair should be a string") | ||
if (typeof rate_ != "number") | ||
throw new TypeError("rate should be a number") | ||
let now = new Date(); | ||
if (currencyPair in this.ratesCache) { | ||
if (now > this.ratesCache[currencyPair].expiryDate) { | ||
let newExpiry = new Date(); | ||
newExpiry.setSeconds(newExpiry.getSeconds() + this.ratesCacheDuration); | ||
this.ratesCache[currencyPair] = { | ||
rate: rate_, | ||
expiryDate: newExpiry | ||
}; | ||
} | ||
} else { | ||
let newExpiry = new Date(); | ||
newExpiry.setSeconds(newExpiry.getSeconds() + this.ratesCacheDuration); | ||
this.ratesCache[currencyPair] = { | ||
rate: rate_, | ||
expiryDate: newExpiry | ||
}; | ||
} | ||
} | ||
} | ||
module.exports = CurrencyConverter |
{ | ||
"name": "currency-converter-lt", | ||
"version": "1.3.1", | ||
"version": "2.0.0-beta.0", | ||
"description": "A nodejs currency converter library that doesn't require subscribing to any API calls.", | ||
@@ -8,3 +8,3 @@ "main": "index.js", | ||
"cheerio": "latest", | ||
"got": "11.8.2" | ||
"request": "^2.88.2" | ||
}, | ||
@@ -11,0 +11,0 @@ "devDependencies": { |
<div align="center"> | ||
<h1>NodeJS Currency Converter</h1> | ||
[](https://travis-ci.com/paul-shuvo/nodejs-currency-converter) [](https://snyk.io/test/github/paul-shuvo/nodejs-currency-converter?targetFile=package.json)  [](https://codecov.io/gh/paul-shuvo/nodejs-currency-converter) | ||
 [](https://codeclimate.com/github/paul-shuvo/nodejs-currency-converter/maintainability) [](https://badge.fury.io/js/currency-converter-lt)  | ||
 [](https://snyk.io/test/github/paul-shuvo/nodejs-currency-converter?targetFile=package.json)  [](https://codecov.io/gh/paul-shuvo/nodejs-currency-converter) | ||
 [](https://badge.fury.io/js/currency-converter-lt)  | ||
<p>A minimal currency converter library for NodeJS that works out of the box.</p> | ||
</div> | ||
<!-- [](https://codeclimate.com/github/paul-shuvo/nodejs-currency-converter/maintainability) --> | ||
<!--  --> | ||
__Announcement__ : For crypto currency conversion, check my other package [Nodejs Crypto Converter](https://github.com/paul-shuvo/nodejs-crypto-converter). | ||
@@ -78,2 +81,21 @@ | ||
Rates can be cached for currency pairs. To implement rate caching, instantiate an object of CurrencyConverter only once in your project, in a CurrencyConverter file, and setup rates caching then import the instance of CurrencyConverter from the CurrencyConverter file in your project across the rest of your project. Use chaining to convert currencies when caching is implemented. Below is an example of a CurrencyConverter file. | ||
Note: Rates are not actually deleted after the ratesCacheDuration. The rate remains in the rates cache of the CurrencyConverter object until a request is made for the same currency pair at which point, the old rate is overwritten. | ||
```javascript | ||
const CC = require('currency-converter-lt') | ||
let currencyConverter = new CC() | ||
let ratesCacheOptions = { | ||
isRatesCaching: true, // Set this boolean to true to implement rate caching | ||
ratesCacheDuration: 3600 // Set this to a positive number to set the number of seconds you want the rates to be cached. Defaults to 3600 seconds (1 hour) | ||
} | ||
currencyConverter = currencyConverter.setupRatesCache(ratesCacheOptions) | ||
module.exports = currencyConverter | ||
``` | ||
Chaining is also supported. | ||
@@ -87,3 +109,5 @@ | ||
## Disclaimer | ||
This package uses web scraping to provide the api. | ||
@@ -90,0 +114,0 @@ ## Issues |
@@ -20,3 +20,3 @@ const chai = require("chai") | ||
}) | ||
it("should instantiate an object with json object as a parameter", () => { | ||
@@ -182,2 +182,58 @@ let CC_ = new CC({from:"GBP", to:"CAD", amount: 100}) | ||
}) | ||
describe("setupRatesCache", () => { | ||
it("should throw a TypeError", () => { | ||
expect(() => currencyConverter.setupRatesCache(5)).to.throw(TypeError); | ||
}) | ||
it("should throw a TypeError", () => { | ||
let ratesCacheOptions = { | ||
isRatesCaching: 3 | ||
} | ||
expect(() => currencyConverter.setupRatesCache(ratesCacheOptions)).to.throw(TypeError); | ||
}) | ||
it("should throw a TypeError", () => { | ||
let ratesCacheOptions = { | ||
isRatesCaching: true, | ||
ratesCacheDuration: "10" | ||
} | ||
expect(() => currencyConverter.setupRatesCache(ratesCacheOptions)).to.throw(TypeError); | ||
}) | ||
it("should throw an Error", () => { | ||
let ratesCacheOptions = { | ||
ratesCacheDuration: 50 | ||
} | ||
expect(() => currencyConverter.setupRatesCache(ratesCacheOptions)).to.throw(Error); | ||
}) | ||
it("should throw an Error", () => { | ||
let ratesCacheOptions = { | ||
isRatesCaching: true, | ||
ratesCacheDuration: -50 | ||
} | ||
expect(() => currencyConverter.setupRatesCache(ratesCacheOptions)).to.throw(Error); | ||
}) | ||
}) | ||
describe("addRateToRatesCache", () => { | ||
it("should throw an error", () => { | ||
let ratesCacheOptions = { | ||
isRatesCaching: true, | ||
ratesCacheDuration: 3600 | ||
} | ||
currencyConverter.setupRatesCache(ratesCacheOptions); | ||
expect(() => currencyConverter.addRateToRatesCache("USDCAD", "0.31")).to.throw(Error); | ||
}) | ||
it("should throw an error", () => { | ||
let ratesCacheOptions = { | ||
isRatesCaching: true, | ||
ratesCacheDuration: 3600 | ||
} | ||
currencyConverter.setupRatesCache(ratesCacheOptions); | ||
expect(() => currencyConverter.addRateToRatesCache(100, "0.31")).to.throw(Error); | ||
}) | ||
}) | ||
}) | ||
@@ -188,2 +244,2 @@ | ||
// console.log(c.currencies) | ||
// console.log(c.currencies) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
30160
23.82%526
27.67%119
25.26%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed