dinero.js 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +316 -0
- package/build/amd/dinero.js +1659 -0
- package/build/amd/dinero.min.js +1 -0
- package/build/amd/dinero.polyfilled.js +3964 -0
- package/build/amd/dinero.polyfilled.min.js +1 -0
- package/build/cjs/dinero.js +1657 -0
- package/build/cjs/dinero.min.js +1 -0
- package/build/cjs/dinero.polyfilled.js +3962 -0
- package/build/cjs/dinero.polyfilled.min.js +1 -0
- package/build/esm/dinero.js +1655 -0
- package/build/esm/dinero.min.js +1 -0
- package/build/esm/dinero.polyfilled.js +3960 -0
- package/build/esm/dinero.polyfilled.min.js +1 -0
- package/build/umd/dinero.js +1663 -0
- package/build/umd/dinero.min.js +1 -0
- package/build/umd/dinero.polyfilled.js +3968 -0
- package/build/umd/dinero.polyfilled.min.js +1 -0
- package/package.json +83 -0
- package/src/dinero-polyfilled.js +13 -0
- package/src/dinero.js +970 -0
- package/src/services/assert.js +59 -0
- package/src/services/calculator.js +122 -0
- package/src/services/currency-converter.js +38 -0
- package/src/services/format.js +76 -0
- package/src/services/helpers.js +193 -0
- package/src/services/settings.js +62 -0
- package/src/services/static.js +103 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { isPercentage, areValidRatios } from './helpers'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Performs an assertion.
|
|
5
|
+
* @ignore
|
|
6
|
+
*
|
|
7
|
+
* @param {Boolean} condition - The expression to assert.
|
|
8
|
+
* @param {String} errorMessage - The message to throw if the assertion fails
|
|
9
|
+
* @param {ErrorConstructor} [ErrorType=Error] - The error to throw if the assertion fails.
|
|
10
|
+
*
|
|
11
|
+
* @throws {Error} If `condition` returns `false`.
|
|
12
|
+
*/
|
|
13
|
+
export function assert(condition, errorMessage, ErrorType = Error) {
|
|
14
|
+
if (!condition) throw new ErrorType(errorMessage)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Asserts a value is a percentage.
|
|
19
|
+
* @ignore
|
|
20
|
+
*
|
|
21
|
+
* @param {} percentage - The percentage to test.
|
|
22
|
+
*
|
|
23
|
+
* @throws {RangeError} If `percentage` is out of range.
|
|
24
|
+
*/
|
|
25
|
+
export function assertPercentage(percentage) {
|
|
26
|
+
assert(
|
|
27
|
+
isPercentage(percentage),
|
|
28
|
+
'You must provide a numeric value between 0 and 100.',
|
|
29
|
+
RangeError
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Asserts an array of ratios is valid.
|
|
35
|
+
* @ignore
|
|
36
|
+
*
|
|
37
|
+
* @param {} ratios - The ratios to test.
|
|
38
|
+
*
|
|
39
|
+
* @throws {TypeError} If `ratios` are invalid.
|
|
40
|
+
*/
|
|
41
|
+
export function assertValidRatios(ratios) {
|
|
42
|
+
assert(
|
|
43
|
+
areValidRatios(ratios),
|
|
44
|
+
'You must provide a non-empty array of numeric values greater than 0.',
|
|
45
|
+
TypeError
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Asserts a value is an integer.
|
|
51
|
+
* @ignore
|
|
52
|
+
*
|
|
53
|
+
* @param {} number - The value to test.
|
|
54
|
+
*
|
|
55
|
+
* @throws {TypeError}
|
|
56
|
+
*/
|
|
57
|
+
export function assertInteger(number) {
|
|
58
|
+
assert(Number.isInteger(number), 'You must provide an integer.', TypeError)
|
|
59
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { isEven, isFloat, countFractionDigits, isHalf } from './helpers'
|
|
2
|
+
|
|
3
|
+
export default function Calculator() {
|
|
4
|
+
const floatMultiply = (a, b) => {
|
|
5
|
+
const getFactor = number => Math.pow(10, countFractionDigits(number))
|
|
6
|
+
const factor = Math.max(getFactor(a), getFactor(b))
|
|
7
|
+
return (Math.round(a * factor) * Math.round(b * factor)) / (factor * factor)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const roundingModes = {
|
|
11
|
+
HALF_ODD(number) {
|
|
12
|
+
const rounded = Math.round(number)
|
|
13
|
+
return isHalf(number)
|
|
14
|
+
? isEven(rounded)
|
|
15
|
+
? rounded - 1
|
|
16
|
+
: rounded
|
|
17
|
+
: rounded
|
|
18
|
+
},
|
|
19
|
+
HALF_EVEN(number) {
|
|
20
|
+
const rounded = Math.round(number)
|
|
21
|
+
return isHalf(number)
|
|
22
|
+
? isEven(rounded)
|
|
23
|
+
? rounded
|
|
24
|
+
: rounded - 1
|
|
25
|
+
: rounded
|
|
26
|
+
},
|
|
27
|
+
HALF_UP(number) {
|
|
28
|
+
return Math.round(number)
|
|
29
|
+
},
|
|
30
|
+
HALF_DOWN(number) {
|
|
31
|
+
return isHalf(number) ? Math.floor(number) : Math.round(number)
|
|
32
|
+
},
|
|
33
|
+
HALF_TOWARDS_ZERO(number) {
|
|
34
|
+
return isHalf(number)
|
|
35
|
+
? Math.sign(number) * Math.floor(Math.abs(number))
|
|
36
|
+
: Math.round(number)
|
|
37
|
+
},
|
|
38
|
+
HALF_AWAY_FROM_ZERO(number) {
|
|
39
|
+
return isHalf(number)
|
|
40
|
+
? Math.sign(number) * Math.ceil(Math.abs(number))
|
|
41
|
+
: Math.round(number)
|
|
42
|
+
},
|
|
43
|
+
DOWN(number) {
|
|
44
|
+
return Math.floor(number)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
/**
|
|
50
|
+
* Returns the sum of two numbers.
|
|
51
|
+
* @ignore
|
|
52
|
+
*
|
|
53
|
+
* @param {Number} a - The first number to add.
|
|
54
|
+
* @param {Number} b - The second number to add.
|
|
55
|
+
*
|
|
56
|
+
* @return {Number}
|
|
57
|
+
*/
|
|
58
|
+
add(a, b) {
|
|
59
|
+
return a + b
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Returns the difference of two numbers.
|
|
63
|
+
* @ignore
|
|
64
|
+
*
|
|
65
|
+
* @param {Number} a - The first number to subtract.
|
|
66
|
+
* @param {Number} b - The second number to subtract.
|
|
67
|
+
*
|
|
68
|
+
* @return {Number}
|
|
69
|
+
*/
|
|
70
|
+
subtract(a, b) {
|
|
71
|
+
return a - b
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Returns the product of two numbers.
|
|
75
|
+
* @ignore
|
|
76
|
+
*
|
|
77
|
+
* @param {Number} a - The first number to multiply.
|
|
78
|
+
* @param {Number} b - The second number to multiply.
|
|
79
|
+
*
|
|
80
|
+
* @return {Number}
|
|
81
|
+
*/
|
|
82
|
+
multiply(a, b) {
|
|
83
|
+
return isFloat(a) || isFloat(b) ? floatMultiply(a, b) : a * b
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* Returns the quotient of two numbers.
|
|
87
|
+
* @ignore
|
|
88
|
+
*
|
|
89
|
+
* @param {Number} a - The first number to divide.
|
|
90
|
+
* @param {Number} b - The second number to divide.
|
|
91
|
+
*
|
|
92
|
+
* @return {Number}
|
|
93
|
+
*/
|
|
94
|
+
divide(a, b) {
|
|
95
|
+
return a / b
|
|
96
|
+
},
|
|
97
|
+
/**
|
|
98
|
+
* Returns the remainder of two numbers.
|
|
99
|
+
* @ignore
|
|
100
|
+
*
|
|
101
|
+
* @param {Number} a - The first number to divide.
|
|
102
|
+
* @param {Number} b - The second number to divide.
|
|
103
|
+
*
|
|
104
|
+
* @return {Number}
|
|
105
|
+
*/
|
|
106
|
+
modulo(a, b) {
|
|
107
|
+
return a % b
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Returns a rounded number based off a specific rounding mode.
|
|
111
|
+
* @ignore
|
|
112
|
+
*
|
|
113
|
+
* @param {Number} number - The number to round.
|
|
114
|
+
* @param {String} [roundingMode='HALF_EVEN'] - The rounding mode to use.
|
|
115
|
+
*
|
|
116
|
+
* @returns {Number}
|
|
117
|
+
*/
|
|
118
|
+
round(number, roundingMode = 'HALF_EVEN') {
|
|
119
|
+
return roundingModes[roundingMode](number)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getJSON, flattenObject, isThenable } from './helpers'
|
|
2
|
+
|
|
3
|
+
export default function CurrencyConverter(options) {
|
|
4
|
+
/* istanbul ignore next */
|
|
5
|
+
const mergeTags = (string = '', tags) => {
|
|
6
|
+
for (const tag in tags) {
|
|
7
|
+
string = string.replace(`{{${tag}}}`, tags[tag])
|
|
8
|
+
}
|
|
9
|
+
return string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* istanbul ignore next */
|
|
13
|
+
const getRatesFromRestApi = (from, to) =>
|
|
14
|
+
getJSON(mergeTags(options.endpoint, { from, to }), {
|
|
15
|
+
headers: options.headers
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
/**
|
|
20
|
+
* Returns the exchange rate.
|
|
21
|
+
* @ignore
|
|
22
|
+
*
|
|
23
|
+
* @param {String} from - The base currency.
|
|
24
|
+
* @param {String} to - The destination currency.
|
|
25
|
+
*
|
|
26
|
+
* @return {Promise}
|
|
27
|
+
*/
|
|
28
|
+
getExchangeRate(from, to) {
|
|
29
|
+
return (isThenable(options.endpoint)
|
|
30
|
+
? options.endpoint
|
|
31
|
+
: getRatesFromRestApi(from, to)
|
|
32
|
+
).then(
|
|
33
|
+
data =>
|
|
34
|
+
flattenObject(data)[mergeTags(options.propertyPath, { from, to })]
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Calculator from './calculator'
|
|
2
|
+
import { isUndefined } from './helpers'
|
|
3
|
+
|
|
4
|
+
const calculator = Calculator()
|
|
5
|
+
|
|
6
|
+
export default function Format(format) {
|
|
7
|
+
const matches = /^(?:(\$|USD)?0(?:(,)0)?(\.)?(0+)?|0(?:(,)0)?(\.)?(0+)?\s?(dollar)?)$/gm.exec(
|
|
8
|
+
format
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
/**
|
|
13
|
+
* Returns the matches.
|
|
14
|
+
* @ignore
|
|
15
|
+
*
|
|
16
|
+
* @return {Array}
|
|
17
|
+
*/
|
|
18
|
+
getMatches() {
|
|
19
|
+
return matches !== null
|
|
20
|
+
? matches.slice(1).filter(match => !isUndefined(match))
|
|
21
|
+
: []
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* Returns the amount of fraction digits to display.
|
|
25
|
+
* @ignore
|
|
26
|
+
*
|
|
27
|
+
* @return {Number}
|
|
28
|
+
*/
|
|
29
|
+
getMinimumFractionDigits() {
|
|
30
|
+
const decimalPosition = match => match === '.'
|
|
31
|
+
return !isUndefined(this.getMatches().find(decimalPosition))
|
|
32
|
+
? this.getMatches()[
|
|
33
|
+
calculator.add(this.getMatches().findIndex(decimalPosition), 1)
|
|
34
|
+
].split('').length
|
|
35
|
+
: 0
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Returns the currency display mode.
|
|
39
|
+
* @ignore
|
|
40
|
+
*
|
|
41
|
+
* @return {String}
|
|
42
|
+
*/
|
|
43
|
+
getCurrencyDisplay() {
|
|
44
|
+
const modes = {
|
|
45
|
+
USD: 'code',
|
|
46
|
+
dollar: 'name',
|
|
47
|
+
$: 'symbol'
|
|
48
|
+
}
|
|
49
|
+
return modes[
|
|
50
|
+
this.getMatches().find(match => {
|
|
51
|
+
return match === 'USD' || match === 'dollar' || match === '$'
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
/**
|
|
56
|
+
* Returns the formatting style.
|
|
57
|
+
* @ignore
|
|
58
|
+
*
|
|
59
|
+
* @return {String}
|
|
60
|
+
*/
|
|
61
|
+
getStyle() {
|
|
62
|
+
return !isUndefined(this.getCurrencyDisplay(this.getMatches()))
|
|
63
|
+
? 'currency'
|
|
64
|
+
: 'decimal'
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Returns whether grouping should be used or not.
|
|
68
|
+
* @ignore
|
|
69
|
+
*
|
|
70
|
+
* @return {Boolean}
|
|
71
|
+
*/
|
|
72
|
+
getUseGrouping() {
|
|
73
|
+
return !isUndefined(this.getMatches().find(match => match === ','))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether a value is numeric.
|
|
3
|
+
* @ignore
|
|
4
|
+
*
|
|
5
|
+
* @param {} value - The value to test.
|
|
6
|
+
*
|
|
7
|
+
* @return {Boolean}
|
|
8
|
+
*/
|
|
9
|
+
export function isNumeric(value) {
|
|
10
|
+
return !isNaN(parseInt(value)) && isFinite(value)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns whether a value is a percentage.
|
|
15
|
+
* @ignore
|
|
16
|
+
*
|
|
17
|
+
* @param {} percentage - The percentage to test.
|
|
18
|
+
*
|
|
19
|
+
* @return {Boolean}
|
|
20
|
+
*/
|
|
21
|
+
export function isPercentage(percentage) {
|
|
22
|
+
return isNumeric(percentage) && percentage <= 100 && percentage >= 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns whether an array of ratios is valid.
|
|
27
|
+
* @ignore
|
|
28
|
+
*
|
|
29
|
+
* @param {} ratios - The ratios to test.
|
|
30
|
+
*
|
|
31
|
+
* @return {Boolean}
|
|
32
|
+
*/
|
|
33
|
+
export function areValidRatios(ratios) {
|
|
34
|
+
return (
|
|
35
|
+
ratios.length > 0 &&
|
|
36
|
+
ratios.every(ratio => ratio >= 0) &&
|
|
37
|
+
ratios.some(ratio => ratio > 0)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns whether a value is even.
|
|
43
|
+
* @ignore
|
|
44
|
+
*
|
|
45
|
+
* @param {Number} value - The value to test.
|
|
46
|
+
*
|
|
47
|
+
* @return {Boolean}
|
|
48
|
+
*/
|
|
49
|
+
export function isEven(value) {
|
|
50
|
+
return value % 2 === 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Returns whether a value is a float.
|
|
55
|
+
* @ignore
|
|
56
|
+
*
|
|
57
|
+
* @param {} value - The value to test.
|
|
58
|
+
*
|
|
59
|
+
* @return {Boolean}
|
|
60
|
+
*/
|
|
61
|
+
export function isFloat(value) {
|
|
62
|
+
return isNumeric(value) && !Number.isInteger(value)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Returns how many fraction digits a number has.
|
|
67
|
+
* @ignore
|
|
68
|
+
*
|
|
69
|
+
* @param {Number} [number=0] - The number to test.
|
|
70
|
+
*
|
|
71
|
+
* @return {Number}
|
|
72
|
+
*/
|
|
73
|
+
export function countFractionDigits(number = 0) {
|
|
74
|
+
const stringRepresentation = number.toString()
|
|
75
|
+
if (stringRepresentation.indexOf('e-') > 0) {
|
|
76
|
+
// It's too small for a normal string representation, e.g. 1e-7 instead of 0.00000001
|
|
77
|
+
return parseInt(stringRepresentation.split('e-')[1])
|
|
78
|
+
} else {
|
|
79
|
+
const fractionDigits = stringRepresentation.split('.')[1]
|
|
80
|
+
return fractionDigits ? fractionDigits.length : 0
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Returns whether a number is half.
|
|
86
|
+
* @ignore
|
|
87
|
+
*
|
|
88
|
+
* @param {Number} number - The number to test.
|
|
89
|
+
*
|
|
90
|
+
* @return {Number}
|
|
91
|
+
*/
|
|
92
|
+
export function isHalf(number) {
|
|
93
|
+
return Math.abs(number) % 1 === 0.5
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Fetches a JSON resource.
|
|
98
|
+
* @ignore
|
|
99
|
+
*
|
|
100
|
+
* @param {String} url - The resource to fetch.
|
|
101
|
+
* @param {Object} [options.headers] - The headers to pass.
|
|
102
|
+
*
|
|
103
|
+
* @throws {Error} If `request.status` is lesser than 200 or greater or equal to 400.
|
|
104
|
+
* @throws {Error} If network fails.
|
|
105
|
+
*
|
|
106
|
+
* @return {JSON}
|
|
107
|
+
*/
|
|
108
|
+
export function getJSON(url, options = {}) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const request = Object.assign(new XMLHttpRequest(), {
|
|
111
|
+
onreadystatechange() {
|
|
112
|
+
if (request.readyState === 4) {
|
|
113
|
+
if (request.status >= 200 && request.status < 400)
|
|
114
|
+
resolve(JSON.parse(request.responseText))
|
|
115
|
+
else reject(new Error(request.statusText))
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
onerror() {
|
|
119
|
+
reject(new Error('Network error'))
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
request.open('GET', url, true)
|
|
124
|
+
setXHRHeaders(request, options.headers)
|
|
125
|
+
request.send()
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Returns an XHR object with attached headers.
|
|
131
|
+
* @ignore
|
|
132
|
+
*
|
|
133
|
+
* @param {XMLHttpRequest} xhr - The XHR request to set headers to.
|
|
134
|
+
* @param {Object} headers - The headers to set.
|
|
135
|
+
*
|
|
136
|
+
* @return {XMLHttpRequest}
|
|
137
|
+
*/
|
|
138
|
+
export function setXHRHeaders(xhr, headers = {}) {
|
|
139
|
+
for (const header in headers) xhr.setRequestHeader(header, headers[header])
|
|
140
|
+
return xhr
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns whether a value is undefined.
|
|
145
|
+
* @ignore
|
|
146
|
+
*
|
|
147
|
+
* @param {} value - The value to test.
|
|
148
|
+
*
|
|
149
|
+
* @return {Boolean}
|
|
150
|
+
*/
|
|
151
|
+
export function isUndefined(value) {
|
|
152
|
+
return typeof value === 'undefined'
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Returns an object flattened to one level deep.
|
|
157
|
+
* @ignore
|
|
158
|
+
*
|
|
159
|
+
* @param {Object} object - The object to flatten.
|
|
160
|
+
* @param {String} separator - The separator to use between flattened nodes.
|
|
161
|
+
*
|
|
162
|
+
* @return {Object}
|
|
163
|
+
*/
|
|
164
|
+
export function flattenObject(object, separator = '.') {
|
|
165
|
+
const finalObject = {}
|
|
166
|
+
Object.entries(object).forEach(item => {
|
|
167
|
+
if (typeof item[1] === 'object') {
|
|
168
|
+
const flatObject = flattenObject(item[1])
|
|
169
|
+
Object.entries(flatObject).forEach(node => {
|
|
170
|
+
finalObject[item[0] + separator + node[0]] = node[1]
|
|
171
|
+
})
|
|
172
|
+
} else {
|
|
173
|
+
finalObject[item[0]] = item[1]
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
return finalObject
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Returns whether a value is thenable.
|
|
181
|
+
* @ignore
|
|
182
|
+
*
|
|
183
|
+
* @param {} value - The value to test.
|
|
184
|
+
*
|
|
185
|
+
* @return {Boolean}
|
|
186
|
+
*/
|
|
187
|
+
export function isThenable(value) {
|
|
188
|
+
return (
|
|
189
|
+
Boolean(value) &&
|
|
190
|
+
(typeof value === 'object' || typeof value === 'function') &&
|
|
191
|
+
typeof value.then === 'function'
|
|
192
|
+
)
|
|
193
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default values for all Dinero objects.
|
|
3
|
+
*
|
|
4
|
+
* You can override default values for all subsequent Dinero objects by changing them directly on the global `Dinero` object.
|
|
5
|
+
* Existing instances won't be affected.
|
|
6
|
+
*
|
|
7
|
+
* @property {Number} defaultAmount - The default amount for new Dinero objects (see {@link module:Dinero Dinero} for format).
|
|
8
|
+
* @property {String} defaultCurrency - The default currency for new Dinero objects (see {@link module:Dinero Dinero} for format).
|
|
9
|
+
* @property {Number} defaultPrecision - The default precision for new Dinero objects (see {@link module:Dinero Dinero} for format).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Will set currency to 'EUR' for all Dinero objects.
|
|
13
|
+
* Dinero.defaultCurrency = 'EUR'
|
|
14
|
+
*
|
|
15
|
+
* @type {Object}
|
|
16
|
+
*/
|
|
17
|
+
export const Defaults = {
|
|
18
|
+
defaultAmount: 0,
|
|
19
|
+
defaultCurrency: 'USD',
|
|
20
|
+
defaultPrecision: 2
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Global settings for all Dinero objects.
|
|
25
|
+
*
|
|
26
|
+
* You can override global values for all subsequent Dinero objects by changing them directly on the global `Dinero` object.
|
|
27
|
+
* Existing instances won't be affected.
|
|
28
|
+
*
|
|
29
|
+
* @property {String} globalLocale - The global locale for new Dinero objects (see {@link module:Dinero~setLocale setLocale} for format).
|
|
30
|
+
* @property {String} globalFormat - The global format for new Dinero objects (see {@link module:Dinero~toFormat toFormat} for format).
|
|
31
|
+
* @property {String} globalRoundingMode - The global rounding mode for new Dinero objects (see {@link module:Dinero~multiply multiply} or {@link module:Dinero~divide divide} for format).
|
|
32
|
+
* @property {String} globalFormatRoundingMode - The global rounding mode to format new Dinero objects (see {@link module:Dinero~toFormat toFormat} or {@link module:Dinero~toRoundedUnit toRoundedUnit} for format).
|
|
33
|
+
* @property {(String|Promise)} globalExchangeRatesApi.endpoint - The global exchange rate API endpoint for new Dinero objects, or the global promise that resolves to the exchanges rates (see {@link module:Dinero~convert convert} for format).
|
|
34
|
+
* @property {String} globalExchangeRatesApi.propertyPath - The global exchange rate API property path for new Dinero objects (see {@link module:Dinero~convert convert} for format).
|
|
35
|
+
* @property {Object} globalExchangeRatesApi.headers - The global exchange rate API headers for new Dinero objects (see {@link module:Dinero~convert convert} for format).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Will set locale to 'fr-FR' for all Dinero objects.
|
|
39
|
+
* Dinero.globalLocale = 'fr-FR'
|
|
40
|
+
* @example
|
|
41
|
+
* // Will set global exchange rate API parameters for all Dinero objects.
|
|
42
|
+
* Dinero.globalExchangeRatesApi = {
|
|
43
|
+
* endpoint: 'https://yourexchangerates.api/latest?base={{from}}',
|
|
44
|
+
* propertyPath: 'data.rates.{{to}}',
|
|
45
|
+
* headers: {
|
|
46
|
+
* 'user-key': 'xxxxxxxxx'
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* @type {Object}
|
|
51
|
+
*/
|
|
52
|
+
export const Globals = {
|
|
53
|
+
globalLocale: 'en-US',
|
|
54
|
+
globalFormat: '$0,0.00',
|
|
55
|
+
globalRoundingMode: 'HALF_EVEN',
|
|
56
|
+
globalFormatRoundingMode: 'HALF_AWAY_FROM_ZERO',
|
|
57
|
+
globalExchangeRatesApi: {
|
|
58
|
+
endpoint: undefined,
|
|
59
|
+
headers: undefined,
|
|
60
|
+
propertyPath: undefined
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static methods for Dinero.
|
|
3
|
+
* @ignore
|
|
4
|
+
*
|
|
5
|
+
* @type {Object}
|
|
6
|
+
*/
|
|
7
|
+
export default {
|
|
8
|
+
/**
|
|
9
|
+
* Returns an array of Dinero objects, normalized to the same precision (the highest).
|
|
10
|
+
*
|
|
11
|
+
* @memberof module:Dinero
|
|
12
|
+
* @method
|
|
13
|
+
*
|
|
14
|
+
* @param {Dinero[]} objects - An array of Dinero objects
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // returns an array of Dinero objects
|
|
18
|
+
* // both with a precision of 3
|
|
19
|
+
* // and an amount of 1000
|
|
20
|
+
* Dinero.normalizePrecision([
|
|
21
|
+
* Dinero({ amount: 100, precision: 2 }),
|
|
22
|
+
* Dinero({ amount: 1000, precision: 3 })
|
|
23
|
+
* ])
|
|
24
|
+
*
|
|
25
|
+
* @return {Dinero[]}
|
|
26
|
+
*/
|
|
27
|
+
normalizePrecision(objects) {
|
|
28
|
+
const highestPrecision = objects.reduce((a, b) =>
|
|
29
|
+
Math.max(a.getPrecision(), b.getPrecision())
|
|
30
|
+
)
|
|
31
|
+
return objects.map(object =>
|
|
32
|
+
object.getPrecision() !== highestPrecision
|
|
33
|
+
? object.convertPrecision(highestPrecision)
|
|
34
|
+
: object
|
|
35
|
+
)
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Returns the smallest Dinero object from an array of Dinero objects
|
|
39
|
+
*
|
|
40
|
+
* @memberof module:Dinero
|
|
41
|
+
* @method
|
|
42
|
+
*
|
|
43
|
+
* @param {Dinero[]} objects - An array of Dinero objects
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // returns the smallest Dinero object with amount of 500 from an array of Dinero objects with different precisions
|
|
47
|
+
* Dinero.minimum([
|
|
48
|
+
* Dinero({ amount: 500, precision: 3 }),
|
|
49
|
+
* Dinero({ amount: 100, precision: 2 })
|
|
50
|
+
* ])
|
|
51
|
+
* @example
|
|
52
|
+
* // returns the smallest Dinero object with amount of 50 from an array of Dinero objects
|
|
53
|
+
* Dinero.minimum([
|
|
54
|
+
* Dinero({ amount: 50 }),
|
|
55
|
+
* Dinero({ amount: 100 })
|
|
56
|
+
* ])
|
|
57
|
+
*
|
|
58
|
+
* @return {Dinero[]}
|
|
59
|
+
*/
|
|
60
|
+
minimum(objects) {
|
|
61
|
+
const [firstObject, ...tailObjects] = objects
|
|
62
|
+
let currentMinimum = firstObject
|
|
63
|
+
|
|
64
|
+
tailObjects.forEach(obj => {
|
|
65
|
+
currentMinimum = currentMinimum.lessThan(obj) ? currentMinimum : obj
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
return currentMinimum
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Returns the biggest Dinero object from an array of Dinero objects
|
|
72
|
+
*
|
|
73
|
+
* @memberof module:Dinero
|
|
74
|
+
* @method
|
|
75
|
+
*
|
|
76
|
+
* @param {Dinero[]} objects - An array of Dinero objects
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // returns the biggest Dinero object with amount of 20, from an array of Dinero objects with different precisions
|
|
80
|
+
* Dinero.maximum([
|
|
81
|
+
* Dinero({ amount: 20, precision: 2 }),
|
|
82
|
+
* Dinero({ amount: 150, precision: 3 })
|
|
83
|
+
* ])
|
|
84
|
+
* @example
|
|
85
|
+
* // returns the biggest Dinero object with amount of 100, from an array of Dinero objects
|
|
86
|
+
* Dinero.maximum([
|
|
87
|
+
* Dinero({ amount: 100 }),
|
|
88
|
+
* Dinero({ amount: 50 })
|
|
89
|
+
* ])
|
|
90
|
+
*
|
|
91
|
+
* @return {Dinero[]}
|
|
92
|
+
*/
|
|
93
|
+
maximum(objects) {
|
|
94
|
+
const [firstObject, ...tailObjects] = objects
|
|
95
|
+
let currentMaximum = firstObject
|
|
96
|
+
|
|
97
|
+
tailObjects.forEach(obj => {
|
|
98
|
+
currentMaximum = currentMaximum.greaterThan(obj) ? currentMaximum : obj
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
return currentMaximum
|
|
102
|
+
}
|
|
103
|
+
}
|