jg-bignumber 1.1.0 → 1.2.0
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/API.md +23 -9
- package/CHANGELOG.md +16 -0
- package/README.md +3 -0
- package/RECIPES.md +105 -0
- package/dist/calculations/calculations.d.ts +2 -2
- package/dist/calculations/calculations.js +3 -3
- package/dist/calculations/calculations.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/processing/processing.d.ts +7 -4
- package/dist/processing/processing.js +8 -3
- package/dist/processing/processing.js.map +1 -1
- package/dist/shared/types.d.ts +3 -0
- package/dist/shared/types.js.map +1 -1
- package/package.json +4 -3
package/API.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# <a id="api-reference"></a>jg-bignumber API reference
|
|
2
2
|
|
|
3
|
-
Every export of `jg-bignumber@1.
|
|
3
|
+
Every export of `jg-bignumber@1.2.0`, 30 in all, with its signature, its errors, and an example. It's generated from the package's TSDoc.
|
|
4
4
|
|
|
5
5
|
- Functions: [`adjustByPercentage`](#api-adjustByPercentage), [`calculateExchange`](#api-calculateExchange), [`calculateExchangeFee`](#api-calculateExchangeFee), [`calculateMax`](#api-calculateMax), [`calculateMean`](#api-calculateMean), [`calculateMedian`](#api-calculateMedian), [`calculateMin`](#api-calculateMin), [`calculatePercentageChange`](#api-calculatePercentageChange), [`calculatePercentageRepresentation`](#api-calculatePercentageRepresentation), [`calculateSum`](#api-calculateSum), [`calculateWeightedEntry`](#api-calculateWeightedEntry), [`getBigNumber`](#api-getBigNumber), [`isBigNumber`](#api-isBigNumber), [`isFloat`](#api-isFloat), [`isInteger`](#api-isInteger), [`isNumber`](#api-isNumber), [`prettifyValue`](#api-prettifyValue), [`processValue`](#api-processValue)
|
|
6
6
|
- Constants: [`BigNumber`](#api-BigNumber), [`ERRORS`](#api-ERRORS)
|
|
7
|
-
- Types: [`IBigNumber`](#api-IBigNumber), [`IBigNumberFormat`](#api-IBigNumberFormat), [`IBigNumberRoundingMode`](#api-IBigNumberRoundingMode), [`IBigNumberRoundingModeName`](#api-IBigNumberRoundingModeName), [`IBigNumberToType`](#api-IBigNumberToType), [`IBigNumberValue`](#api-IBigNumberValue), [`IConfig`](#api-IConfig), [`IOutput`](#api-IOutput), [`IType`](#api-IType)
|
|
7
|
+
- Types: [`IBigNumber`](#api-IBigNumber), [`IBigNumberFormat`](#api-IBigNumberFormat), [`IBigNumberRoundingMode`](#api-IBigNumberRoundingMode), [`IBigNumberRoundingModeName`](#api-IBigNumberRoundingModeName), [`IBigNumberToType`](#api-IBigNumberToType), [`IBigNumberValue`](#api-IBigNumberValue), [`IConfig`](#api-IConfig), [`IOutput`](#api-IOutput), [`IPrettifyFormat`](#api-IPrettifyFormat), [`IType`](#api-IType)
|
|
8
8
|
|
|
9
9
|
## <a id="api-functions"></a>Functions
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ Every export of `jg-bignumber@1.1.0`, 29 in all, with its signature, its errors,
|
|
|
12
12
|
|
|
13
13
|
*Function*
|
|
14
14
|
|
|
15
|
-
Changes a value by a percentage: a positive percentage increases it, and a negative one decreases it, to 0 at most.
|
|
15
|
+
Changes a value by a percentage: a positive percentage increases it, and a negative one decreases it, to 0 at most. A value of 0 stays 0.
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
18
|
adjustByPercentage<T extends Partial<IConfig>>(
|
|
@@ -36,7 +36,7 @@ adjustByPercentage<T extends Partial<IConfig>>(
|
|
|
36
36
|
- `INVALID_DECIMAL_PLACES`: if the number of decimal places is invalid for any reason
|
|
37
37
|
- `INVALID_ROUNDING_MODE`: if the rounding mode name is not supported
|
|
38
38
|
- `INVALID_TYPE`: if the processing type is not supported
|
|
39
|
-
- `NEGATIVE_VALUE_NOT_ALLOWED`: if the value is
|
|
39
|
+
- `NEGATIVE_VALUE_NOT_ALLOWED`: if the value is negative
|
|
40
40
|
|
|
41
41
|
**Example**
|
|
42
42
|
|
|
@@ -553,19 +553,19 @@ isNumber('abc'); // => false
|
|
|
553
553
|
|
|
554
554
|
*Function*
|
|
555
555
|
|
|
556
|
-
Processes a value and formats it for people, with group separators, a prefix, and a suffix.
|
|
556
|
+
Processes a value and formats it for people, with group separators, a prefix, and a suffix. Trailing zeros are dropped, unless `format.minimumDecimalPlaces` keeps them.
|
|
557
557
|
|
|
558
558
|
```ts
|
|
559
559
|
prettifyValue(
|
|
560
560
|
value: Value,
|
|
561
|
-
config?: { processing?: Partial<IConfig>; format?:
|
|
561
|
+
config?: { processing?: Partial<IConfig>; format?: IPrettifyFormat },
|
|
562
562
|
): string
|
|
563
563
|
```
|
|
564
564
|
|
|
565
565
|
**Parameters**
|
|
566
566
|
|
|
567
567
|
- `value` `Value`: The value.
|
|
568
|
-
- `config?` `{ processing?: Partial<IConfig>; format?:
|
|
568
|
+
- `config?` `{ processing?: Partial<IConfig>; format?: IPrettifyFormat }`: How the value is processed and formatted. Defaults to `{}`.
|
|
569
569
|
|
|
570
570
|
**Returns** `string`: The formatted value.
|
|
571
571
|
|
|
@@ -575,7 +575,8 @@ prettifyValue(
|
|
|
575
575
|
- `INVALID_DECIMAL_PLACES`: if the number of decimal places is invalid for any reason
|
|
576
576
|
- `INVALID_ROUNDING_MODE`: if the rounding mode name is not supported
|
|
577
577
|
- `INVALID_TYPE`: if the processing type is not supported
|
|
578
|
-
- `INVALID_BIGNUMBER_FORMAT`: if any of the format properties are invalid
|
|
578
|
+
- `INVALID_BIGNUMBER_FORMAT`: if any of the format properties are invalid, or minimumDecimalPlaces
|
|
579
|
+
- exceeds decimalPlaces
|
|
579
580
|
|
|
580
581
|
**Example**
|
|
581
582
|
|
|
@@ -583,7 +584,8 @@ prettifyValue(
|
|
|
583
584
|
import { prettifyValue } from 'jg-bignumber';
|
|
584
585
|
|
|
585
586
|
prettifyValue(1234567.891); // => '1,234,567.89'
|
|
586
|
-
prettifyValue(1234.5, {
|
|
587
|
+
prettifyValue(1234.5, { format: { prefix: '$' } }); // => '$1,234.5'
|
|
588
|
+
prettifyValue(1234.5, { format: { prefix: '$', minimumDecimalPlaces: 2 } }); // => '$1,234.50'
|
|
587
589
|
```
|
|
588
590
|
|
|
589
591
|
### <a id="api-processValue"></a>`processValue`
|
|
@@ -743,6 +745,18 @@ type IOutput<T> = T extends {
|
|
|
743
745
|
} ? IBigNumber : number;
|
|
744
746
|
```
|
|
745
747
|
|
|
748
|
+
### <a id="api-IPrettifyFormat"></a>`IPrettifyFormat`
|
|
749
|
+
|
|
750
|
+
*Type*
|
|
751
|
+
|
|
752
|
+
The format prettifyValue takes: any of bignumber.js's toFormat settings, and the fewest decimals it shows, padded with trailing zeros, such as 2 for '$1,234.50'. minimumDecimalPlaces defaults to 0, and can't exceed the processing's decimalPlaces.
|
|
753
|
+
|
|
754
|
+
```ts
|
|
755
|
+
type IPrettifyFormat = Partial<IBigNumberFormat> & {
|
|
756
|
+
minimumDecimalPlaces?: number;
|
|
757
|
+
};
|
|
758
|
+
```
|
|
759
|
+
|
|
746
760
|
### <a id="api-IType"></a>`IType`
|
|
747
761
|
|
|
748
762
|
*Type*
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `prettifyValue` keeps trailing zeros up to `format.minimumDecimalPlaces`, such as `$1,234.50` for a price, through the new `IPrettifyFormat` type. A minimum past `decimalPlaces` throws `INVALID_BIGNUMBER_FORMAT`.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `adjustByPercentage` returns 0 for a value of 0, instead of throwing `NEGATIVE_VALUE_NOT_ALLOWED`, which it still throws for a negative value.
|
|
12
|
+
|
|
13
|
+
## 1.1.1
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `RECIPES.md`, patterns for apps that use the package: summing money without rounding errors, and a percentage change for a dashboard. Each block is typechecked against the release.
|
|
18
|
+
|
|
3
19
|
## 1.1.0
|
|
4
20
|
|
|
5
21
|
A fresh start: breaking changes in a minor version, once, because nothing depended on 1.0.x.
|
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ processValue(512.155); // 512.16
|
|
|
20
20
|
processValue(19.991, { roundingMode: 'ROUND_CEIL' }); // 20
|
|
21
21
|
processValue('0.000001', { decimalPlaces: 6, type: 'string' }); // '0.000001'
|
|
22
22
|
prettifyValue(1234.5, { format: { prefix: '$' } }); // '$1,234.5'
|
|
23
|
+
prettifyValue(1234.5, { format: { prefix: '$', minimumDecimalPlaces: 2 } }); // '$1,234.50'
|
|
23
24
|
```
|
|
24
25
|
|
|
25
26
|
Percentages and money:
|
|
@@ -47,6 +48,8 @@ calculateWeightedEntry([
|
|
|
47
48
|
|
|
48
49
|
The full API reference ships in the package as `API.md`, generated from its TSDoc for the installed version, and is at https://jg-packages.jesusgraterol.dev/packages/jg-bignumber/.
|
|
49
50
|
|
|
51
|
+
Recipes for common jobs ship as `RECIPES.md`, with every block typechecked against the release, and are at https://jg-packages.jesusgraterol.dev/packages/jg-bignumber/recipes/.
|
|
52
|
+
|
|
50
53
|
## License
|
|
51
54
|
|
|
52
55
|
[MIT](https://github.com/jesusgraterol/jg-packages/blob/main/packages/jg-bignumber/LICENSE)
|
package/RECIPES.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# jg-bignumber recipes
|
|
2
|
+
|
|
3
|
+
Patterns for apps that add up money and report how a metric changed, with exact decimal math and rounding where you choose.
|
|
4
|
+
|
|
5
|
+
## Summing money without rounding errors
|
|
6
|
+
|
|
7
|
+
Use this for a cart, an invoice, or any total of prices. JavaScript numbers are binary fractions, so `0.1 + 0.2` is `0.30000000000000004`, and each addition can add an error. Keep amounts as decimal strings from the API or the database, do the arithmetic with jg-bignumber, and round where the invoice rounds:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
calculateSum,
|
|
12
|
+
getBigNumber,
|
|
13
|
+
prettifyValue,
|
|
14
|
+
processValue,
|
|
15
|
+
type IBigNumber,
|
|
16
|
+
} from 'jg-bignumber';
|
|
17
|
+
|
|
18
|
+
// a line of an invoice, with its price as a decimal string, as an API or a PostgreSQL numeric
|
|
19
|
+
// column sends it, so it never passes through a float
|
|
20
|
+
type IInvoiceLine = { unitPrice: string; quantity: number };
|
|
21
|
+
|
|
22
|
+
type IInvoiceTotals = { subtotal: IBigNumber; tax: IBigNumber; total: IBigNumber };
|
|
23
|
+
|
|
24
|
+
// the reader's invoice, with its tax rate as a percentage, such as '8.25'
|
|
25
|
+
declare const invoice: { lines: IInvoiceLine[]; taxRate: string };
|
|
26
|
+
|
|
27
|
+
// the cell that shows the invoice's total
|
|
28
|
+
declare const totalCell: HTMLElement;
|
|
29
|
+
|
|
30
|
+
const calculateInvoiceTotals = (lines: IInvoiceLine[], taxRate: string): IInvoiceTotals => {
|
|
31
|
+
// each line's total stays exact, so nothing is rounded before the sum
|
|
32
|
+
const lineTotals = lines.map(({ unitPrice, quantity }) =>
|
|
33
|
+
getBigNumber(unitPrice).times(quantity),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// the subtotal and the tax are each rounded to cents, as the invoice prints them, so the
|
|
37
|
+
// printed amounts add up to the printed total
|
|
38
|
+
const subtotal = calculateSum(lineTotals, { type: 'bignumber' });
|
|
39
|
+
const tax = processValue(subtotal.times(taxRate).dividedBy(100), { type: 'bignumber' });
|
|
40
|
+
return { subtotal, tax, total: calculateSum([subtotal, tax], { type: 'bignumber' }) };
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const { total } = calculateInvoiceTotals(invoice.lines, invoice.taxRate);
|
|
44
|
+
|
|
45
|
+
// toFixed keeps the cents, such as '1234.50', where a number drops the trailing zero, and
|
|
46
|
+
// minimumDecimalPlaces does the same for the formatted total, such as '$1,234.50'
|
|
47
|
+
const totalForApi = total.toFixed(2);
|
|
48
|
+
totalCell.textContent = prettifyValue(total, { format: { prefix: '$', minimumDecimalPlaces: 2 } });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Every jg-bignumber calculation, and `processValue`, rounds its result, so call one where the invoice rounds, and do the steps in between with BigNumber methods, such as `times` and `dividedBy`, which don't. `{ type: 'bignumber' }` returns a BigNumber instead of a number, so the next step starts from the decimal value. Results round to 2 decimal places with `ROUND_HALF_UP`: pass `roundingMode: 'ROUND_HALF_EVEN'` where an accounting rule asks for banker's rounding, or `decimalPlaces: 0` for a currency without cents. A string that isn't a number, such as `''` from an empty form field, throws `INVALID_VALUE`, so check input with `isNumber` before it reaches the math.
|
|
52
|
+
|
|
53
|
+
## A percentage change for a dashboard
|
|
54
|
+
|
|
55
|
+
Use this for a metric tile that compares a period with the one before, such as this month's revenue against last month's. `calculatePercentageChange` returns a signed percentage, and `prettifyValue` formats it with a sign and a suffix:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import {
|
|
59
|
+
calculatePercentageChange,
|
|
60
|
+
getBigNumber,
|
|
61
|
+
prettifyValue,
|
|
62
|
+
type IBigNumberValue,
|
|
63
|
+
} from 'jg-bignumber';
|
|
64
|
+
|
|
65
|
+
// how a metric moved, which picks the tile's arrow and color
|
|
66
|
+
type ITrend = 'up' | 'down' | 'flat';
|
|
67
|
+
|
|
68
|
+
type IChange = { label: string; trend: ITrend };
|
|
69
|
+
|
|
70
|
+
// the reader's revenue for the last two months, and the tile's change label
|
|
71
|
+
declare const revenue: { previous: string; current: string };
|
|
72
|
+
declare const changeLabel: HTMLElement;
|
|
73
|
+
|
|
74
|
+
// describes how a metric changed, or returns null when the previous value can't be the base
|
|
75
|
+
const describeChange = (previous: IBigNumberValue, current: IBigNumberValue): IChange | null => {
|
|
76
|
+
// a change from 0, or from a negative value, has no meaningful percentage, and
|
|
77
|
+
// calculatePercentageChange throws NEGATIVE_VALUE_NOT_ALLOWED for one
|
|
78
|
+
if (!getBigNumber(previous).isGreaterThan(0)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// rounded to one decimal before the trend is picked, so the arrow always agrees with the label
|
|
83
|
+
const change = calculatePercentageChange(previous, current, { decimalPlaces: 1 });
|
|
84
|
+
let trend: ITrend = 'flat';
|
|
85
|
+
if (change > 0) {
|
|
86
|
+
trend = 'up';
|
|
87
|
+
} else if (change < 0) {
|
|
88
|
+
trend = 'down';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// only an increase gets a plus sign, so an unchanged metric reads 0%, not +0%
|
|
92
|
+
const label = prettifyValue(change, {
|
|
93
|
+
format: { positiveSign: trend === 'up' ? '+' : '', suffix: '%' },
|
|
94
|
+
});
|
|
95
|
+
return { label, trend };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const change = describeChange(revenue.previous, revenue.current);
|
|
99
|
+
|
|
100
|
+
// revenue that starts from 0 has no percentage, so the tile says it's new
|
|
101
|
+
changeLabel.textContent = change?.label ?? 'New';
|
|
102
|
+
changeLabel.dataset['trend'] = change?.trend ?? 'flat';
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A change too small to show, such as 0.04%, rounds to 0 and reads as flat, never as an arrow next to 0%. The largest decrease is -100%, which `calculatePercentageChange` returns whenever the current value is 0 or less. `prettifyValue` groups thousands, as in `+1,234.6%`, and drops trailing zeros, so 12% and 12.5% can sit side by side.
|
|
@@ -111,7 +111,7 @@ export declare const calculateMedian: <T extends Partial<IConfig>>(values: IBigN
|
|
|
111
111
|
export declare const calculatePercentageChange: <T extends Partial<IConfig>>(oldValue: IBigNumberValue, newValue: IBigNumberValue, config?: T) => IOutput<T>;
|
|
112
112
|
/**
|
|
113
113
|
* Changes a value by a percentage: a positive percentage increases it, and a negative one
|
|
114
|
-
* decreases it, to 0 at most.
|
|
114
|
+
* decreases it, to 0 at most. A value of 0 stays 0.
|
|
115
115
|
* @param value The value to change.
|
|
116
116
|
* @param percentage The percentage to change it by.
|
|
117
117
|
* @param config How the result is processed.
|
|
@@ -126,7 +126,7 @@ export declare const calculatePercentageChange: <T extends Partial<IConfig>>(old
|
|
|
126
126
|
* - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason
|
|
127
127
|
* - INVALID_ROUNDING_MODE: if the rounding mode name is not supported
|
|
128
128
|
* - INVALID_TYPE: if the processing type is not supported
|
|
129
|
-
* - NEGATIVE_VALUE_NOT_ALLOWED: if the value is
|
|
129
|
+
* - NEGATIVE_VALUE_NOT_ALLOWED: if the value is negative
|
|
130
130
|
*/
|
|
131
131
|
export declare const adjustByPercentage: <T extends Partial<IConfig>>(value: IBigNumberValue, percentage: IBigNumberValue, config?: T) => IOutput<T>;
|
|
132
132
|
/**
|
|
@@ -162,7 +162,7 @@ export const calculatePercentageChange = (oldValue, newValue, config) => {
|
|
|
162
162
|
};
|
|
163
163
|
/**
|
|
164
164
|
* Changes a value by a percentage: a positive percentage increases it, and a negative one
|
|
165
|
-
* decreases it, to 0 at most.
|
|
165
|
+
* decreases it, to 0 at most. A value of 0 stays 0.
|
|
166
166
|
* @param value The value to change.
|
|
167
167
|
* @param percentage The percentage to change it by.
|
|
168
168
|
* @param config How the result is processed.
|
|
@@ -177,12 +177,12 @@ export const calculatePercentageChange = (oldValue, newValue, config) => {
|
|
|
177
177
|
* - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason
|
|
178
178
|
* - INVALID_ROUNDING_MODE: if the rounding mode name is not supported
|
|
179
179
|
* - INVALID_TYPE: if the processing type is not supported
|
|
180
|
-
* - NEGATIVE_VALUE_NOT_ALLOWED: if the value is
|
|
180
|
+
* - NEGATIVE_VALUE_NOT_ALLOWED: if the value is negative
|
|
181
181
|
*/
|
|
182
182
|
export const adjustByPercentage = (value, percentage, config) => {
|
|
183
183
|
const valueBN = getBigNumber(value);
|
|
184
184
|
const percentageBN = getBigNumber(percentage);
|
|
185
|
-
validatePositiveValue(valueBN);
|
|
185
|
+
validatePositiveValue(valueBN, true);
|
|
186
186
|
let adjusted;
|
|
187
187
|
if (percentageBN.isGreaterThan(0)) {
|
|
188
188
|
adjusted = percentageBN.dividedBy(100).plus(1).times(valueBN);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculations.js","sourceRoot":"","sources":["../../src/calculations/calculations.ts"],"names":[],"mappings":"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","sourcesContent":["import { BigNumber } from '../shared/constants.js';\nimport type { IBigNumber, IBigNumberValue, IConfig, IOutput } from '../shared/types.js';\nimport { getBigNumber, processValue } from '../processing/processing.js';\nimport { sortBigNumbers } from '../utils/utils.js';\nimport { validatePositiveValue, validateValuesArray } from '../validations/validations.js';\n\n/*\n * Essential calculations\n */\n\n/**\n * Adds up a list of values. An empty list sums to 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The sum.\n * @example\n * import { calculateSum } from 'jg-bignumber';\n *\n * calculateSum([0.1, '0.2', 0.3]); // => 0.6\n * calculateSum([0.1, 0.2], { type: 'string' }); // => '0.3'\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateSum = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateSum');\n return processValue(values.length > 0 ? BigNumber.sum(...values) : 0, config);\n};\n\n/**\n * Finds the smallest value in a list. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The smallest value.\n * @example\n * import { calculateMin } from 'jg-bignumber';\n *\n * calculateMin([3, '1.5', 2]); // => 1.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMin = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMin');\n return processValue(values.length > 0 ? BigNumber.min(...values) : 0, config);\n};\n\n/**\n * Finds the largest value in a list. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The largest value.\n * @example\n * import { calculateMax } from 'jg-bignumber';\n *\n * calculateMax([3, '1.5', 2]); // => 3\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMax = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMax');\n return processValue(values.length > 0 ? BigNumber.max(...values) : 0, config);\n};\n\n/**\n * Calculates the mean of a list of values. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The mean.\n * @example\n * import { calculateMean } from 'jg-bignumber';\n *\n * calculateMean([1, 2, 4]); // => 2.33\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMean = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMean');\n if (values.length > 0) {\n return processValue(BigNumber.sum(...values).dividedBy(values.length), config);\n }\n return processValue(0, config);\n};\n\n/**\n * Calculates the median of a list of values: the middle value, or the mean of the two middle\n * values when the list has an even length. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The median.\n * @example\n * import { calculateMedian } from 'jg-bignumber';\n *\n * calculateMedian([5, 1, 3]); // => 3\n * calculateMedian([4, 1, 3, 2]); // => 2.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMedian = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMedian');\n if (values.length === 0) {\n return processValue(0, config);\n }\n const half = Math.floor(values.length / 2);\n const sorted = values.map(getBigNumber).sort(sortBigNumbers('asc'));\n const middle = sorted[half] as IBigNumber;\n const median =\n values.length % 2 === 1 ? middle : (sorted[half - 1] as IBigNumber).plus(middle).dividedBy(2);\n return processValue(median, config);\n};\n\n/*\n * Percentage calculations\n */\n\n/**\n * Calculates the percentage a value changed by: positive when it increased, negative when it\n * decreased, and 0 when it didn't change. The largest decrease is -100%, returned whenever the new\n * value is 0 or less.\n * @param oldValue The value before the change.\n * @param newValue The value after the change.\n * @param config How the result is processed.\n * @returns The percentage change.\n * @example\n * import { calculatePercentageChange } from 'jg-bignumber';\n *\n * calculatePercentageChange(100, 125); // => 25\n * calculatePercentageChange(100, 80); // => -20\n * calculatePercentageChange(100, 0); // => -100\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the oldValue is not positive\n */\nexport const calculatePercentageChange = <T extends Partial<IConfig>>(\n oldValue: IBigNumberValue,\n newValue: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const oldValueBN = getBigNumber(oldValue);\n const newValueBN = getBigNumber(newValue);\n validatePositiveValue(oldValueBN);\n\n let change: IBigNumber;\n if (newValueBN.isGreaterThan(oldValueBN)) {\n change = newValueBN.minus(oldValueBN).dividedBy(oldValueBN).times(100);\n } else if (oldValueBN.isGreaterThan(newValueBN)) {\n change = newValueBN.isGreaterThan(0)\n ? oldValueBN.minus(newValueBN).dividedBy(oldValueBN).times(100).negated()\n : getBigNumber(-100);\n } else {\n change = getBigNumber(0);\n }\n return processValue(change, config);\n};\n\n/**\n * Changes a value by a percentage: a positive percentage increases it, and a negative one\n * decreases it, to 0 at most.\n * @param value The value to change.\n * @param percentage The percentage to change it by.\n * @param config How the result is processed.\n * @returns The changed value.\n * @example\n * import { adjustByPercentage } from 'jg-bignumber';\n *\n * adjustByPercentage(100, 25); // => 125\n * adjustByPercentage(100, -10); // => 90\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value is not positive\n */\nexport const adjustByPercentage = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n percentage: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const percentageBN = getBigNumber(percentage);\n validatePositiveValue(valueBN);\n\n let adjusted: IBigNumber;\n if (percentageBN.isGreaterThan(0)) {\n adjusted = percentageBN.dividedBy(100).plus(1).times(valueBN);\n } else if (percentageBN.isLessThan(0)) {\n adjusted = percentageBN.isGreaterThan(-100)\n ? percentageBN.times(-1).dividedBy(100).minus(1).times(valueBN).times(-1)\n : getBigNumber(0);\n } else {\n adjusted = valueBN;\n }\n return processValue(adjusted, config);\n};\n\n/**\n * Calculates what percentage of a total a value represents.\n * @param value The part.\n * @param total The total.\n * @param config How the result is processed.\n * @returns The percentage.\n * @example\n * import { calculatePercentageRepresentation } from 'jg-bignumber';\n *\n * calculatePercentageRepresentation(25, 200); // => 12.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or total are not positive\n */\nexport const calculatePercentageRepresentation = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n total: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const totalBN = getBigNumber(total);\n validatePositiveValue(valueBN, true);\n validatePositiveValue(totalBN);\n return processValue(valueBN.times(100).dividedBy(totalBN), config);\n};\n\n/*\n * Financial calculations\n */\n\n/**\n * Calculates the amount of an asset an exchange gives for a value at a rate, such as how much\n * BTC 100 USDT buys at 65,000 USDT per BTC.\n * @param value The amount being exchanged.\n * @param rate The price of one unit of the asset received.\n * @param config How the result is processed.\n * @returns The amount received.\n * @example\n * import { calculateExchange } from 'jg-bignumber';\n *\n * calculateExchange(100, 65000, { decimalPlaces: 8 }); // => 0.00153846\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or rate are not positive\n */\nexport const calculateExchange = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n rate: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const rateBN = getBigNumber(rate);\n validatePositiveValue(valueBN);\n validatePositiveValue(rateBN);\n return processValue(valueBN.dividedBy(rateBN), config);\n};\n\n/**\n * Calculates the fee charged for an exchange, as a percentage of the value exchanged.\n * @param value The amount being exchanged.\n * @param feePercentage The fee, as a percentage.\n * @param config How the result is processed.\n * @returns The fee.\n * @example\n * import { calculateExchangeFee } from 'jg-bignumber';\n *\n * calculateExchangeFee(1000, 0.1); // => 1\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or feePercentage are not positive\n */\nexport const calculateExchangeFee = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n feePercentage: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const feePercentageBN = getBigNumber(feePercentage);\n validatePositiveValue(valueBN);\n validatePositiveValue(feePercentageBN, true);\n return processValue(feePercentageBN.times(valueBN).dividedBy(100), config);\n};\n\n/**\n * Calculates the average entry price of a position bought in several trades, weighting each price\n * by the amount bought. An empty list, or one whose amounts add up to 0, returns 0.\n * @param trades The trades, each as a `[price, amount]` tuple.\n * @param config How the result is processed.\n * @returns The weighted average price.\n * @example\n * import { calculateWeightedEntry } from 'jg-bignumber';\n *\n * calculateWeightedEntry([[100, 2], [130, 1]]); // => 110\n * calculateWeightedEntry([]); // => 0\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateWeightedEntry = <T extends Partial<IConfig>>(\n trades: [IBigNumberValue, IBigNumberValue][],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(trades, 'calculateWeightedEntry');\n if (trades.length === 0) {\n return processValue(0, config);\n }\n let priceTimesShares = getBigNumber(0);\n let totalShares = getBigNumber(0);\n trades.forEach(([price, amount]) => {\n const amountBN = getBigNumber(amount);\n priceTimesShares = priceTimesShares.plus(getBigNumber(price).times(amountBN));\n totalShares = totalShares.plus(amountBN);\n });\n if (totalShares.isZero()) {\n return processValue(0, config);\n }\n return processValue(priceTimesShares.dividedBy(totalShares), config);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"calculations.js","sourceRoot":"","sources":["../../src/calculations/calculations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAE3F;;GAEG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,MAAyB,EACzB,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,MAAyB,EACzB,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,MAAyB,EACzB,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAyB,EACzB,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,MAAyB,EACzB,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAe,CAAC;IAC1C,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,MAAM,CAAC,IAAI,GAAG,CAAC,CAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,QAAyB,EACzB,QAAyB,EACzB,MAAU,EACE,EAAE;IACd,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAElC,IAAI,MAAkB,CAAC;IACvB,IAAI,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzE,CAAC;SAAM,IAAI,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;YAClC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE;YACzE,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,KAAsB,EACtB,UAA2B,EAC3B,MAAU,EACE,EAAE;IACd,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAC9C,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAErC,IAAI,QAAoB,CAAC;IACzB,IAAI,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,QAAQ,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC;YACzC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;IACD,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAC/C,KAAsB,EACtB,KAAsB,EACtB,MAAU,EACE,EAAE;IACd,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;AACrE,CAAC,CAAC;AAEF;;GAEG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,KAAsB,EACtB,IAAqB,EACrB,MAAU,EACE,EAAE;IACd,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,OAAO,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AACzD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,KAAsB,EACtB,aAA8B,EAC9B,MAAU,EACE,EAAE;IACd,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,eAAe,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;IACpD,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,qBAAqB,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC7C,OAAO,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,MAA4C,EAC5C,MAAU,EACE,EAAE;IACd,mBAAmB,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,gBAAgB,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACtC,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9E,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QACzB,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;AACvE,CAAC,CAAC","sourcesContent":["import { BigNumber } from '../shared/constants.js';\nimport type { IBigNumber, IBigNumberValue, IConfig, IOutput } from '../shared/types.js';\nimport { getBigNumber, processValue } from '../processing/processing.js';\nimport { sortBigNumbers } from '../utils/utils.js';\nimport { validatePositiveValue, validateValuesArray } from '../validations/validations.js';\n\n/*\n * Essential calculations\n */\n\n/**\n * Adds up a list of values. An empty list sums to 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The sum.\n * @example\n * import { calculateSum } from 'jg-bignumber';\n *\n * calculateSum([0.1, '0.2', 0.3]); // => 0.6\n * calculateSum([0.1, 0.2], { type: 'string' }); // => '0.3'\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateSum = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateSum');\n return processValue(values.length > 0 ? BigNumber.sum(...values) : 0, config);\n};\n\n/**\n * Finds the smallest value in a list. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The smallest value.\n * @example\n * import { calculateMin } from 'jg-bignumber';\n *\n * calculateMin([3, '1.5', 2]); // => 1.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMin = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMin');\n return processValue(values.length > 0 ? BigNumber.min(...values) : 0, config);\n};\n\n/**\n * Finds the largest value in a list. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The largest value.\n * @example\n * import { calculateMax } from 'jg-bignumber';\n *\n * calculateMax([3, '1.5', 2]); // => 3\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMax = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMax');\n return processValue(values.length > 0 ? BigNumber.max(...values) : 0, config);\n};\n\n/**\n * Calculates the mean of a list of values. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The mean.\n * @example\n * import { calculateMean } from 'jg-bignumber';\n *\n * calculateMean([1, 2, 4]); // => 2.33\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMean = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMean');\n if (values.length > 0) {\n return processValue(BigNumber.sum(...values).dividedBy(values.length), config);\n }\n return processValue(0, config);\n};\n\n/**\n * Calculates the median of a list of values: the middle value, or the mean of the two middle\n * values when the list has an even length. An empty list returns 0.\n * @param values The values.\n * @param config How the result is processed.\n * @returns The median.\n * @example\n * import { calculateMedian } from 'jg-bignumber';\n *\n * calculateMedian([5, 1, 3]); // => 3\n * calculateMedian([4, 1, 3, 2]); // => 2.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateMedian = <T extends Partial<IConfig>>(\n values: IBigNumberValue[],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(values, 'calculateMedian');\n if (values.length === 0) {\n return processValue(0, config);\n }\n const half = Math.floor(values.length / 2);\n const sorted = values.map(getBigNumber).sort(sortBigNumbers('asc'));\n const middle = sorted[half] as IBigNumber;\n const median =\n values.length % 2 === 1 ? middle : (sorted[half - 1] as IBigNumber).plus(middle).dividedBy(2);\n return processValue(median, config);\n};\n\n/*\n * Percentage calculations\n */\n\n/**\n * Calculates the percentage a value changed by: positive when it increased, negative when it\n * decreased, and 0 when it didn't change. The largest decrease is -100%, returned whenever the new\n * value is 0 or less.\n * @param oldValue The value before the change.\n * @param newValue The value after the change.\n * @param config How the result is processed.\n * @returns The percentage change.\n * @example\n * import { calculatePercentageChange } from 'jg-bignumber';\n *\n * calculatePercentageChange(100, 125); // => 25\n * calculatePercentageChange(100, 80); // => -20\n * calculatePercentageChange(100, 0); // => -100\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the oldValue is not positive\n */\nexport const calculatePercentageChange = <T extends Partial<IConfig>>(\n oldValue: IBigNumberValue,\n newValue: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const oldValueBN = getBigNumber(oldValue);\n const newValueBN = getBigNumber(newValue);\n validatePositiveValue(oldValueBN);\n\n let change: IBigNumber;\n if (newValueBN.isGreaterThan(oldValueBN)) {\n change = newValueBN.minus(oldValueBN).dividedBy(oldValueBN).times(100);\n } else if (oldValueBN.isGreaterThan(newValueBN)) {\n change = newValueBN.isGreaterThan(0)\n ? oldValueBN.minus(newValueBN).dividedBy(oldValueBN).times(100).negated()\n : getBigNumber(-100);\n } else {\n change = getBigNumber(0);\n }\n return processValue(change, config);\n};\n\n/**\n * Changes a value by a percentage: a positive percentage increases it, and a negative one\n * decreases it, to 0 at most. A value of 0 stays 0.\n * @param value The value to change.\n * @param percentage The percentage to change it by.\n * @param config How the result is processed.\n * @returns The changed value.\n * @example\n * import { adjustByPercentage } from 'jg-bignumber';\n *\n * adjustByPercentage(100, 25); // => 125\n * adjustByPercentage(100, -10); // => 90\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value is negative\n */\nexport const adjustByPercentage = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n percentage: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const percentageBN = getBigNumber(percentage);\n validatePositiveValue(valueBN, true);\n\n let adjusted: IBigNumber;\n if (percentageBN.isGreaterThan(0)) {\n adjusted = percentageBN.dividedBy(100).plus(1).times(valueBN);\n } else if (percentageBN.isLessThan(0)) {\n adjusted = percentageBN.isGreaterThan(-100)\n ? percentageBN.times(-1).dividedBy(100).minus(1).times(valueBN).times(-1)\n : getBigNumber(0);\n } else {\n adjusted = valueBN;\n }\n return processValue(adjusted, config);\n};\n\n/**\n * Calculates what percentage of a total a value represents.\n * @param value The part.\n * @param total The total.\n * @param config How the result is processed.\n * @returns The percentage.\n * @example\n * import { calculatePercentageRepresentation } from 'jg-bignumber';\n *\n * calculatePercentageRepresentation(25, 200); // => 12.5\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or total are not positive\n */\nexport const calculatePercentageRepresentation = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n total: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const totalBN = getBigNumber(total);\n validatePositiveValue(valueBN, true);\n validatePositiveValue(totalBN);\n return processValue(valueBN.times(100).dividedBy(totalBN), config);\n};\n\n/*\n * Financial calculations\n */\n\n/**\n * Calculates the amount of an asset an exchange gives for a value at a rate, such as how much\n * BTC 100 USDT buys at 65,000 USDT per BTC.\n * @param value The amount being exchanged.\n * @param rate The price of one unit of the asset received.\n * @param config How the result is processed.\n * @returns The amount received.\n * @example\n * import { calculateExchange } from 'jg-bignumber';\n *\n * calculateExchange(100, 65000, { decimalPlaces: 8 }); // => 0.00153846\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or rate are not positive\n */\nexport const calculateExchange = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n rate: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const rateBN = getBigNumber(rate);\n validatePositiveValue(valueBN);\n validatePositiveValue(rateBN);\n return processValue(valueBN.dividedBy(rateBN), config);\n};\n\n/**\n * Calculates the fee charged for an exchange, as a percentage of the value exchanged.\n * @param value The amount being exchanged.\n * @param feePercentage The fee, as a percentage.\n * @param config How the result is processed.\n * @returns The fee.\n * @example\n * import { calculateExchangeFee } from 'jg-bignumber';\n *\n * calculateExchangeFee(1000, 0.1); // => 1\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - NEGATIVE_VALUE_NOT_ALLOWED: if the value or feePercentage are not positive\n */\nexport const calculateExchangeFee = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n feePercentage: IBigNumberValue,\n config?: T,\n): IOutput<T> => {\n const valueBN = getBigNumber(value);\n const feePercentageBN = getBigNumber(feePercentage);\n validatePositiveValue(valueBN);\n validatePositiveValue(feePercentageBN, true);\n return processValue(feePercentageBN.times(valueBN).dividedBy(100), config);\n};\n\n/**\n * Calculates the average entry price of a position bought in several trades, weighting each price\n * by the amount bought. An empty list, or one whose amounts add up to 0, returns 0.\n * @param trades The trades, each as a `[price, amount]` tuple.\n * @param config How the result is processed.\n * @returns The weighted average price.\n * @example\n * import { calculateWeightedEntry } from 'jg-bignumber';\n *\n * calculateWeightedEntry([[100, 2], [130, 1]]); // => 110\n * calculateWeightedEntry([]); // => 0\n * @throws\n * - INVALID_VALUE: if any of the given values isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_VALUES_ARRAY: if the provided values arg is not a valid array\n */\nexport const calculateWeightedEntry = <T extends Partial<IConfig>>(\n trades: [IBigNumberValue, IBigNumberValue][],\n config?: T,\n): IOutput<T> => {\n validateValuesArray(trades, 'calculateWeightedEntry');\n if (trades.length === 0) {\n return processValue(0, config);\n }\n let priceTimesShares = getBigNumber(0);\n let totalShares = getBigNumber(0);\n trades.forEach(([price, amount]) => {\n const amountBN = getBigNumber(amount);\n priceTimesShares = priceTimesShares.plus(getBigNumber(price).times(amountBN));\n totalShares = totalShares.plus(amountBN);\n });\n if (totalShares.isZero()) {\n return processValue(0, config);\n }\n return processValue(priceTimesShares.dividedBy(totalShares), config);\n};\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { IBigNumber, IBigNumberFormat, IBigNumberRoundingMode, IBigNumberRoundingModeName, IBigNumberToType, IBigNumberValue, IConfig, IOutput, IType, } from './shared/types.js';
|
|
1
|
+
export type { IBigNumber, IBigNumberFormat, IBigNumberRoundingMode, IBigNumberRoundingModeName, IBigNumberToType, IBigNumberValue, IConfig, IOutput, IPrettifyFormat, IType, } from './shared/types.js';
|
|
2
2
|
export { BigNumber } from './shared/constants.js';
|
|
3
3
|
export { ERRORS } from './shared/errors.js';
|
|
4
4
|
export { getBigNumber, isBigNumber, isFloat, isInteger, isNumber, prettifyValue, processValue, } from './processing/processing.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,cAAc;AACd,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,cAAc;AACd,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,mCAAmC;AACnC,OAAO,EACL,YAAY,EACZ,WAAW,EACX,OAAO,EACP,SAAS,EACT,QAAQ,EACR,aAAa,EACb,YAAY,GACb,MAAM,4BAA4B,CAAC;AAEpC,eAAe;AACf,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,yBAAyB,EACzB,iCAAiC,EACjC,YAAY,EACZ,sBAAsB,GACvB,MAAM,gCAAgC,CAAC","sourcesContent":["// types\nexport type {\n IBigNumber,\n IBigNumberFormat,\n IBigNumberRoundingMode,\n IBigNumberRoundingModeName,\n IBigNumberToType,\n IBigNumberValue,\n IConfig,\n IOutput,\n IPrettifyFormat,\n IType,\n} from './shared/types.js';\n\n// constructor\nexport { BigNumber } from './shared/constants.js';\n\n// error codes\nexport { ERRORS } from './shared/errors.js';\n\n// value processors and type checks\nexport {\n getBigNumber,\n isBigNumber,\n isFloat,\n isInteger,\n isNumber,\n prettifyValue,\n processValue,\n} from './processing/processing.js';\n\n// calculations\nexport {\n adjustByPercentage,\n calculateExchange,\n calculateExchangeFee,\n calculateMax,\n calculateMean,\n calculateMedian,\n calculateMin,\n calculatePercentageChange,\n calculatePercentageRepresentation,\n calculateSum,\n calculateWeightedEntry,\n} from './calculations/calculations.js';\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IBigNumber,
|
|
1
|
+
import type { IBigNumber, IBigNumberValue, IConfig, IOutput, IPrettifyFormat } from '../shared/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Creates a BigNumber from a number, a numeric string, or a BigNumber, which is returned as is.
|
|
4
4
|
* Only finite values are accepted: `NaN` and `±Infinity` are rejected.
|
|
@@ -33,6 +33,7 @@ export declare const getBigNumber: (value: IBigNumberValue) => IBigNumber;
|
|
|
33
33
|
export declare const processValue: <T extends Partial<IConfig>>(value: IBigNumberValue, configuration?: T) => IOutput<T>;
|
|
34
34
|
/**
|
|
35
35
|
* Processes a value and formats it for people, with group separators, a prefix, and a suffix.
|
|
36
|
+
* Trailing zeros are dropped, unless `format.minimumDecimalPlaces` keeps them.
|
|
36
37
|
* @param value The value.
|
|
37
38
|
* @param config How the value is processed and formatted.
|
|
38
39
|
* @returns The formatted value.
|
|
@@ -40,17 +41,19 @@ export declare const processValue: <T extends Partial<IConfig>>(value: IBigNumbe
|
|
|
40
41
|
* import { prettifyValue } from 'jg-bignumber';
|
|
41
42
|
*
|
|
42
43
|
* prettifyValue(1234567.891); // => '1,234,567.89'
|
|
43
|
-
* prettifyValue(1234.5, {
|
|
44
|
+
* prettifyValue(1234.5, { format: { prefix: '$' } }); // => '$1,234.5'
|
|
45
|
+
* prettifyValue(1234.5, { format: { prefix: '$', minimumDecimalPlaces: 2 } }); // => '$1,234.50'
|
|
44
46
|
* @throws
|
|
45
47
|
* - INVALID_VALUE: if the value isn't a finite number or BigNumber throws an error
|
|
46
48
|
* - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason
|
|
47
49
|
* - INVALID_ROUNDING_MODE: if the rounding mode name is not supported
|
|
48
50
|
* - INVALID_TYPE: if the processing type is not supported
|
|
49
|
-
* - INVALID_BIGNUMBER_FORMAT: if any of the format properties are invalid
|
|
51
|
+
* - INVALID_BIGNUMBER_FORMAT: if any of the format properties are invalid, or minimumDecimalPlaces
|
|
52
|
+
* exceeds decimalPlaces
|
|
50
53
|
*/
|
|
51
54
|
export declare const prettifyValue: (value: IBigNumberValue, config?: {
|
|
52
55
|
processing?: Partial<IConfig>;
|
|
53
|
-
format?:
|
|
56
|
+
format?: IPrettifyFormat;
|
|
54
57
|
}) => string;
|
|
55
58
|
/**
|
|
56
59
|
* Checks whether a value is a BigNumber instance, from this package or any other copy of
|
|
@@ -52,6 +52,7 @@ export const processValue = (value, configuration) => {
|
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
54
|
* Processes a value and formats it for people, with group separators, a prefix, and a suffix.
|
|
55
|
+
* Trailing zeros are dropped, unless `format.minimumDecimalPlaces` keeps them.
|
|
55
56
|
* @param value The value.
|
|
56
57
|
* @param config How the value is processed and formatted.
|
|
57
58
|
* @returns The formatted value.
|
|
@@ -59,20 +60,24 @@ export const processValue = (value, configuration) => {
|
|
|
59
60
|
* import { prettifyValue } from 'jg-bignumber';
|
|
60
61
|
*
|
|
61
62
|
* prettifyValue(1234567.891); // => '1,234,567.89'
|
|
62
|
-
* prettifyValue(1234.5, {
|
|
63
|
+
* prettifyValue(1234.5, { format: { prefix: '$' } }); // => '$1,234.5'
|
|
64
|
+
* prettifyValue(1234.5, { format: { prefix: '$', minimumDecimalPlaces: 2 } }); // => '$1,234.50'
|
|
63
65
|
* @throws
|
|
64
66
|
* - INVALID_VALUE: if the value isn't a finite number or BigNumber throws an error
|
|
65
67
|
* - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason
|
|
66
68
|
* - INVALID_ROUNDING_MODE: if the rounding mode name is not supported
|
|
67
69
|
* - INVALID_TYPE: if the processing type is not supported
|
|
68
|
-
* - INVALID_BIGNUMBER_FORMAT: if any of the format properties are invalid
|
|
70
|
+
* - INVALID_BIGNUMBER_FORMAT: if any of the format properties are invalid, or minimumDecimalPlaces
|
|
71
|
+
* exceeds decimalPlaces
|
|
69
72
|
*/
|
|
70
73
|
export const prettifyValue = (value, config = {}) => {
|
|
71
74
|
try {
|
|
75
|
+
const { decimalPlaces } = buildConfig(config.processing);
|
|
76
|
+
// the value is already rounded to decimalPlaces, so the maximum only checks the minimum
|
|
72
77
|
return processValue(value, {
|
|
73
78
|
...config.processing,
|
|
74
79
|
type: 'bignumber',
|
|
75
|
-
}).toFormat(buildFormatConfig(config.format));
|
|
80
|
+
}).toFormat([config.format?.minimumDecimalPlaces, decimalPlaces], buildFormatConfig(config.format));
|
|
76
81
|
}
|
|
77
82
|
catch (error) {
|
|
78
83
|
if (isException(error)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processing.js","sourceRoot":"","sources":["../../src/processing/processing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAQ7C,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,0BAA0B,EAC1B,sBAAsB,EACtB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAsB,EAAc,EAAE;IACjE,IAAI,SAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,SAAS,GAAG,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC1B,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAsB,EACtB,aAAiB,EACL,EAAE;IACd,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACjG,OAAO,sBAAsB,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAe,CAAC;AACtE,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"processing.js","sourceRoot":"","sources":["../../src/processing/processing.ts"],"names":[],"mappings":"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","sourcesContent":["import { Exception, isException } from 'jg-exception';\n\nimport { BigNumber } from '../shared/constants.js';\nimport { ERRORS } from '../shared/errors.js';\nimport type {\n IBigNumber,\n IBigNumberValue,\n IConfig,\n IOutput,\n IPrettifyFormat,\n} from '../shared/types.js';\nimport {\n buildConfig,\n buildFormatConfig,\n buildInvalidValueException,\n convertBigNumberToType,\n roundBigNumber,\n} from '../utils/utils.js';\n\n/**\n * Creates a BigNumber from a number, a numeric string, or a BigNumber, which is returned as is.\n * Only finite values are accepted: `NaN` and `±Infinity` are rejected.\n * @param value The value.\n * @returns The BigNumber.\n * @example\n * import { getBigNumber } from 'jg-bignumber';\n *\n * getBigNumber('0.1').plus('0.2').toString(); // => '0.3'\n * @throws\n * - INVALID_VALUE: if the value isn't a finite number or BigNumber throws an error\n */\nexport const getBigNumber = (value: IBigNumberValue): IBigNumber => {\n let bigNumber: IBigNumber;\n try {\n bigNumber = BigNumber.isBigNumber(value) ? value : BigNumber(value);\n } catch (error) {\n throw buildInvalidValueException(value, error);\n }\n if (!bigNumber.isFinite()) {\n throw buildInvalidValueException(value);\n }\n return bigNumber;\n};\n\n/**\n * Rounds a value and returns it as the type the configuration asks for: a number by default, or a\n * string or a BigNumber.\n * @param value The value.\n * @param configuration The decimal places, rounding mode, and output type.\n * @returns The processed value.\n * @example\n * import { processValue } from 'jg-bignumber';\n *\n * processValue(512.155); // => 512.16\n * processValue(512.155, { decimalPlaces: 1, roundingMode: 'ROUND_FLOOR' }); // => 512.1\n * processValue('0.000001', { decimalPlaces: 6, type: 'string' }); // => '0.000001'\n * @throws\n * - INVALID_VALUE: if the value isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n */\nexport const processValue = <T extends Partial<IConfig>>(\n value: IBigNumberValue,\n configuration?: T,\n): IOutput<T> => {\n const config = buildConfig(configuration);\n const bigNumber = roundBigNumber(getBigNumber(value), config.decimalPlaces, config.roundingMode);\n return convertBigNumberToType(bigNumber, config.type) as IOutput<T>;\n};\n\n/**\n * Processes a value and formats it for people, with group separators, a prefix, and a suffix.\n * Trailing zeros are dropped, unless `format.minimumDecimalPlaces` keeps them.\n * @param value The value.\n * @param config How the value is processed and formatted.\n * @returns The formatted value.\n * @example\n * import { prettifyValue } from 'jg-bignumber';\n *\n * prettifyValue(1234567.891); // => '1,234,567.89'\n * prettifyValue(1234.5, { format: { prefix: '$' } }); // => '$1,234.5'\n * prettifyValue(1234.5, { format: { prefix: '$', minimumDecimalPlaces: 2 } }); // => '$1,234.50'\n * @throws\n * - INVALID_VALUE: if the value isn't a finite number or BigNumber throws an error\n * - INVALID_DECIMAL_PLACES: if the number of decimal places is invalid for any reason\n * - INVALID_ROUNDING_MODE: if the rounding mode name is not supported\n * - INVALID_TYPE: if the processing type is not supported\n * - INVALID_BIGNUMBER_FORMAT: if any of the format properties are invalid, or minimumDecimalPlaces\n * exceeds decimalPlaces\n */\nexport const prettifyValue = (\n value: IBigNumberValue,\n config: { processing?: Partial<IConfig>; format?: IPrettifyFormat } = {},\n): string => {\n try {\n const { decimalPlaces } = buildConfig(config.processing);\n // the value is already rounded to decimalPlaces, so the maximum only checks the minimum\n return processValue(value, {\n ...config.processing,\n type: 'bignumber',\n }).toFormat(\n [config.format?.minimumDecimalPlaces, decimalPlaces],\n buildFormatConfig(config.format),\n );\n } catch (error) {\n if (isException(error)) {\n throw error;\n }\n throw new Exception('The value could not be formatted.', {\n code: ERRORS.INVALID_BIGNUMBER_FORMAT,\n cause: error,\n });\n }\n};\n\n/**\n * Checks whether a value is a BigNumber instance, from this package or any other copy of\n * bignumber.js.\n * @param value The value.\n * @returns Whether it's a BigNumber.\n * @example\n * import { getBigNumber, isBigNumber } from 'jg-bignumber';\n *\n * isBigNumber(getBigNumber(1)); // => true\n * isBigNumber(1); // => false\n */\nexport const isBigNumber = (value: unknown): value is IBigNumber => BigNumber.isBigNumber(value);\n\n/**\n * Checks whether a value is a finite number, numeric string, or BigNumber.\n * @param value The value.\n * @returns Whether it's a finite number.\n * @example\n * import { isNumber } from 'jg-bignumber';\n *\n * isNumber('12.5'); // => true\n * isNumber(Infinity); // => false\n * isNumber('abc'); // => false\n */\nexport const isNumber = (value: unknown): boolean => {\n try {\n getBigNumber(value as IBigNumberValue);\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Checks whether a value is a finite integer, in any of the supported types.\n * @param value The value.\n * @returns Whether it's an integer.\n * @example\n * import { isInteger } from 'jg-bignumber';\n *\n * isInteger('12'); // => true\n * isInteger(12.5); // => false\n */\nexport const isInteger = (value: unknown): boolean => {\n try {\n return getBigNumber(value as IBigNumberValue).isInteger();\n } catch {\n return false;\n }\n};\n\n/**\n * Checks whether a value is a finite number with a fractional part, in any of the supported types.\n * @param value The value.\n * @returns Whether it's a float.\n * @example\n * import { isFloat } from 'jg-bignumber';\n *\n * isFloat(12.5); // => true\n * isFloat('12'); // => false\n */\nexport const isFloat = (value: unknown): boolean => {\n try {\n return !getBigNumber(value as IBigNumberValue).isInteger();\n } catch {\n return false;\n }\n};\n"]}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export type IBigNumberRoundingModeName = 'ROUND_UP' | 'ROUND_DOWN' | 'ROUND_CEIL
|
|
|
4
4
|
export type IBigNumberRoundingMode = BigNumber.RoundingMode;
|
|
5
5
|
export type IBigNumberValue = BigNumber.Value;
|
|
6
6
|
export type IBigNumberFormat = Required<BigNumber.Format>;
|
|
7
|
+
export type IPrettifyFormat = Partial<IBigNumberFormat> & {
|
|
8
|
+
minimumDecimalPlaces?: number;
|
|
9
|
+
};
|
|
7
10
|
export type IType = 'string' | 'number' | 'bignumber';
|
|
8
11
|
export type IConfig = {
|
|
9
12
|
decimalPlaces: number;
|
package/dist/shared/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { BigNumber } from 'bignumber.js';\n\n/*\n * A BigNumber instance, created with `getBigNumber(value)` or the exported `BigNumber`\n * constructor. Every bignumber.js method is available on it.\n */\nexport type IBigNumber = BigNumber;\n\n/*\n * How a value is rounded when it has more decimals than allowed:\n * - ROUND_UP: away from zero\n * - ROUND_DOWN: towards zero\n * - ROUND_CEIL: towards Infinity\n * - ROUND_FLOOR: towards -Infinity\n * - ROUND_HALF_UP (default): to the nearest neighbour, away from zero when equidistant\n * - ROUND_HALF_DOWN: to the nearest neighbour, towards zero when equidistant\n * - ROUND_HALF_EVEN: to the nearest neighbour, towards the even one when equidistant\n * - ROUND_HALF_CEIL: to the nearest neighbour, towards Infinity when equidistant\n * - ROUND_HALF_FLOOR: to the nearest neighbour, towards -Infinity when equidistant\n */\nexport type IBigNumberRoundingModeName =\n | 'ROUND_UP'\n | 'ROUND_DOWN'\n | 'ROUND_CEIL'\n | 'ROUND_FLOOR'\n | 'ROUND_HALF_UP'\n | 'ROUND_HALF_DOWN'\n | 'ROUND_HALF_EVEN'\n | 'ROUND_HALF_CEIL'\n | 'ROUND_HALF_FLOOR';\n\n// the numeric rounding mode bignumber.js uses for each IBigNumberRoundingModeName\nexport type IBigNumberRoundingMode = BigNumber.RoundingMode;\n\n// the values a BigNumber can be created from: numbers, numeric strings, and BigNumbers\nexport type IBigNumberValue = BigNumber.Value;\n\n/*\n * How prettifyValue formats a value, with every setting of bignumber.js's toFormat, defaults in\n * parentheses: prefix (''), negativeSign ('-'), positiveSign (''), decimalSeparator ('.'),\n * groupSeparator (','), groupSize (3), secondaryGroupSize (0), fractionGroupSeparator (' '),\n * fractionGroupSize (0), and suffix ('').\n */\nexport type IBigNumberFormat = Required<BigNumber.Format>;\n\n// the type a processed value is returned as\nexport type IType = 'string' | 'number' | 'bignumber';\n\n// how a value is processed\nexport type IConfig = {\n // the maximum number of decimals in the output. Defaults to 2\n decimalPlaces: number;\n\n // how the value is rounded when it has more decimals. Defaults to 'ROUND_HALF_UP'\n roundingMode: IBigNumberRoundingModeName;\n\n // the output's type. Defaults to 'number'\n type: IType;\n};\n\n// the TypeScript type of a value converted to an IType\nexport type IBigNumberToType<T> = T extends 'string'\n ? string\n : T extends 'number'\n ? number\n : T extends 'bignumber'\n ? IBigNumber\n : never;\n\n// the return type of a function that processes a value, picked from its configuration's type\nexport type IOutput<T> = T extends { type: 'string' }\n ? string\n : T extends { type: 'number' }\n ? number\n : T extends { type: 'bignumber' }\n ? IBigNumber\n : number;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { BigNumber } from 'bignumber.js';\n\n/*\n * A BigNumber instance, created with `getBigNumber(value)` or the exported `BigNumber`\n * constructor. Every bignumber.js method is available on it.\n */\nexport type IBigNumber = BigNumber;\n\n/*\n * How a value is rounded when it has more decimals than allowed:\n * - ROUND_UP: away from zero\n * - ROUND_DOWN: towards zero\n * - ROUND_CEIL: towards Infinity\n * - ROUND_FLOOR: towards -Infinity\n * - ROUND_HALF_UP (default): to the nearest neighbour, away from zero when equidistant\n * - ROUND_HALF_DOWN: to the nearest neighbour, towards zero when equidistant\n * - ROUND_HALF_EVEN: to the nearest neighbour, towards the even one when equidistant\n * - ROUND_HALF_CEIL: to the nearest neighbour, towards Infinity when equidistant\n * - ROUND_HALF_FLOOR: to the nearest neighbour, towards -Infinity when equidistant\n */\nexport type IBigNumberRoundingModeName =\n | 'ROUND_UP'\n | 'ROUND_DOWN'\n | 'ROUND_CEIL'\n | 'ROUND_FLOOR'\n | 'ROUND_HALF_UP'\n | 'ROUND_HALF_DOWN'\n | 'ROUND_HALF_EVEN'\n | 'ROUND_HALF_CEIL'\n | 'ROUND_HALF_FLOOR';\n\n// the numeric rounding mode bignumber.js uses for each IBigNumberRoundingModeName\nexport type IBigNumberRoundingMode = BigNumber.RoundingMode;\n\n// the values a BigNumber can be created from: numbers, numeric strings, and BigNumbers\nexport type IBigNumberValue = BigNumber.Value;\n\n/*\n * How prettifyValue formats a value, with every setting of bignumber.js's toFormat, defaults in\n * parentheses: prefix (''), negativeSign ('-'), positiveSign (''), decimalSeparator ('.'),\n * groupSeparator (','), groupSize (3), secondaryGroupSize (0), fractionGroupSeparator (' '),\n * fractionGroupSize (0), and suffix ('').\n */\nexport type IBigNumberFormat = Required<BigNumber.Format>;\n\n/*\n * The format prettifyValue takes: any of bignumber.js's toFormat settings, and the fewest decimals\n * it shows, padded with trailing zeros, such as 2 for '$1,234.50'. minimumDecimalPlaces defaults\n * to 0, and can't exceed the processing's decimalPlaces.\n */\nexport type IPrettifyFormat = Partial<IBigNumberFormat> & { minimumDecimalPlaces?: number };\n\n// the type a processed value is returned as\nexport type IType = 'string' | 'number' | 'bignumber';\n\n// how a value is processed\nexport type IConfig = {\n // the maximum number of decimals in the output. Defaults to 2\n decimalPlaces: number;\n\n // how the value is rounded when it has more decimals. Defaults to 'ROUND_HALF_UP'\n roundingMode: IBigNumberRoundingModeName;\n\n // the output's type. Defaults to 'number'\n type: IType;\n};\n\n// the TypeScript type of a value converted to an IType\nexport type IBigNumberToType<T> = T extends 'string'\n ? string\n : T extends 'number'\n ? number\n : T extends 'bignumber'\n ? IBigNumber\n : never;\n\n// the return type of a function that processes a value, picked from its configuration's type\nexport type IOutput<T> = T extends { type: 'string' }\n ? string\n : T extends { type: 'number' }\n ? number\n : T extends { type: 'bignumber' }\n ? IBigNumber\n : number;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jg-bignumber",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Exact decimal math with bignumber.js: rounding, formatting, and sum, mean, percentage, and exchange calculations.",
|
|
5
5
|
"author": "Jesus Graterol",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"CHANGELOG.md",
|
|
19
|
-
"API.md"
|
|
19
|
+
"API.md",
|
|
20
|
+
"RECIPES.md"
|
|
20
21
|
],
|
|
21
22
|
"sideEffects": false,
|
|
22
23
|
"engines": {
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
],
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"bignumber.js": "^11.1.5",
|
|
47
|
-
"jg-exception": "^1.
|
|
48
|
+
"jg-exception": "^1.2.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@jg-packages/eslint-config": "0.0.0",
|