jg-bignumber 1.1.1 → 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 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.1.1`, 29 in all, with its signature, its errors, and an example. It's generated from the package's TSDoc.
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.1`, 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 not positive
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?: Partial<Required<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?: Partial<Required<Format>> }`: How the value is processed and formatted. Defaults to `{}`.
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, { processing: { decimalPlaces: 2 }, format: { prefix: '$' } }); // => '$1,234.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,15 @@
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
+
3
13
  ## 1.1.1
4
14
 
5
15
  ### Added
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:
package/RECIPES.md CHANGED
@@ -7,7 +7,13 @@ Patterns for apps that add up money and report how a metric changed, with exact
7
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
8
 
9
9
  ```ts
10
- import { calculateSum, getBigNumber, processValue, type IBigNumber } from 'jg-bignumber';
10
+ import {
11
+ calculateSum,
12
+ getBigNumber,
13
+ prettifyValue,
14
+ processValue,
15
+ type IBigNumber,
16
+ } from 'jg-bignumber';
11
17
 
12
18
  // a line of an invoice, with its price as a decimal string, as an API or a PostgreSQL numeric
13
19
  // column sends it, so it never passes through a float
@@ -36,10 +42,10 @@ const calculateInvoiceTotals = (lines: IInvoiceLine[], taxRate: string): IInvoic
36
42
 
37
43
  const { total } = calculateInvoiceTotals(invoice.lines, invoice.taxRate);
38
44
 
39
- // toFixed and toFormat keep the cents, such as '1234.50' and '1,234.50', where a number or
40
- // prettifyValue drops the trailing zero
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'
41
47
  const totalForApi = total.toFixed(2);
42
- totalCell.textContent = `$${total.toFormat(2)}`;
48
+ totalCell.textContent = prettifyValue(total, { format: { prefix: '$', minimumDecimalPlaces: 2 } });
43
49
  ```
44
50
 
45
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.
@@ -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 not positive
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 not positive
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":"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,CAAC,CAAC;IAE/B,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.\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":"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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. 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":"AAaA,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 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
+ {"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, IBigNumberFormat, IBigNumberValue, IConfig, IOutput } from '../shared/types.js';
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, { processing: { decimalPlaces: 2 }, format: { prefix: '$' } }); // => '$1,234.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?: Partial<IBigNumberFormat>;
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, { processing: { decimalPlaces: 2 }, format: { prefix: '$' } }); // => '$1,234.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":"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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 IBigNumberFormat,\n IBigNumberValue,\n IConfig,\n IOutput,\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 * @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, { processing: { decimalPlaces: 2 }, format: { prefix: '$' } }); // => '$1,234.5'\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\n */\nexport const prettifyValue = (\n value: IBigNumberValue,\n config: { processing?: Partial<IConfig>; format?: Partial<IBigNumberFormat> } = {},\n): string => {\n try {\n return processValue(value, {\n ...config.processing,\n type: 'bignumber',\n }).toFormat(buildFormatConfig(config.format));\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"]}
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"]}
@@ -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;
@@ -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.1.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",