iso-price 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/contract/index.d.ts +25 -0
- package/dist/contract/index.js +60 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/domain.objects/IsoCurrency.d.ts +63 -0
- package/dist/domain.objects/IsoCurrency.js +70 -0
- package/dist/domain.objects/IsoCurrency.js.map +1 -0
- package/dist/domain.objects/IsoPrice.d.ts +16 -0
- package/dist/domain.objects/IsoPrice.js +3 -0
- package/dist/domain.objects/IsoPrice.js.map +1 -0
- package/dist/domain.objects/IsoPriceExponent.d.ts +28 -0
- package/dist/domain.objects/IsoPriceExponent.js +33 -0
- package/dist/domain.objects/IsoPriceExponent.js.map +1 -0
- package/dist/domain.objects/IsoPriceHuman.d.ts +19 -0
- package/dist/domain.objects/IsoPriceHuman.js +3 -0
- package/dist/domain.objects/IsoPriceHuman.js.map +1 -0
- package/dist/domain.objects/IsoPriceRoundMode.d.ts +23 -0
- package/dist/domain.objects/IsoPriceRoundMode.js +28 -0
- package/dist/domain.objects/IsoPriceRoundMode.js.map +1 -0
- package/dist/domain.objects/IsoPriceShape.d.ts +30 -0
- package/dist/domain.objects/IsoPriceShape.js +3 -0
- package/dist/domain.objects/IsoPriceShape.js.map +1 -0
- package/dist/domain.objects/IsoPriceWords.d.ts +20 -0
- package/dist/domain.objects/IsoPriceWords.js +3 -0
- package/dist/domain.objects/IsoPriceWords.js.map +1 -0
- package/dist/domain.operations/arithmetic/allocatePrice.d.ts +48 -0
- package/dist/domain.operations/arithmetic/allocatePrice.js +167 -0
- package/dist/domain.operations/arithmetic/allocatePrice.js.map +1 -0
- package/dist/domain.operations/arithmetic/dividePrice.d.ts +40 -0
- package/dist/domain.operations/arithmetic/dividePrice.js +127 -0
- package/dist/domain.operations/arithmetic/dividePrice.js.map +1 -0
- package/dist/domain.operations/arithmetic/multiplyPrice.d.ts +38 -0
- package/dist/domain.operations/arithmetic/multiplyPrice.js +89 -0
- package/dist/domain.operations/arithmetic/multiplyPrice.js.map +1 -0
- package/dist/domain.operations/arithmetic/subPrices.d.ts +28 -0
- package/dist/domain.operations/arithmetic/subPrices.js +62 -0
- package/dist/domain.operations/arithmetic/subPrices.js.map +1 -0
- package/dist/domain.operations/arithmetic/sumPrices.d.ts +44 -0
- package/dist/domain.operations/arithmetic/sumPrices.js +88 -0
- package/dist/domain.operations/arithmetic/sumPrices.js.map +1 -0
- package/dist/domain.operations/cast/asIsoPrice.d.ts +35 -0
- package/dist/domain.operations/cast/asIsoPrice.js +117 -0
- package/dist/domain.operations/cast/asIsoPrice.js.map +1 -0
- package/dist/domain.operations/cast/asIsoPriceHuman.d.ts +25 -0
- package/dist/domain.operations/cast/asIsoPriceHuman.js +106 -0
- package/dist/domain.operations/cast/asIsoPriceHuman.js.map +1 -0
- package/dist/domain.operations/cast/asIsoPriceShape.d.ts +25 -0
- package/dist/domain.operations/cast/asIsoPriceShape.js +164 -0
- package/dist/domain.operations/cast/asIsoPriceShape.js.map +1 -0
- package/dist/domain.operations/cast/asIsoPriceWords.d.ts +25 -0
- package/dist/domain.operations/cast/asIsoPriceWords.js +103 -0
- package/dist/domain.operations/cast/asIsoPriceWords.js.map +1 -0
- package/dist/domain.operations/guard/isIsoPrice.d.ts +18 -0
- package/dist/domain.operations/guard/isIsoPrice.js +29 -0
- package/dist/domain.operations/guard/isIsoPrice.js.map +1 -0
- package/dist/domain.operations/guard/isIsoPriceHuman.d.ts +24 -0
- package/dist/domain.operations/guard/isIsoPriceHuman.js +76 -0
- package/dist/domain.operations/guard/isIsoPriceHuman.js.map +1 -0
- package/dist/domain.operations/guard/isIsoPriceShape.d.ts +29 -0
- package/dist/domain.operations/guard/isIsoPriceShape.js +50 -0
- package/dist/domain.operations/guard/isIsoPriceShape.js.map +1 -0
- package/dist/domain.operations/guard/isIsoPriceWords.d.ts +24 -0
- package/dist/domain.operations/guard/isIsoPriceWords.js +48 -0
- package/dist/domain.operations/guard/isIsoPriceWords.js.map +1 -0
- package/dist/domain.operations/precision/getIsoPriceExponentByCurrency.d.ts +15 -0
- package/dist/domain.operations/precision/getIsoPriceExponentByCurrency.js +49 -0
- package/dist/domain.operations/precision/getIsoPriceExponentByCurrency.js.map +1 -0
- package/dist/domain.operations/precision/roundPrice.d.ts +25 -0
- package/dist/domain.operations/precision/roundPrice.js +24 -0
- package/dist/domain.operations/precision/roundPrice.js.map +1 -0
- package/dist/domain.operations/precision/setPricePrecision.d.ts +29 -0
- package/dist/domain.operations/precision/setPricePrecision.js +119 -0
- package/dist/domain.operations/precision/setPricePrecision.js.map +1 -0
- package/dist/domain.operations/statistics/calcPriceAvg.d.ts +21 -0
- package/dist/domain.operations/statistics/calcPriceAvg.js +92 -0
- package/dist/domain.operations/statistics/calcPriceAvg.js.map +1 -0
- package/dist/domain.operations/statistics/calcPriceStdev.d.ts +23 -0
- package/dist/domain.operations/statistics/calcPriceStdev.js +137 -0
- package/dist/domain.operations/statistics/calcPriceStdev.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/license.md +21 -0
- package/package.json +102 -0
- package/readme.md +373 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asIsoPriceWords = void 0;
|
|
4
|
+
const IsoPriceExponent_1 = require("../../domain.objects/IsoPriceExponent");
|
|
5
|
+
const isIsoPriceWords_1 = require("../guard/isIsoPriceWords");
|
|
6
|
+
const getIsoPriceExponentByCurrency_1 = require("../precision/getIsoPriceExponentByCurrency");
|
|
7
|
+
const asIsoPriceShape_1 = require("./asIsoPriceShape");
|
|
8
|
+
/**
|
|
9
|
+
* .what = gets the decimal places for an exponent
|
|
10
|
+
* .why = determines how to format the amount string
|
|
11
|
+
*/
|
|
12
|
+
const getDecimalPlaces = (exponent) => {
|
|
13
|
+
const match = exponent.match(/\^(-?\d+)$/);
|
|
14
|
+
if (!match)
|
|
15
|
+
return 2; // default to 2 decimal places
|
|
16
|
+
return Math.abs(parseInt(match[1], 10));
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* .what = formats the decimal part with underscore separators for high precision
|
|
20
|
+
* .why = improves readability of micro/nano/pico precision amounts
|
|
21
|
+
*/
|
|
22
|
+
const formatDecimalPart = (decPart) => {
|
|
23
|
+
// for 3+ digit decimals, add underscore separators every 3 digits from left
|
|
24
|
+
if (decPart.length > 3) {
|
|
25
|
+
const groups = [];
|
|
26
|
+
for (let i = 0; i < decPart.length; i += 3) {
|
|
27
|
+
groups.push(decPart.slice(i, i + 3));
|
|
28
|
+
}
|
|
29
|
+
return groups.join('_');
|
|
30
|
+
}
|
|
31
|
+
return decPart;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* .what = formats a bigint amount to a decimal string with underscores
|
|
35
|
+
* .why = converts 5037n with exponent 2 to '50.37'
|
|
36
|
+
*/
|
|
37
|
+
const formatAmount = (amount, exponent = IsoPriceExponent_1.IsoPriceExponent.CENTI) => {
|
|
38
|
+
const decimalPlaces = getDecimalPlaces(exponent);
|
|
39
|
+
const isNegative = amount < 0n;
|
|
40
|
+
const absAmount = isNegative ? -amount : amount;
|
|
41
|
+
// handle zero decimal places (whole units like JPY)
|
|
42
|
+
if (decimalPlaces === 0) {
|
|
43
|
+
const formattedInt = absAmount
|
|
44
|
+
.toString()
|
|
45
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, '_');
|
|
46
|
+
return isNegative ? `-${formattedInt}` : formattedInt;
|
|
47
|
+
}
|
|
48
|
+
// convert to string and pad with zeros at start if needed
|
|
49
|
+
const amountStr = absAmount.toString().padStart(decimalPlaces + 1, '0');
|
|
50
|
+
// split into integer and decimal parts
|
|
51
|
+
const intPart = amountStr.slice(0, -decimalPlaces) || '0';
|
|
52
|
+
const decPart = amountStr.slice(-decimalPlaces);
|
|
53
|
+
// format integer part with underscore thousands separators
|
|
54
|
+
const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, '_');
|
|
55
|
+
// build the result
|
|
56
|
+
const sign = isNegative ? '-' : '';
|
|
57
|
+
// for centi (2 decimal places), trim zeros at end but keep at least .00
|
|
58
|
+
if (decimalPlaces === 2) {
|
|
59
|
+
const trimmedDec = decPart.replace(/0+$/, '');
|
|
60
|
+
if (trimmedDec.length === 0) {
|
|
61
|
+
return `${sign}${formattedInt}.00`;
|
|
62
|
+
}
|
|
63
|
+
return `${sign}${formattedInt}.${trimmedDec.padEnd(2, '0')}`;
|
|
64
|
+
}
|
|
65
|
+
// for higher precision, preserve full precision with underscore separators
|
|
66
|
+
const formattedDec = formatDecimalPart(decPart);
|
|
67
|
+
return `${sign}${formattedInt}.${formattedDec}`;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* .what = converts any IsoPrice format to IsoPriceWords
|
|
71
|
+
* .why = enables uniform representation as words for serialization
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* asIsoPriceWords({ amount: 5037n, currency: 'USD' })
|
|
75
|
+
* // => 'USD 50.37'
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* asIsoPriceWords('$50.37')
|
|
79
|
+
* // => 'USD 50.37'
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* asIsoPriceWords({ amount: 1000000n, currency: 'USD' })
|
|
83
|
+
* // => 'USD 10_000.00'
|
|
84
|
+
*/
|
|
85
|
+
const asIsoPriceWords = (input, options) => {
|
|
86
|
+
// if already words format, normalize it (replace commas with underscores)
|
|
87
|
+
if ((0, isIsoPriceWords_1.isIsoPriceWords)(input)) {
|
|
88
|
+
// re-parse to ensure consistent format
|
|
89
|
+
const shape = (0, asIsoPriceShape_1.asIsoPriceShape)(input);
|
|
90
|
+
// use currency's standard exponent when shape.exponent is not set
|
|
91
|
+
const exponent = shape.exponent ?? (0, getIsoPriceExponentByCurrency_1.getIsoPriceExponentByCurrency)(shape.currency);
|
|
92
|
+
const formatted = formatAmount(shape.amount, exponent);
|
|
93
|
+
return `${shape.currency} ${formatted}`;
|
|
94
|
+
}
|
|
95
|
+
// convert to shape first, then format
|
|
96
|
+
const shape = (0, asIsoPriceShape_1.asIsoPriceShape)(input, options);
|
|
97
|
+
// use currency's standard exponent when shape.exponent is not set
|
|
98
|
+
const exponent = shape.exponent ?? (0, getIsoPriceExponentByCurrency_1.getIsoPriceExponentByCurrency)(shape.currency);
|
|
99
|
+
const formatted = formatAmount(shape.amount, exponent);
|
|
100
|
+
return `${shape.currency} ${formatted}`;
|
|
101
|
+
};
|
|
102
|
+
exports.asIsoPriceWords = asIsoPriceWords;
|
|
103
|
+
//# sourceMappingURL=asIsoPriceWords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asIsoPriceWords.js","sourceRoot":"","sources":["../../../src/domain.operations/cast/asIsoPriceWords.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IsoPrice } from '../../domain.objects/IsoPrice';
|
|
2
|
+
/**
|
|
3
|
+
* .what = type guard for IsoPrice union type
|
|
4
|
+
* .why = validates that a value is any of the three iso-price formats
|
|
5
|
+
*
|
|
6
|
+
* accepts:
|
|
7
|
+
* - IsoPriceWords: 'USD 50.37'
|
|
8
|
+
* - IsoPriceShape: { amount: 5037n, currency: 'USD' }
|
|
9
|
+
* - IsoPriceHuman: '$50.37'
|
|
10
|
+
*/
|
|
11
|
+
export declare const isIsoPrice: {
|
|
12
|
+
(value: unknown): value is IsoPrice;
|
|
13
|
+
/**
|
|
14
|
+
* .what = assertion function that throws on invalid input
|
|
15
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
16
|
+
*/
|
|
17
|
+
assure(value: unknown): asserts value is IsoPrice;
|
|
18
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isIsoPrice = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
const isIsoPriceHuman_1 = require("./isIsoPriceHuman");
|
|
6
|
+
const isIsoPriceShape_1 = require("./isIsoPriceShape");
|
|
7
|
+
const isIsoPriceWords_1 = require("./isIsoPriceWords");
|
|
8
|
+
/**
|
|
9
|
+
* .what = type guard for IsoPrice union type
|
|
10
|
+
* .why = validates that a value is any of the three iso-price formats
|
|
11
|
+
*
|
|
12
|
+
* accepts:
|
|
13
|
+
* - IsoPriceWords: 'USD 50.37'
|
|
14
|
+
* - IsoPriceShape: { amount: 5037n, currency: 'USD' }
|
|
15
|
+
* - IsoPriceHuman: '$50.37'
|
|
16
|
+
*/
|
|
17
|
+
const isIsoPrice = (value) => {
|
|
18
|
+
return ((0, isIsoPriceWords_1.isIsoPriceWords)(value) || (0, isIsoPriceShape_1.isIsoPriceShape)(value) || (0, isIsoPriceHuman_1.isIsoPriceHuman)(value));
|
|
19
|
+
};
|
|
20
|
+
exports.isIsoPrice = isIsoPrice;
|
|
21
|
+
/**
|
|
22
|
+
* .what = assertion function that throws on invalid input
|
|
23
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
24
|
+
*/
|
|
25
|
+
exports.isIsoPrice.assure = (value) => {
|
|
26
|
+
if (!(0, exports.isIsoPrice)(value))
|
|
27
|
+
throw new helpful_errors_1.BadRequestError('value is not a valid IsoPrice', { value });
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=isIsoPrice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIsoPrice.js","sourceRoot":"","sources":["../../../src/domain.operations/guard/isIsoPrice.ts"],"names":[],"mappings":";;;AAAA,mDAAiD;AAGjD,uDAAoD;AACpD,uDAAoD;AACpD,uDAAoD;AAEpD;;;;;;;;GAQG;AACI,MAAM,UAAU,GAAG,CAAC,KAAc,EAAqB,EAAE;IAC9D,OAAO,CACL,IAAA,iCAAe,EAAC,KAAK,CAAC,IAAI,IAAA,iCAAe,EAAC,KAAK,CAAC,IAAI,IAAA,iCAAe,EAAC,KAAK,CAAC,CAC3E,CAAC;AACJ,CAAC,CAAC;AAJW,QAAA,UAAU,cAIrB;AAEF;;;GAGG;AACH,kBAAU,CAAC,MAAM,GAAG,CAAC,KAAc,EAA6B,EAAE;IAChE,IAAI,CAAC,IAAA,kBAAU,EAAC,KAAK,CAAC;QACpB,MAAM,IAAI,gCAAe,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1E,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = type guard for IsoPriceHuman format
|
|
3
|
+
* .why = validates strings match the symbol-based human-readable pattern
|
|
4
|
+
*
|
|
5
|
+
* valid examples:
|
|
6
|
+
* - '$50.37'
|
|
7
|
+
* - '€50.37'
|
|
8
|
+
* - '¥1,000'
|
|
9
|
+
* - '$1,000,000.00'
|
|
10
|
+
* - '100 €' (suffix position)
|
|
11
|
+
*
|
|
12
|
+
* invalid examples:
|
|
13
|
+
* - 'USD 50.37' (code-prefix is words format, not human)
|
|
14
|
+
* - '50.37' (no symbol)
|
|
15
|
+
* - { amount: 5037n, currency: 'USD' } (object, not string)
|
|
16
|
+
*/
|
|
17
|
+
export declare const isIsoPriceHuman: {
|
|
18
|
+
(value: unknown): value is string & import("domain-glossaries").OfGlossary<"iso-price-human">;
|
|
19
|
+
/**
|
|
20
|
+
* .what = assertion function that throws on invalid input
|
|
21
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
22
|
+
*/
|
|
23
|
+
assure(value: unknown): asserts value is string & import("domain-glossaries").OfGlossary<"iso-price-human">;
|
|
24
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isIsoPriceHuman = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
/**
|
|
6
|
+
* .what = common currency symbols for human-readable price formats
|
|
7
|
+
* .why = validates that the string contains a currency symbol (not a code)
|
|
8
|
+
*/
|
|
9
|
+
const CURRENCY_SYMBOLS = [
|
|
10
|
+
'$', // USD, CAD, AUD, etc.
|
|
11
|
+
'€', // EUR
|
|
12
|
+
'£', // GBP
|
|
13
|
+
'¥', // JPY, CNY
|
|
14
|
+
'₹', // INR
|
|
15
|
+
'₽', // RUB
|
|
16
|
+
'₩', // KRW
|
|
17
|
+
'₪', // ILS
|
|
18
|
+
'฿', // THB
|
|
19
|
+
'₫', // VND
|
|
20
|
+
'kr', // SEK, NOK, DKK
|
|
21
|
+
'R', // ZAR, BRL
|
|
22
|
+
'zł', // PLN
|
|
23
|
+
'Kč', // CZK
|
|
24
|
+
'CHF', // note: CHF is a code but used as-is in human format
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* .what = regex pattern for human-readable price format
|
|
28
|
+
* .why = matches symbol-prefix or symbol-suffix patterns with optional separators
|
|
29
|
+
*
|
|
30
|
+
* examples:
|
|
31
|
+
* - '$50.37' (symbol prefix)
|
|
32
|
+
* - '€1,000.00' (symbol prefix with commas)
|
|
33
|
+
* - '100 €' (symbol suffix, european style)
|
|
34
|
+
* - '¥1,000' (no decimals)
|
|
35
|
+
*/
|
|
36
|
+
const hasSymbolPrefix = (value) => {
|
|
37
|
+
return CURRENCY_SYMBOLS.some((symbol) => value.startsWith(symbol));
|
|
38
|
+
};
|
|
39
|
+
const hasSymbolSuffix = (value) => {
|
|
40
|
+
return CURRENCY_SYMBOLS.some((symbol) => value.endsWith(symbol) || value.endsWith(` ${symbol}`));
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* .what = type guard for IsoPriceHuman format
|
|
44
|
+
* .why = validates strings match the symbol-based human-readable pattern
|
|
45
|
+
*
|
|
46
|
+
* valid examples:
|
|
47
|
+
* - '$50.37'
|
|
48
|
+
* - '€50.37'
|
|
49
|
+
* - '¥1,000'
|
|
50
|
+
* - '$1,000,000.00'
|
|
51
|
+
* - '100 €' (suffix position)
|
|
52
|
+
*
|
|
53
|
+
* invalid examples:
|
|
54
|
+
* - 'USD 50.37' (code-prefix is words format, not human)
|
|
55
|
+
* - '50.37' (no symbol)
|
|
56
|
+
* - { amount: 5037n, currency: 'USD' } (object, not string)
|
|
57
|
+
*/
|
|
58
|
+
const isIsoPriceHuman = (value) => {
|
|
59
|
+
if (typeof value !== 'string')
|
|
60
|
+
return false;
|
|
61
|
+
// must not be words format (code-prefix pattern)
|
|
62
|
+
if (/^[A-Z]{3} /.test(value))
|
|
63
|
+
return false;
|
|
64
|
+
// must have a currency symbol (prefix or suffix)
|
|
65
|
+
return hasSymbolPrefix(value) || hasSymbolSuffix(value);
|
|
66
|
+
};
|
|
67
|
+
exports.isIsoPriceHuman = isIsoPriceHuman;
|
|
68
|
+
/**
|
|
69
|
+
* .what = assertion function that throws on invalid input
|
|
70
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
71
|
+
*/
|
|
72
|
+
exports.isIsoPriceHuman.assure = (value) => {
|
|
73
|
+
if (!(0, exports.isIsoPriceHuman)(value))
|
|
74
|
+
throw new helpful_errors_1.BadRequestError('value is not a valid IsoPriceHuman', { value });
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=isIsoPriceHuman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIsoPriceHuman.js","sourceRoot":"","sources":["../../../src/domain.operations/guard/isIsoPriceHuman.ts"],"names":[],"mappings":";;;AAAA,mDAAiD;AAIjD;;;GAGG;AACH,MAAM,gBAAgB,GAAG;IACvB,GAAG,EAAE,sBAAsB;IAC3B,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,IAAI,EAAE,gBAAgB;IACtB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,qDAAqD;CAC7D,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,eAAe,GAAG,CAAC,KAAa,EAAW,EAAE;IACjD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAa,EAAW,EAAE;IACjD,OAAO,gBAAgB,CAAC,IAAI,CAC1B,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CACnE,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACI,MAAM,eAAe,GAAG,CAAC,KAAc,EAA0B,EAAE;IACxE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5C,iDAAiD;IACjD,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,iDAAiD;IACjD,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC,CAAC;AARW,QAAA,eAAe,mBAQ1B;AAEF;;;GAGG;AACH,uBAAe,CAAC,MAAM,GAAG,CAAC,KAAc,EAAkC,EAAE;IAC1E,IAAI,CAAC,IAAA,uBAAe,EAAC,KAAK,CAAC;QACzB,MAAM,IAAI,gCAAe,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IsoPriceShape } from '../../domain.objects/IsoPriceShape';
|
|
2
|
+
/**
|
|
3
|
+
* .what = type guard for IsoPriceShape format
|
|
4
|
+
* .why = validates objects have the required shape properties
|
|
5
|
+
*
|
|
6
|
+
* required:
|
|
7
|
+
* - amount: bigint
|
|
8
|
+
* - currency: string
|
|
9
|
+
*
|
|
10
|
+
* optional:
|
|
11
|
+
* - exponent: string (IsoPriceExponent value)
|
|
12
|
+
*
|
|
13
|
+
* valid examples:
|
|
14
|
+
* - { amount: 5037n, currency: 'USD' }
|
|
15
|
+
* - { amount: 3n, currency: 'USD', exponent: 'micro.x10^-6' }
|
|
16
|
+
*
|
|
17
|
+
* invalid examples:
|
|
18
|
+
* - { amount: 5037, currency: 'USD' } (number instead of bigint)
|
|
19
|
+
* - { amount: 5037n } (currency absent)
|
|
20
|
+
* - 'USD 50.37' (string instead of object)
|
|
21
|
+
*/
|
|
22
|
+
export declare const isIsoPriceShape: {
|
|
23
|
+
(value: unknown): value is IsoPriceShape<string, "whole.x10^0" | "centi.x10^-2" | "milli.x10^-3" | "micro.x10^-6" | "nano.x10^-9" | "pico.x10^-12" | import("../..").IsoPriceExponent>;
|
|
24
|
+
/**
|
|
25
|
+
* .what = assertion function that throws on invalid input
|
|
26
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
27
|
+
*/
|
|
28
|
+
assure(value: unknown): asserts value is IsoPriceShape<string, "whole.x10^0" | "centi.x10^-2" | "milli.x10^-3" | "micro.x10^-6" | "nano.x10^-9" | "pico.x10^-12" | import("../..").IsoPriceExponent>;
|
|
29
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isIsoPriceShape = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
/**
|
|
6
|
+
* .what = type guard for IsoPriceShape format
|
|
7
|
+
* .why = validates objects have the required shape properties
|
|
8
|
+
*
|
|
9
|
+
* required:
|
|
10
|
+
* - amount: bigint
|
|
11
|
+
* - currency: string
|
|
12
|
+
*
|
|
13
|
+
* optional:
|
|
14
|
+
* - exponent: string (IsoPriceExponent value)
|
|
15
|
+
*
|
|
16
|
+
* valid examples:
|
|
17
|
+
* - { amount: 5037n, currency: 'USD' }
|
|
18
|
+
* - { amount: 3n, currency: 'USD', exponent: 'micro.x10^-6' }
|
|
19
|
+
*
|
|
20
|
+
* invalid examples:
|
|
21
|
+
* - { amount: 5037, currency: 'USD' } (number instead of bigint)
|
|
22
|
+
* - { amount: 5037n } (currency absent)
|
|
23
|
+
* - 'USD 50.37' (string instead of object)
|
|
24
|
+
*/
|
|
25
|
+
const isIsoPriceShape = (value) => {
|
|
26
|
+
// must be an object
|
|
27
|
+
if (typeof value !== 'object' || value === null)
|
|
28
|
+
return false;
|
|
29
|
+
const obj = value;
|
|
30
|
+
// amount must be bigint
|
|
31
|
+
if (typeof obj.amount !== 'bigint')
|
|
32
|
+
return false;
|
|
33
|
+
// currency must be string
|
|
34
|
+
if (typeof obj.currency !== 'string')
|
|
35
|
+
return false;
|
|
36
|
+
// exponent is optional but must be string if present
|
|
37
|
+
if (obj.exponent !== undefined && typeof obj.exponent !== 'string')
|
|
38
|
+
return false;
|
|
39
|
+
return true;
|
|
40
|
+
};
|
|
41
|
+
exports.isIsoPriceShape = isIsoPriceShape;
|
|
42
|
+
/**
|
|
43
|
+
* .what = assertion function that throws on invalid input
|
|
44
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
45
|
+
*/
|
|
46
|
+
exports.isIsoPriceShape.assure = (value) => {
|
|
47
|
+
if (!(0, exports.isIsoPriceShape)(value))
|
|
48
|
+
throw new helpful_errors_1.BadRequestError('value is not a valid IsoPriceShape', { value });
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=isIsoPriceShape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIsoPriceShape.js","sourceRoot":"","sources":["../../../src/domain.operations/guard/isIsoPriceShape.ts"],"names":[],"mappings":";;;AAAA,mDAAiD;AAIjD;;;;;;;;;;;;;;;;;;;GAmBG;AACI,MAAM,eAAe,GAAG,CAAC,KAAc,EAA0B,EAAE;IACxE,oBAAoB;IACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAE9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAE7C,wBAAwB;IACxB,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEjD,0BAA0B;IAC1B,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEnD,qDAAqD;IACrD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAChE,OAAO,KAAK,CAAC;IAEf,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAjBW,QAAA,eAAe,mBAiB1B;AAEF;;;GAGG;AACH,uBAAe,CAAC,MAAM,GAAG,CAAC,KAAc,EAAkC,EAAE;IAC1E,IAAI,CAAC,IAAA,uBAAe,EAAC,KAAK,CAAC;QACzB,MAAM,IAAI,gCAAe,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IsoPriceWords } from '../../domain.objects/IsoPriceWords';
|
|
2
|
+
/**
|
|
3
|
+
* .what = type guard for IsoPriceWords format
|
|
4
|
+
* .why = validates strings match the `{CURRENCY_CODE} {AMOUNT}` pattern
|
|
5
|
+
*
|
|
6
|
+
* valid examples:
|
|
7
|
+
* - 'USD 50.37'
|
|
8
|
+
* - 'USD 1_000_000.00'
|
|
9
|
+
* - 'USD 1,000,000.00' (commas accepted, normalized to underscores on output)
|
|
10
|
+
* - 'EUR 0.000003'
|
|
11
|
+
* - 'JPY 1000'
|
|
12
|
+
*
|
|
13
|
+
* invalid examples:
|
|
14
|
+
* - '$50.37' (symbol instead of code)
|
|
15
|
+
* - 'usd 50.37' (lowercase currency)
|
|
16
|
+
*/
|
|
17
|
+
export declare const isIsoPriceWords: {
|
|
18
|
+
(value: unknown): value is IsoPriceWords;
|
|
19
|
+
/**
|
|
20
|
+
* .what = assertion function that throws on invalid input
|
|
21
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
22
|
+
*/
|
|
23
|
+
assure(value: unknown): asserts value is IsoPriceWords;
|
|
24
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isIsoPriceWords = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
/**
|
|
6
|
+
* .what = regex pattern for valid iso-price words format
|
|
7
|
+
* .why = validates `{CURRENCY_CODE} {AMOUNT}` pattern
|
|
8
|
+
*
|
|
9
|
+
* pattern breakdown:
|
|
10
|
+
* - `^[A-Z]{3}` — 3 uppercase letters for currency code
|
|
11
|
+
* - ` ` — single space separator
|
|
12
|
+
* - `-?` — optional negative sign
|
|
13
|
+
* - `(\d+|\d{1,3}([_,]\d{3})+)` — either plain digits OR underscore/comma-separated groups
|
|
14
|
+
* - `(\.(\d+|\d{1,3}([_,]\d{3})+))?$` — optional decimal point with underscore/comma-separated digits
|
|
15
|
+
*
|
|
16
|
+
* accepts both commas and underscores for input convenience; output uses underscores
|
|
17
|
+
*/
|
|
18
|
+
const WORDS_PATTERN = /^[A-Z]{3} -?(\d+|\d{1,3}([_,]\d{3})+)(\.(\d+|\d{1,3}([_,]\d{3})+))?$/;
|
|
19
|
+
/**
|
|
20
|
+
* .what = type guard for IsoPriceWords format
|
|
21
|
+
* .why = validates strings match the `{CURRENCY_CODE} {AMOUNT}` pattern
|
|
22
|
+
*
|
|
23
|
+
* valid examples:
|
|
24
|
+
* - 'USD 50.37'
|
|
25
|
+
* - 'USD 1_000_000.00'
|
|
26
|
+
* - 'USD 1,000,000.00' (commas accepted, normalized to underscores on output)
|
|
27
|
+
* - 'EUR 0.000003'
|
|
28
|
+
* - 'JPY 1000'
|
|
29
|
+
*
|
|
30
|
+
* invalid examples:
|
|
31
|
+
* - '$50.37' (symbol instead of code)
|
|
32
|
+
* - 'usd 50.37' (lowercase currency)
|
|
33
|
+
*/
|
|
34
|
+
const isIsoPriceWords = (value) => {
|
|
35
|
+
if (typeof value !== 'string')
|
|
36
|
+
return false;
|
|
37
|
+
return WORDS_PATTERN.test(value);
|
|
38
|
+
};
|
|
39
|
+
exports.isIsoPriceWords = isIsoPriceWords;
|
|
40
|
+
/**
|
|
41
|
+
* .what = assertion function that throws on invalid input
|
|
42
|
+
* .why = enables fail-fast validation with helpful error messages
|
|
43
|
+
*/
|
|
44
|
+
exports.isIsoPriceWords.assure = (value) => {
|
|
45
|
+
if (!(0, exports.isIsoPriceWords)(value))
|
|
46
|
+
throw new helpful_errors_1.BadRequestError('value is not a valid IsoPriceWords', { value });
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=isIsoPriceWords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIsoPriceWords.js","sourceRoot":"","sources":["../../../src/domain.operations/guard/isIsoPriceWords.ts"],"names":[],"mappings":";;;AAAA,mDAAiD;AAIjD;;;;;;;;;;;;GAYG;AACH,MAAM,aAAa,GACjB,sEAAsE,CAAC;AAEzE;;;;;;;;;;;;;;GAcG;AACI,MAAM,eAAe,GAAG,CAAC,KAAc,EAA0B,EAAE;IACxE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC,CAAC;AAHW,QAAA,eAAe,mBAG1B;AAEF;;;GAGG;AACH,uBAAe,CAAC,MAAM,GAAG,CAAC,KAAc,EAAkC,EAAE;IAC1E,IAAI,CAAC,IAAA,uBAAe,EAAC,KAAK,CAAC;QACzB,MAAM,IAAI,gCAAe,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IsoPriceExponent } from '../../domain.objects/IsoPriceExponent';
|
|
2
|
+
/**
|
|
3
|
+
* .what = returns the standard iso 4217 exponent for a currency
|
|
4
|
+
* .why = enables correct precision per currency standard
|
|
5
|
+
*
|
|
6
|
+
* defaults to centi.x10^-2 for unknown currencies, as >95% of currencies
|
|
7
|
+
* use 2 decimal places (cents).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* getIsoPriceExponentByCurrency('USD') // => 'centi.x10^-2'
|
|
11
|
+
* getIsoPriceExponentByCurrency('JPY') // => 'whole.x10^0'
|
|
12
|
+
* getIsoPriceExponentByCurrency('BHD') // => 'milli.x10^-3'
|
|
13
|
+
* getIsoPriceExponentByCurrency('BTC') // => 'centi.x10^-2' (default)
|
|
14
|
+
*/
|
|
15
|
+
export declare const getIsoPriceExponentByCurrency: (currency: string) => IsoPriceExponent;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getIsoPriceExponentByCurrency = void 0;
|
|
4
|
+
const IsoPriceExponent_1 = require("../../domain.objects/IsoPriceExponent");
|
|
5
|
+
/**
|
|
6
|
+
* .what = currency codes that use whole units (no decimals)
|
|
7
|
+
* .why = JPY, KRW, VND, IDR have no minor units per iso 4217
|
|
8
|
+
*/
|
|
9
|
+
const WHOLE_UNIT_CURRENCIES = new Set([
|
|
10
|
+
'JPY',
|
|
11
|
+
'KRW',
|
|
12
|
+
'VND',
|
|
13
|
+
'IDR',
|
|
14
|
+
'CLP',
|
|
15
|
+
'PYG',
|
|
16
|
+
'UGX',
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* .what = currency codes that use 3 decimal places
|
|
20
|
+
* .why = BHD, KWD, OMR, TND have fils/baisa (1/1000) per iso 4217
|
|
21
|
+
*/
|
|
22
|
+
const MILLI_UNIT_CURRENCIES = new Set(['BHD', 'KWD', 'OMR', 'TND']);
|
|
23
|
+
/**
|
|
24
|
+
* .what = returns the standard iso 4217 exponent for a currency
|
|
25
|
+
* .why = enables correct precision per currency standard
|
|
26
|
+
*
|
|
27
|
+
* defaults to centi.x10^-2 for unknown currencies, as >95% of currencies
|
|
28
|
+
* use 2 decimal places (cents).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* getIsoPriceExponentByCurrency('USD') // => 'centi.x10^-2'
|
|
32
|
+
* getIsoPriceExponentByCurrency('JPY') // => 'whole.x10^0'
|
|
33
|
+
* getIsoPriceExponentByCurrency('BHD') // => 'milli.x10^-3'
|
|
34
|
+
* getIsoPriceExponentByCurrency('BTC') // => 'centi.x10^-2' (default)
|
|
35
|
+
*/
|
|
36
|
+
const getIsoPriceExponentByCurrency = (currency) => {
|
|
37
|
+
// check for whole unit currencies (0 decimal places)
|
|
38
|
+
if (WHOLE_UNIT_CURRENCIES.has(currency)) {
|
|
39
|
+
return IsoPriceExponent_1.IsoPriceExponent.WHOLE;
|
|
40
|
+
}
|
|
41
|
+
// check for milli unit currencies (3 decimal places)
|
|
42
|
+
if (MILLI_UNIT_CURRENCIES.has(currency)) {
|
|
43
|
+
return IsoPriceExponent_1.IsoPriceExponent.MILLI;
|
|
44
|
+
}
|
|
45
|
+
// default to centi (2 decimal places) — covers >95% of currencies
|
|
46
|
+
return IsoPriceExponent_1.IsoPriceExponent.CENTI;
|
|
47
|
+
};
|
|
48
|
+
exports.getIsoPriceExponentByCurrency = getIsoPriceExponentByCurrency;
|
|
49
|
+
//# sourceMappingURL=getIsoPriceExponentByCurrency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getIsoPriceExponentByCurrency.js","sourceRoot":"","sources":["../../../src/domain.operations/precision/getIsoPriceExponentByCurrency.ts"],"names":[],"mappings":";;;AAAA,4EAAyE;AAEzE;;;GAGG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACI,MAAM,6BAA6B,GAAG,CAC3C,QAAgB,EACE,EAAE;IACpB,qDAAqD;IACrD,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,OAAO,mCAAgB,CAAC,KAAK,CAAC;IAChC,CAAC;IAED,qDAAqD;IACrD,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,OAAO,mCAAgB,CAAC,KAAK,CAAC;IAChC,CAAC;IAED,kEAAkE;IAClE,OAAO,mCAAgB,CAAC,KAAK,CAAC;AAChC,CAAC,CAAC;AAfW,QAAA,6BAA6B,iCAexC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IsoPrice } from '../../domain.objects/IsoPrice';
|
|
2
|
+
import type { IsoPriceExponent } from '../../domain.objects/IsoPriceExponent';
|
|
3
|
+
import type { IsoPriceRoundMode } from '../../domain.objects/IsoPriceRoundMode';
|
|
4
|
+
import type { IsoPriceWords } from '../../domain.objects/IsoPriceWords';
|
|
5
|
+
/**
|
|
6
|
+
* .what = rounds a price to a target precision
|
|
7
|
+
* .why = semantic alias for setPricePrecision when precision decrease is intended
|
|
8
|
+
*
|
|
9
|
+
* this is syntactic sugar for the common case of a precision reduction.
|
|
10
|
+
* use setPricePrecision directly if you need to increase precision.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* roundPrice({ of: 'USD 50.375', to: 'centi.x10^-2' })
|
|
14
|
+
* // => 'USD 50.38' (default half-up)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* roundPrice({ of: 'USD 50.375', to: 'centi.x10^-2' }, { round: 'floor' })
|
|
18
|
+
* // => 'USD 50.37'
|
|
19
|
+
*/
|
|
20
|
+
export declare const roundPrice: <TCurrency extends string = string>(input: {
|
|
21
|
+
of: IsoPrice<TCurrency> | string;
|
|
22
|
+
to: IsoPriceExponent | `${IsoPriceExponent}`;
|
|
23
|
+
}, options?: {
|
|
24
|
+
round?: IsoPriceRoundMode;
|
|
25
|
+
}) => IsoPriceWords<TCurrency>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.roundPrice = void 0;
|
|
4
|
+
const setPricePrecision_1 = require("./setPricePrecision");
|
|
5
|
+
/**
|
|
6
|
+
* .what = rounds a price to a target precision
|
|
7
|
+
* .why = semantic alias for setPricePrecision when precision decrease is intended
|
|
8
|
+
*
|
|
9
|
+
* this is syntactic sugar for the common case of a precision reduction.
|
|
10
|
+
* use setPricePrecision directly if you need to increase precision.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* roundPrice({ of: 'USD 50.375', to: 'centi.x10^-2' })
|
|
14
|
+
* // => 'USD 50.38' (default half-up)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* roundPrice({ of: 'USD 50.375', to: 'centi.x10^-2' }, { round: 'floor' })
|
|
18
|
+
* // => 'USD 50.37'
|
|
19
|
+
*/
|
|
20
|
+
const roundPrice = (input, options) => {
|
|
21
|
+
return (0, setPricePrecision_1.setPricePrecision)(input, options);
|
|
22
|
+
};
|
|
23
|
+
exports.roundPrice = roundPrice;
|
|
24
|
+
//# sourceMappingURL=roundPrice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roundPrice.js","sourceRoot":"","sources":["../../../src/domain.operations/precision/roundPrice.ts"],"names":[],"mappings":";;;AAIA,2DAAwD;AAExD;;;;;;;;;;;;;;GAcG;AACI,MAAM,UAAU,GAAG,CACxB,KAGC,EACD,OAAuC,EACb,EAAE;IAC5B,OAAO,IAAA,qCAAiB,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC,CAAC;AARW,QAAA,UAAU,cAQrB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IsoPrice } from '../../domain.objects/IsoPrice';
|
|
2
|
+
import { IsoPriceExponent } from '../../domain.objects/IsoPriceExponent';
|
|
3
|
+
import { IsoPriceRoundMode } from '../../domain.objects/IsoPriceRoundMode';
|
|
4
|
+
import type { IsoPriceWords } from '../../domain.objects/IsoPriceWords';
|
|
5
|
+
/**
|
|
6
|
+
* .what = changes the precision of a price to a target exponent
|
|
7
|
+
* .why = enables precision increase (lossless) and decrease (with round)
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // increase precision (lossless)
|
|
11
|
+
* setPricePrecision({ of: 'USD 50.37', to: 'micro.x10^-6' })
|
|
12
|
+
* // => 'USD 50.370000'
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // decrease precision (requires round)
|
|
16
|
+
* setPricePrecision({ of: 'USD 5.555', to: 'centi.x10^-2' })
|
|
17
|
+
* // => 'USD 5.56' (default half-up)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // decrease precision with explicit round mode
|
|
21
|
+
* setPricePrecision({ of: 'USD 5.555', to: 'centi.x10^-2' }, { round: 'floor' })
|
|
22
|
+
* // => 'USD 5.55'
|
|
23
|
+
*/
|
|
24
|
+
export declare const setPricePrecision: <TCurrency extends string = string>(input: {
|
|
25
|
+
of: IsoPrice<TCurrency> | string;
|
|
26
|
+
to: IsoPriceExponent | `${IsoPriceExponent}`;
|
|
27
|
+
}, options?: {
|
|
28
|
+
round?: IsoPriceRoundMode;
|
|
29
|
+
}) => IsoPriceWords<TCurrency>;
|