@ducatjs/money 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/NOTICE +51 -0
- package/README.md +617 -2
- package/assets/CREDITS.md +12 -0
- package/data/adyen-fx.json +19 -0
- package/data/adyen.json +171 -0
- package/data/braintree.json +223 -0
- package/data/cash-rounding.json +399 -0
- package/data/checkout.json +230 -0
- package/data/iso4217-list-one.xml +1956 -0
- package/data/klarna.json +95 -0
- package/data/paypal.json +65 -0
- package/data/stripe-fx.json +17 -0
- package/data/stripe.json +285 -0
- package/dist/adyen-fx.d.ts +25 -0
- package/dist/adyen-fx.d.ts.map +1 -0
- package/dist/adyen-fx.js +122 -0
- package/dist/adyen-fx.js.map +1 -0
- package/dist/adyen.d.ts +25 -0
- package/dist/adyen.d.ts.map +1 -0
- package/dist/adyen.js +34 -0
- package/dist/adyen.js.map +1 -0
- package/dist/allocate.d.ts +72 -0
- package/dist/allocate.d.ts.map +1 -0
- package/dist/allocate.js +314 -0
- package/dist/allocate.js.map +1 -0
- package/dist/bag.d.ts +58 -0
- package/dist/bag.d.ts.map +1 -0
- package/dist/bag.js +122 -0
- package/dist/bag.js.map +1 -0
- package/dist/braintree.d.ts +34 -0
- package/dist/braintree.d.ts.map +1 -0
- package/dist/braintree.js +45 -0
- package/dist/braintree.js.map +1 -0
- package/dist/cash.d.ts +35 -0
- package/dist/cash.d.ts.map +1 -0
- package/dist/cash.js +86 -0
- package/dist/cash.js.map +1 -0
- package/dist/checkout.d.ts +42 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +52 -0
- package/dist/checkout.js.map +1 -0
- package/dist/convert.d.ts +51 -0
- package/dist/convert.d.ts.map +1 -0
- package/dist/convert.js +55 -0
- package/dist/convert.js.map +1 -0
- package/dist/currency.d.ts +22 -0
- package/dist/currency.d.ts.map +1 -0
- package/dist/currency.js +38 -0
- package/dist/currency.js.map +1 -0
- package/dist/decimal.d.ts +52 -0
- package/dist/decimal.d.ts.map +1 -0
- package/dist/decimal.js +251 -0
- package/dist/decimal.js.map +1 -0
- package/dist/ecb.d.ts +17 -0
- package/dist/ecb.d.ts.map +1 -0
- package/dist/ecb.js +147 -0
- package/dist/ecb.js.map +1 -0
- package/dist/exact.d.ts +62 -0
- package/dist/exact.d.ts.map +1 -0
- package/dist/exact.js +147 -0
- package/dist/exact.js.map +1 -0
- package/dist/fetch.d.ts +58 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +79 -0
- package/dist/fetch.js.map +1 -0
- package/dist/fixed.d.ts +121 -0
- package/dist/fixed.d.ts.map +1 -0
- package/dist/fixed.js +420 -0
- package/dist/fixed.js.map +1 -0
- package/dist/fn.d.ts +27 -0
- package/dist/fn.d.ts.map +1 -0
- package/dist/fn.js +30 -0
- package/dist/fn.js.map +1 -0
- package/dist/format.d.ts +13 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +90 -0
- package/dist/format.js.map +1 -0
- package/dist/generated/adyen.d.ts +3 -0
- package/dist/generated/adyen.d.ts.map +1 -0
- package/dist/generated/adyen.js +144 -0
- package/dist/generated/adyen.js.map +1 -0
- package/dist/generated/braintree.d.ts +3 -0
- package/dist/generated/braintree.d.ts.map +1 -0
- package/dist/generated/braintree.js +140 -0
- package/dist/generated/braintree.js.map +1 -0
- package/dist/generated/cash.d.ts +12 -0
- package/dist/generated/cash.d.ts.map +1 -0
- package/dist/generated/cash.js +364 -0
- package/dist/generated/cash.js.map +1 -0
- package/dist/generated/checkout.d.ts +3 -0
- package/dist/generated/checkout.d.ts.map +1 -0
- package/dist/generated/checkout.js +151 -0
- package/dist/generated/checkout.js.map +1 -0
- package/dist/generated/iso4217.d.ts +174 -0
- package/dist/generated/iso4217.d.ts.map +1 -0
- package/dist/generated/iso4217.js +175 -0
- package/dist/generated/iso4217.js.map +1 -0
- package/dist/generated/kernel.d.ts +17 -0
- package/dist/generated/kernel.d.ts.map +1 -0
- package/dist/generated/kernel.js +208 -0
- package/dist/generated/kernel.js.map +1 -0
- package/dist/generated/klarna.d.ts +3 -0
- package/dist/generated/klarna.d.ts.map +1 -0
- package/dist/generated/klarna.js +21 -0
- package/dist/generated/klarna.js.map +1 -0
- package/dist/generated/paypal.d.ts +3 -0
- package/dist/generated/paypal.d.ts.map +1 -0
- package/dist/generated/paypal.js +31 -0
- package/dist/generated/paypal.js.map +1 -0
- package/dist/generated/stripe.d.ts +8 -0
- package/dist/generated/stripe.d.ts.map +1 -0
- package/dist/generated/stripe.js +150 -0
- package/dist/generated/stripe.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/klarna.d.ts +31 -0
- package/dist/klarna.d.ts.map +1 -0
- package/dist/klarna.js +38 -0
- package/dist/klarna.js.map +1 -0
- package/dist/money.d.ts +218 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +577 -0
- package/dist/money.js.map +1 -0
- package/dist/parse.d.ts +11 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +132 -0
- package/dist/parse.js.map +1 -0
- package/dist/paypal.d.ts +41 -0
- package/dist/paypal.d.ts.map +1 -0
- package/dist/paypal.js +58 -0
- package/dist/paypal.js.map +1 -0
- package/dist/plugins/adyen.d.ts +15 -0
- package/dist/plugins/adyen.d.ts.map +1 -0
- package/dist/plugins/adyen.js +10 -0
- package/dist/plugins/adyen.js.map +1 -0
- package/dist/plugins/all.d.ts +22 -0
- package/dist/plugins/all.d.ts.map +1 -0
- package/dist/plugins/all.js +23 -0
- package/dist/plugins/all.js.map +1 -0
- package/dist/plugins/allocate.d.ts +20 -0
- package/dist/plugins/allocate.d.ts.map +1 -0
- package/dist/plugins/allocate.js +26 -0
- package/dist/plugins/allocate.js.map +1 -0
- package/dist/plugins/braintree.d.ts +12 -0
- package/dist/plugins/braintree.d.ts.map +1 -0
- package/dist/plugins/braintree.js +12 -0
- package/dist/plugins/braintree.js.map +1 -0
- package/dist/plugins/cash.d.ts +19 -0
- package/dist/plugins/cash.d.ts.map +1 -0
- package/dist/plugins/cash.js +16 -0
- package/dist/plugins/cash.js.map +1 -0
- package/dist/plugins/checkout.d.ts +21 -0
- package/dist/plugins/checkout.d.ts.map +1 -0
- package/dist/plugins/checkout.js +16 -0
- package/dist/plugins/checkout.js.map +1 -0
- package/dist/plugins/convert.d.ts +20 -0
- package/dist/plugins/convert.d.ts.map +1 -0
- package/dist/plugins/convert.js +13 -0
- package/dist/plugins/convert.js.map +1 -0
- package/dist/plugins/exact.d.ts +15 -0
- package/dist/plugins/exact.d.ts.map +1 -0
- package/dist/plugins/exact.js +13 -0
- package/dist/plugins/exact.js.map +1 -0
- package/dist/plugins/fixed.d.ts +17 -0
- package/dist/plugins/fixed.d.ts.map +1 -0
- package/dist/plugins/fixed.js +13 -0
- package/dist/plugins/fixed.js.map +1 -0
- package/dist/plugins/format.d.ts +9 -0
- package/dist/plugins/format.d.ts.map +1 -0
- package/dist/plugins/format.js +16 -0
- package/dist/plugins/format.js.map +1 -0
- package/dist/plugins/klarna.d.ts +10 -0
- package/dist/plugins/klarna.d.ts.map +1 -0
- package/dist/plugins/klarna.js +10 -0
- package/dist/plugins/klarna.js.map +1 -0
- package/dist/plugins/paypal.d.ts +14 -0
- package/dist/plugins/paypal.d.ts.map +1 -0
- package/dist/plugins/paypal.js +16 -0
- package/dist/plugins/paypal.js.map +1 -0
- package/dist/plugins/prisma.d.ts +8 -0
- package/dist/plugins/prisma.d.ts.map +1 -0
- package/dist/plugins/prisma.js +13 -0
- package/dist/plugins/prisma.js.map +1 -0
- package/dist/plugins/stripe.d.ts +14 -0
- package/dist/plugins/stripe.d.ts.map +1 -0
- package/dist/plugins/stripe.js +16 -0
- package/dist/plugins/stripe.js.map +1 -0
- package/dist/plugins/tax.d.ts +21 -0
- package/dist/plugins/tax.d.ts.map +1 -0
- package/dist/plugins/tax.js +18 -0
- package/dist/plugins/tax.js.map +1 -0
- package/dist/prisma.d.ts +66 -0
- package/dist/prisma.d.ts.map +1 -0
- package/dist/prisma.js +66 -0
- package/dist/prisma.js.map +1 -0
- package/dist/processor.d.ts +28 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +118 -0
- package/dist/processor.js.map +1 -0
- package/dist/provider.d.ts +89 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +240 -0
- package/dist/provider.js.map +1 -0
- package/dist/rate.d.ts +119 -0
- package/dist/rate.d.ts.map +1 -0
- package/dist/rate.js +271 -0
- package/dist/rate.js.map +1 -0
- package/dist/rounding-error.d.ts +9 -0
- package/dist/rounding-error.d.ts.map +1 -0
- package/dist/rounding-error.js +9 -0
- package/dist/rounding-error.js.map +1 -0
- package/dist/rounding.d.ts +50 -0
- package/dist/rounding.d.ts.map +1 -0
- package/dist/rounding.js +87 -0
- package/dist/rounding.js.map +1 -0
- package/dist/stripe-fx.d.ts +22 -0
- package/dist/stripe-fx.d.ts.map +1 -0
- package/dist/stripe-fx.js +30 -0
- package/dist/stripe-fx.js.map +1 -0
- package/dist/stripe.d.ts +36 -0
- package/dist/stripe.d.ts.map +1 -0
- package/dist/stripe.js +39 -0
- package/dist/stripe.js.map +1 -0
- package/dist/tax.d.ts +29 -0
- package/dist/tax.d.ts.map +1 -0
- package/dist/tax.js +39 -0
- package/dist/tax.js.map +1 -0
- package/package.json +171 -4
- package/src/adyen-fx.ts +154 -0
- package/src/adyen.ts +46 -0
- package/src/allocate.ts +393 -0
- package/src/bag.ts +170 -0
- package/src/braintree.ts +71 -0
- package/src/cash.ts +115 -0
- package/src/checkout.ts +77 -0
- package/src/convert.ts +159 -0
- package/src/currency.ts +61 -0
- package/src/decimal.ts +283 -0
- package/src/ecb.ts +162 -0
- package/src/exact.ts +182 -0
- package/src/fetch.ts +127 -0
- package/src/fixed.ts +558 -0
- package/src/fn.ts +80 -0
- package/src/format.ts +106 -0
- package/src/generated/adyen.ts +144 -0
- package/src/generated/braintree.ts +140 -0
- package/src/generated/cash.ts +375 -0
- package/src/generated/checkout.ts +151 -0
- package/src/generated/iso4217.ts +179 -0
- package/src/generated/kernel.ts +230 -0
- package/src/generated/klarna.ts +21 -0
- package/src/generated/paypal.ts +31 -0
- package/src/generated/stripe.ts +150 -0
- package/src/index.ts +37 -0
- package/src/klarna.ts +54 -0
- package/src/money.ts +781 -0
- package/src/parse.ts +144 -0
- package/src/paypal.ts +93 -0
- package/src/plugins/adyen.ts +25 -0
- package/src/plugins/all.ts +47 -0
- package/src/plugins/allocate.ts +53 -0
- package/src/plugins/braintree.ts +23 -0
- package/src/plugins/cash.ts +33 -0
- package/src/plugins/checkout.ts +32 -0
- package/src/plugins/convert.ts +50 -0
- package/src/plugins/exact.ts +23 -0
- package/src/plugins/fixed.ts +28 -0
- package/src/plugins/format.ts +28 -0
- package/src/plugins/klarna.ts +21 -0
- package/src/plugins/paypal.ts +29 -0
- package/src/plugins/prisma.ts +24 -0
- package/src/plugins/stripe.ts +29 -0
- package/src/plugins/tax.ts +41 -0
- package/src/prisma.ts +118 -0
- package/src/processor.ts +181 -0
- package/src/provider.ts +324 -0
- package/src/rate.ts +377 -0
- package/src/rounding-error.ts +8 -0
- package/src/rounding.ts +122 -0
- package/src/stripe-fx.ts +49 -0
- package/src/stripe.ts +69 -0
- package/src/tax.ts +71 -0
package/src/parse.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { money, type CurrencyInput, type Money, type MoneyOptions } from './money.js';
|
|
2
|
+
|
|
3
|
+
interface Symbols {
|
|
4
|
+
group: string;
|
|
5
|
+
decimal: string;
|
|
6
|
+
}
|
|
7
|
+
const symCache = new Map<string, Symbols>();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The group and decimal separators `format()` uses for this locale and currency. They come from a
|
|
11
|
+
* currency-style formatter, not a plain number one, because some locales use different separators
|
|
12
|
+
* for money: fr-CH writes 1 234.56 € but 1 234,56 for a number, and de-AT 1.234,56 € but 1 234,56.
|
|
13
|
+
*/
|
|
14
|
+
function symbols(locale: string | undefined, currency: string): Symbols {
|
|
15
|
+
const key = `${locale ?? ''}|${currency}`;
|
|
16
|
+
let found = symCache.get(key);
|
|
17
|
+
if (!found) {
|
|
18
|
+
const parts = separatorParts(locale, currency);
|
|
19
|
+
found = {
|
|
20
|
+
group: parts.find((part) => part.type === 'group')?.value ?? ',',
|
|
21
|
+
decimal: parts.find((part) => part.type === 'decimal')?.value ?? '.',
|
|
22
|
+
};
|
|
23
|
+
if (symCache.size > 256) {
|
|
24
|
+
symCache.clear();
|
|
25
|
+
}
|
|
26
|
+
symCache.set(key, found);
|
|
27
|
+
}
|
|
28
|
+
return found;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function separatorParts(locale: string | undefined, currency: string): Intl.NumberFormatPart[] {
|
|
32
|
+
try {
|
|
33
|
+
// Two fraction digits even for JPY and the like, so the decimal separator always appears.
|
|
34
|
+
return new Intl.NumberFormat(locale, {
|
|
35
|
+
style: 'currency',
|
|
36
|
+
currency,
|
|
37
|
+
useGrouping: true,
|
|
38
|
+
minimumFractionDigits: 2,
|
|
39
|
+
maximumFractionDigits: 2,
|
|
40
|
+
}).formatToParts(1234567.5);
|
|
41
|
+
} catch {
|
|
42
|
+
// Codes Intl rejects as currencies (custom ones that are not three letters): a number format's
|
|
43
|
+
// separators.
|
|
44
|
+
return new Intl.NumberFormat(locale, { useGrouping: true }).formatToParts(1234567.5);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Zero code points of the decimal digit blocks Intl uses (arab, arabext, deva, beng, thai,
|
|
49
|
+
// fullwide, ...).
|
|
50
|
+
const ZEROS = [
|
|
51
|
+
0x660, 0x6f0, 0x7c0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, 0xe50, 0xed0,
|
|
52
|
+
0xf20, 0x1040, 0x17e0, 0x1810, 0xff10,
|
|
53
|
+
];
|
|
54
|
+
const FULLWIDTH_ZERO = 0xff10;
|
|
55
|
+
const LAST_BLOCK_BEFORE_FULLWIDTH = 0x1810;
|
|
56
|
+
function asciiDigit(cp: number): number {
|
|
57
|
+
if (cp >= 48 && cp <= 57) {
|
|
58
|
+
return cp - 48;
|
|
59
|
+
}
|
|
60
|
+
// Every non-digit character used to scan the whole table. Separators, signs and Latin-1 spaces
|
|
61
|
+
// are below the first block (U+0660); currency signs such as € (U+20AC) and the narrow no-break
|
|
62
|
+
// space (U+202F) fall in the gap before the fullwidth digits.
|
|
63
|
+
if (cp < ZEROS[0]! || (cp > LAST_BLOCK_BEFORE_FULLWIDTH + 9 && cp < FULLWIDTH_ZERO)) {
|
|
64
|
+
return -1;
|
|
65
|
+
}
|
|
66
|
+
// ZEROS is sorted, so the first block above cp ends the search
|
|
67
|
+
for (let i = 0; i < ZEROS.length; i++) {
|
|
68
|
+
const zero = ZEROS[i]!;
|
|
69
|
+
if (cp < zero) {
|
|
70
|
+
return -1;
|
|
71
|
+
}
|
|
72
|
+
if (cp <= zero + 9) {
|
|
73
|
+
return cp - zero;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return -1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parses a locale-formatted amount: parse('1.234,50 €', 'EUR', 'de-DE'), parse('CHF 1’234.50',
|
|
81
|
+
* 'CHF', 'de-CH'), parse('١٢٣٫٤٥ US$', 'USD', 'ar-EG'). Currency symbols/codes, spaces and bidi
|
|
82
|
+
* marks around the number are ignored (the currency is the `currency` argument, never guessed from
|
|
83
|
+
* the text). A minus sign (ASCII or U+2212) or accounting parentheses anywhere in the affixes make
|
|
84
|
+
* it negative. Inside the number only digits, the locale's group separator (before the decimal
|
|
85
|
+
* separator) and one decimal separator are allowed.
|
|
86
|
+
*/
|
|
87
|
+
export function parse<C extends CurrencyInput>(
|
|
88
|
+
input: string,
|
|
89
|
+
currency: C,
|
|
90
|
+
locale?: string,
|
|
91
|
+
options?: MoneyOptions,
|
|
92
|
+
): Money<C> {
|
|
93
|
+
const { group, decimal } = symbols(locale, currency);
|
|
94
|
+
const chars = Array.from(input);
|
|
95
|
+
let first = -1;
|
|
96
|
+
let last = -1;
|
|
97
|
+
for (let i = 0; i < chars.length; i++) {
|
|
98
|
+
if (asciiDigit(chars[i]!.codePointAt(0)!) >= 0) {
|
|
99
|
+
if (first < 0) {
|
|
100
|
+
first = i;
|
|
101
|
+
}
|
|
102
|
+
last = i;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (first < 0) {
|
|
106
|
+
throw new SyntaxError(`Cannot parse "${input}": no digits`);
|
|
107
|
+
}
|
|
108
|
+
const prefix = chars.slice(0, first).join('');
|
|
109
|
+
const suffix = chars.slice(last + 1).join('');
|
|
110
|
+
const affix = prefix + suffix;
|
|
111
|
+
if (!/^[\p{L}\p{Sc}\p{Z}\s\p{Cf}.()+\-−]*$/u.test(affix)) {
|
|
112
|
+
throw new SyntaxError(`Cannot parse "${input}": unexpected characters`);
|
|
113
|
+
}
|
|
114
|
+
const neg = /[-−(]/.test(affix);
|
|
115
|
+
const isGroup = (ch: string) =>
|
|
116
|
+
ch === group ||
|
|
117
|
+
(/^[\s\p{Z}]$/u.test(group) && /^[\s\p{Z}]$/u.test(ch)) ||
|
|
118
|
+
((group === '’' || group === "'") && (ch === "'" || ch === '’')) ||
|
|
119
|
+
ch === '٬';
|
|
120
|
+
let out = prefix.endsWith(decimal) ? '0.' : '';
|
|
121
|
+
let seenDecimal = out !== '';
|
|
122
|
+
for (let i = first; i <= last; i++) {
|
|
123
|
+
const ch = chars[i]!;
|
|
124
|
+
const digit = asciiDigit(ch.codePointAt(0)!);
|
|
125
|
+
if (digit >= 0) {
|
|
126
|
+
out += digit;
|
|
127
|
+
} else if (ch === decimal || ch === '٫') {
|
|
128
|
+
if (seenDecimal) {
|
|
129
|
+
throw new SyntaxError(`Cannot parse "${input}": more than one decimal separator`);
|
|
130
|
+
}
|
|
131
|
+
seenDecimal = true;
|
|
132
|
+
out += '.';
|
|
133
|
+
} else if (isGroup(ch)) {
|
|
134
|
+
if (seenDecimal) {
|
|
135
|
+
throw new SyntaxError(
|
|
136
|
+
`Cannot parse "${input}": group separator after the decimal separator`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
throw new SyntaxError(`Cannot parse "${input}": unexpected "${ch}"`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return money((neg ? '-' : '') + out, currency, options);
|
|
144
|
+
}
|
package/src/paypal.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPal's amount view for the REST APIs (Orders v2, Payments v2):
|
|
3
|
+
* https://developer.paypal.com/api/rest/reference/currency-codes/, encoded in data/paypal.json.
|
|
4
|
+
* `value` is a decimal string in major units, with at most 15 digits before the point:
|
|
5
|
+
* - HUF, JPY and TWD don't support decimals: "1000", never "1000.00" (ISO 4217 gives HUF and TWD
|
|
6
|
+
* 2);
|
|
7
|
+
* - every other listed currency has 2 decimals: "10.99".
|
|
8
|
+
* BRL, CNY and MYR are for in-country accounts only; that isn't checked here.
|
|
9
|
+
*/
|
|
10
|
+
import { PAYPAL_EXPONENTS } from './generated/paypal.js';
|
|
11
|
+
import { type CurrencyInput, type Money } from './money.js';
|
|
12
|
+
import { fromProcessorDecimal, toProcessorDecimal } from './processor.js';
|
|
13
|
+
import type { RoundingMode } from './rounding.js';
|
|
14
|
+
|
|
15
|
+
export { PAYPAL_EXPONENTS };
|
|
16
|
+
|
|
17
|
+
/** The `value` pattern from PayPal's Orders v2 schema. */
|
|
18
|
+
const VALUE_PATTERN = /^((-?[0-9]+)|(-?([0-9]+)?[.][0-9]+))$/;
|
|
19
|
+
|
|
20
|
+
/** PayPal allows at most 15 digits before the decimal point. */
|
|
21
|
+
const MAX_INTEGER_DIGITS = 15;
|
|
22
|
+
|
|
23
|
+
/** The `value` field's maxLength in the Orders v2 schema. */
|
|
24
|
+
const MAX_VALUE_LENGTH = 32;
|
|
25
|
+
|
|
26
|
+
/** The number of decimals PayPal takes for a currency (JPY, HUF, TWD 0; the others 2). */
|
|
27
|
+
export function paypalExponent(currency: string): number {
|
|
28
|
+
const exponent = PAYPAL_EXPONENTS[currency.toUpperCase()];
|
|
29
|
+
if (exponent === undefined) {
|
|
30
|
+
throw new RangeError(`${currency} is not a PayPal currency`);
|
|
31
|
+
}
|
|
32
|
+
return exponent;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Whether PayPal lists the currency (case-insensitive). */
|
|
36
|
+
export function isPayPalCurrency(currency: string): boolean {
|
|
37
|
+
return PAYPAL_EXPONENTS[currency.toUpperCase()] !== undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Options for the PayPal amount: how to round when PayPal needs a coarser amount. */
|
|
41
|
+
export interface PayPalAmountOptions {
|
|
42
|
+
/**
|
|
43
|
+
* How to round when PayPal needs fewer decimals than the value has (default 'unnecessary':
|
|
44
|
+
* throw).
|
|
45
|
+
*/
|
|
46
|
+
readonly rounding?: RoundingMode;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The exact `value` string: toPayPalValue(money('10.99', 'USD')) === '10.99', HUF 1000 -> '1000'.
|
|
51
|
+
* Throws a RangeError for negative amounts (refunds are sent as positive amounts).
|
|
52
|
+
*/
|
|
53
|
+
export function toPayPalValue(money: Money, options?: PayPalAmountOptions): string {
|
|
54
|
+
const rounding = options?.rounding ?? 'unnecessary';
|
|
55
|
+
|
|
56
|
+
// "The amount must be a positive number"; zero stays allowed because the same money object is
|
|
57
|
+
// used for breakdown fields such as a zero tax_total. Refunds are positive amounts.
|
|
58
|
+
const value = toProcessorDecimal(
|
|
59
|
+
'PayPal',
|
|
60
|
+
money,
|
|
61
|
+
paypalExponent(money.currency),
|
|
62
|
+
rounding,
|
|
63
|
+
'nonNegative',
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const integerDigits = value.replace('-', '').split('.')[0]!;
|
|
67
|
+
if (integerDigits.length > MAX_INTEGER_DIGITS) {
|
|
68
|
+
throw new RangeError(
|
|
69
|
+
`${money} is too large for PayPal (at most 15 digits before the decimal point)`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A PayPal `money` object: `{ currency_code, value }`. */
|
|
76
|
+
export function toPayPal(
|
|
77
|
+
money: Money,
|
|
78
|
+
options?: PayPalAmountOptions,
|
|
79
|
+
): { currency_code: string; value: string } {
|
|
80
|
+
return { currency_code: money.currency.toUpperCase(), value: toPayPalValue(money, options) };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Reads a PayPal `money` object exactly: fromPayPal({ currency_code: 'USD', value: '230.00' }). */
|
|
84
|
+
export function fromPayPal<C extends CurrencyInput>(amount: {
|
|
85
|
+
currency_code: C;
|
|
86
|
+
value: string;
|
|
87
|
+
}): Money<Uppercase<C>> {
|
|
88
|
+
const code = amount.currency_code.toUpperCase() as Uppercase<C>;
|
|
89
|
+
|
|
90
|
+
// Validates the currency before parsing, so an unlisted currency is the error reported.
|
|
91
|
+
paypalExponent(code);
|
|
92
|
+
return fromProcessorDecimal('PayPal', amount.value, code, VALUE_PATTERN, MAX_VALUE_LENGTH);
|
|
93
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** `@ducatjs/money/adyen`: Adyen's minor-unit view. Importing this module adds `toAdyen`. */
|
|
2
|
+
import { toAdyen } from '../adyen.js';
|
|
3
|
+
import { extendMoney, type Money } from '../money.js';
|
|
4
|
+
import type { RoundingMode } from '../rounding.js';
|
|
5
|
+
|
|
6
|
+
export * from '../adyen.js';
|
|
7
|
+
|
|
8
|
+
declare module '../money.js' {
|
|
9
|
+
interface Money<C extends string> {
|
|
10
|
+
/**
|
|
11
|
+
* Adyen `amount` object: `money('15000', 'IDR').toAdyen()` is `{ value: 15000, currency: 'IDR'
|
|
12
|
+
* }`.
|
|
13
|
+
*/
|
|
14
|
+
toAdyen(rounding?: RoundingMode): { value: number; currency: string };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extendMoney(
|
|
19
|
+
{
|
|
20
|
+
toAdyen(this: Money, rounding?: RoundingMode) {
|
|
21
|
+
return toAdyen(this, rounding);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{ owner: '@ducatjs/money/adyen' },
|
|
25
|
+
);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** `@ducatjs/money/all`: core plus every opt-in module, with all methods installed. */
|
|
2
|
+
export * from '../index.js';
|
|
3
|
+
// The core Money methods as plain functions too, as in /fn: /all is everything.
|
|
4
|
+
export {
|
|
5
|
+
add,
|
|
6
|
+
subtract,
|
|
7
|
+
negate,
|
|
8
|
+
abs,
|
|
9
|
+
multiply,
|
|
10
|
+
divide,
|
|
11
|
+
round,
|
|
12
|
+
toScale,
|
|
13
|
+
compare,
|
|
14
|
+
equals,
|
|
15
|
+
lessThan,
|
|
16
|
+
lessThanOrEqual,
|
|
17
|
+
greaterThan,
|
|
18
|
+
greaterThanOrEqual,
|
|
19
|
+
isZero,
|
|
20
|
+
isPositive,
|
|
21
|
+
isNegative,
|
|
22
|
+
sign,
|
|
23
|
+
min,
|
|
24
|
+
max,
|
|
25
|
+
clamp,
|
|
26
|
+
toDecimal,
|
|
27
|
+
toMinor,
|
|
28
|
+
toMinorNumber,
|
|
29
|
+
} from '../money.js';
|
|
30
|
+
export * from './allocate.js';
|
|
31
|
+
export * from './tax.js';
|
|
32
|
+
export * from './convert.js';
|
|
33
|
+
export * from './exact.js';
|
|
34
|
+
export * from '../ecb.js';
|
|
35
|
+
export * from '../stripe-fx.js';
|
|
36
|
+
export * from '../adyen-fx.js';
|
|
37
|
+
export * from './cash.js';
|
|
38
|
+
export * from './format.js';
|
|
39
|
+
export * from '../parse.js';
|
|
40
|
+
export * from './stripe.js';
|
|
41
|
+
export * from './adyen.js';
|
|
42
|
+
export * from './checkout.js';
|
|
43
|
+
export * from './paypal.js';
|
|
44
|
+
export * from './braintree.js';
|
|
45
|
+
export * from './klarna.js';
|
|
46
|
+
export * from './prisma.js';
|
|
47
|
+
export * from './fixed.js';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/allocate`: allocation, splitting and tranches. Importing this module adds the
|
|
3
|
+
* methods below to every Money; the free functions are exported too (and from `@ducatjs/money/fn`,
|
|
4
|
+
* which changes no prototypes).
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
allocate,
|
|
8
|
+
chunk,
|
|
9
|
+
instalments,
|
|
10
|
+
schedule,
|
|
11
|
+
split,
|
|
12
|
+
type AllocateOptions,
|
|
13
|
+
type InstalmentOptions,
|
|
14
|
+
type Tranche,
|
|
15
|
+
type Weight,
|
|
16
|
+
} from '../allocate.js';
|
|
17
|
+
import { extendMoney, type Money } from '../money.js';
|
|
18
|
+
|
|
19
|
+
export * from '../allocate.js';
|
|
20
|
+
|
|
21
|
+
declare module '../money.js' {
|
|
22
|
+
interface Money<C extends string> {
|
|
23
|
+
/** Splits by weights; the parts always sum to this. */
|
|
24
|
+
allocate(weights: readonly Weight[], options?: AllocateOptions): Money<C>[];
|
|
25
|
+
/** Splits into `count` near-equal parts that sum to this. */
|
|
26
|
+
split(count: number, options?: AllocateOptions): Money<C>[];
|
|
27
|
+
instalments(count: number, options?: InstalmentOptions<C>): Money<C>[];
|
|
28
|
+
schedule(tranches: readonly Tranche<C>[]): Money<C>[];
|
|
29
|
+
/** Tranches of at most `max`: 1000 by 300 gives 300, 300, 300, 100. */
|
|
30
|
+
chunk(max: Money<C>): Money<C>[];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
extendMoney(
|
|
35
|
+
{
|
|
36
|
+
allocate(this: Money, weights: readonly Weight[], options?: AllocateOptions) {
|
|
37
|
+
return allocate(this, weights, options);
|
|
38
|
+
},
|
|
39
|
+
split(this: Money, count: number, options?: AllocateOptions) {
|
|
40
|
+
return split(this, count, options);
|
|
41
|
+
},
|
|
42
|
+
instalments(this: Money, count: number, options?: InstalmentOptions<string>) {
|
|
43
|
+
return instalments(this, count, options);
|
|
44
|
+
},
|
|
45
|
+
schedule(this: Money, tranches: readonly Tranche<string>[]) {
|
|
46
|
+
return schedule(this, tranches);
|
|
47
|
+
},
|
|
48
|
+
chunk(this: Money, max: Money) {
|
|
49
|
+
return chunk(this, max);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{ owner: '@ducatjs/money/allocate' },
|
|
53
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/braintree`: Braintree's amount view. Importing this module adds `toBraintree`.
|
|
3
|
+
*/
|
|
4
|
+
import { toBraintree, type BraintreeAmountOptions } from '../braintree.js';
|
|
5
|
+
import { extendMoney, type Money } from '../money.js';
|
|
6
|
+
|
|
7
|
+
export * from '../braintree.js';
|
|
8
|
+
|
|
9
|
+
declare module '../money.js' {
|
|
10
|
+
interface Money<C extends string> {
|
|
11
|
+
/** The exact `amount` string for Braintree: `money('10', 'USD').toBraintree()` is '10.00'. */
|
|
12
|
+
toBraintree(options?: BraintreeAmountOptions): string;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
extendMoney(
|
|
17
|
+
{
|
|
18
|
+
toBraintree(this: Money, options?: BraintreeAmountOptions) {
|
|
19
|
+
return toBraintree(this, options);
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{ owner: '@ducatjs/money/braintree' },
|
|
23
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/cash`: cash rounding (cash tenders only; card payments are never rounded) and
|
|
3
|
+
* rounding to an increment. Importing this module adds the methods below.
|
|
4
|
+
*/
|
|
5
|
+
import { cashRound, roundToIncrement, type CashRoundOptions } from '../cash.js';
|
|
6
|
+
import { extendMoney, type Money } from '../money.js';
|
|
7
|
+
import type { RoundingMode } from '../rounding.js';
|
|
8
|
+
|
|
9
|
+
export * from '../cash.js';
|
|
10
|
+
|
|
11
|
+
declare module '../money.js' {
|
|
12
|
+
interface Money<C extends string> {
|
|
13
|
+
/**
|
|
14
|
+
* Rounds a cash total to the local cash step (CHF 0.05, SEK 1, ...); unchanged when no rule
|
|
15
|
+
* applies.
|
|
16
|
+
*/
|
|
17
|
+
cashRound(options?: CashRoundOptions): Money<C>;
|
|
18
|
+
/** Rounds to a multiple of `increment`, e.g. CHF 10.03 to CHF 0.05 gives CHF 10.05. */
|
|
19
|
+
roundToIncrement(increment: Money<C>, rounding?: RoundingMode): Money<C>;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
extendMoney(
|
|
24
|
+
{
|
|
25
|
+
cashRound(this: Money, options?: CashRoundOptions) {
|
|
26
|
+
return cashRound(this, options);
|
|
27
|
+
},
|
|
28
|
+
roundToIncrement(this: Money, increment: Money, rounding?: RoundingMode) {
|
|
29
|
+
return roundToIncrement(this, increment, rounding);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{ owner: '@ducatjs/money/cash' },
|
|
33
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/checkout`: Checkout.com's amount view. Importing this module adds `toCheckout`
|
|
3
|
+
* and `toCheckoutAmount`.
|
|
4
|
+
*/
|
|
5
|
+
import { toCheckout, toCheckoutAmount, type CheckoutAmountOptions } from '../checkout.js';
|
|
6
|
+
import { extendMoney, type Money } from '../money.js';
|
|
7
|
+
|
|
8
|
+
export * from '../checkout.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/**
|
|
13
|
+
* The integer `amount` to send to Checkout.com: `money('5000', 'CLP').toCheckoutAmount()` is
|
|
14
|
+
* 500000.
|
|
15
|
+
*/
|
|
16
|
+
toCheckoutAmount(options?: CheckoutAmountOptions): number;
|
|
17
|
+
/** `{ amount, currency }` for a Checkout.com payment request. */
|
|
18
|
+
toCheckout(options?: CheckoutAmountOptions): { amount: number; currency: string };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
extendMoney(
|
|
23
|
+
{
|
|
24
|
+
toCheckoutAmount(this: Money, options?: CheckoutAmountOptions) {
|
|
25
|
+
return toCheckoutAmount(this, options);
|
|
26
|
+
},
|
|
27
|
+
toCheckout(this: Money, options?: CheckoutAmountOptions) {
|
|
28
|
+
return toCheckout(this, options);
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{ owner: '@ducatjs/money/checkout' },
|
|
32
|
+
);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/convert`: currency conversion at exact rates. Importing this module adds
|
|
3
|
+
* `Money#convert`.
|
|
4
|
+
*/
|
|
5
|
+
import { convert } from '../convert.js';
|
|
6
|
+
import type { Factor } from '../decimal.js';
|
|
7
|
+
import { extendMoney, type CurrencyInput, type Money } from '../money.js';
|
|
8
|
+
import type { ProviderConvertOptions } from '../convert.js';
|
|
9
|
+
import type { RateProvider } from '../provider.js';
|
|
10
|
+
import type { ConvertOptions, Rate } from '../rate.js';
|
|
11
|
+
import type { RoundingMode } from '../rounding.js';
|
|
12
|
+
|
|
13
|
+
export * from '../convert.js';
|
|
14
|
+
|
|
15
|
+
declare module '../money.js' {
|
|
16
|
+
interface Money<C extends string> {
|
|
17
|
+
/** Converts at a Rate, rounding once: `eur.convert(eurUsd, 'halfEven')`. */
|
|
18
|
+
convert<To extends string>(
|
|
19
|
+
rate: Rate<NoInfer<C>, To>,
|
|
20
|
+
rounding?: RoundingMode,
|
|
21
|
+
options?: ConvertOptions,
|
|
22
|
+
): Money<To>;
|
|
23
|
+
/** Converts at an exact decimal-string rate: `eur.convert('USD', '1.0832', 'halfEven')`. */
|
|
24
|
+
convert<To extends CurrencyInput>(
|
|
25
|
+
to: To,
|
|
26
|
+
rate: Factor,
|
|
27
|
+
rounding?: RoundingMode,
|
|
28
|
+
options?: ConvertOptions,
|
|
29
|
+
): Money<To>;
|
|
30
|
+
/**
|
|
31
|
+
* Converts through a provider, rounding once: `usd.convert('JPY', via('EUR', ecb),
|
|
32
|
+
* 'halfEven')`.
|
|
33
|
+
*/
|
|
34
|
+
convert<To extends CurrencyInput>(
|
|
35
|
+
to: To,
|
|
36
|
+
provider: RateProvider,
|
|
37
|
+
rounding?: RoundingMode,
|
|
38
|
+
options?: ProviderConvertOptions,
|
|
39
|
+
): Money<To>;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
extendMoney(
|
|
44
|
+
{
|
|
45
|
+
convert(this: Money, ...args: [never, never?, never?, never?]) {
|
|
46
|
+
return (convert as (money: Money, ...rest: unknown[]) => Money)(this, ...args);
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{ owner: '@ducatjs/money/convert' },
|
|
50
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/exact`: exact rational amounts that round once. Importing this module adds
|
|
3
|
+
* `Money#exact`.
|
|
4
|
+
*/
|
|
5
|
+
import { exact, type ExactMoney } from '../exact.js';
|
|
6
|
+
import { extendMoney, type Money } from '../money.js';
|
|
7
|
+
|
|
8
|
+
export * from '../exact.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/**
|
|
13
|
+
* The exact value, for chained arithmetic that rounds once: `price.exact().divide(3).round()`.
|
|
14
|
+
*/
|
|
15
|
+
exact(): ExactMoney<C>;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
extendMoney({
|
|
20
|
+
exact(this: Money) {
|
|
21
|
+
return exact(this);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/fixed`: exact fixed-point decimals without a currency, on the same engine as
|
|
3
|
+
* Money. Importing this module adds `Money#toFixedPoint()`.
|
|
4
|
+
*/
|
|
5
|
+
import { moneyToFixed, type Fixed } from '../fixed.js';
|
|
6
|
+
import { extendMoney, type Money } from '../money.js';
|
|
7
|
+
|
|
8
|
+
export * from '../fixed.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/**
|
|
13
|
+
* The exact Fixed of this amount, at its scale: `money('12.34', 'EUR').toFixedPoint()` is
|
|
14
|
+
* 12.34. Not `toFixed`, which Number, decimal.js and big.js all use for `toFixed(places):
|
|
15
|
+
* string`.
|
|
16
|
+
*/
|
|
17
|
+
toFixedPoint(): Fixed;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
extendMoney(
|
|
22
|
+
{
|
|
23
|
+
toFixedPoint(this: Money) {
|
|
24
|
+
return moneyToFixed(this);
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{ owner: '@ducatjs/money/fixed' },
|
|
28
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/format`: locale formatting through Intl. Importing this module adds the methods
|
|
3
|
+
* below.
|
|
4
|
+
*/
|
|
5
|
+
import { format, formatToParts } from '../format.js';
|
|
6
|
+
import { extendMoney, type Money } from '../money.js';
|
|
7
|
+
|
|
8
|
+
export * from '../format.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/** Locale formatting via Intl: `price.format('de-DE')` gives "19,99 €" */
|
|
13
|
+
format(locale?: string, options?: Intl.NumberFormatOptions): string;
|
|
14
|
+
formatToParts(locale?: string, options?: Intl.NumberFormatOptions): Intl.NumberFormatPart[];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extendMoney(
|
|
19
|
+
{
|
|
20
|
+
format(this: Money, locale?: string, options?: Intl.NumberFormatOptions) {
|
|
21
|
+
return format(this, locale, options);
|
|
22
|
+
},
|
|
23
|
+
formatToParts(this: Money, locale?: string, options?: Intl.NumberFormatOptions) {
|
|
24
|
+
return formatToParts(this, locale, options);
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{ owner: '@ducatjs/money/format' },
|
|
28
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** `@ducatjs/money/klarna`: Klarna's amount view. Importing this module adds `toKlarna`. */
|
|
2
|
+
import { toKlarna, type KlarnaAmountOptions } from '../klarna.js';
|
|
3
|
+
import { extendMoney, type Money } from '../money.js';
|
|
4
|
+
|
|
5
|
+
export * from '../klarna.js';
|
|
6
|
+
|
|
7
|
+
declare module '../money.js' {
|
|
8
|
+
interface Money<C extends string> {
|
|
9
|
+
/** The integer for any Klarna amount field: `money('25', 'EUR').toKlarna()` is 2500. */
|
|
10
|
+
toKlarna(options?: KlarnaAmountOptions): number;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
extendMoney(
|
|
15
|
+
{
|
|
16
|
+
toKlarna(this: Money, options?: KlarnaAmountOptions) {
|
|
17
|
+
return toKlarna(this, options);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{ owner: '@ducatjs/money/klarna' },
|
|
21
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/paypal`: PayPal's amount view. Importing this module adds `toPayPal` and
|
|
3
|
+
* `toPayPalValue`.
|
|
4
|
+
*/
|
|
5
|
+
import { extendMoney, type Money } from '../money.js';
|
|
6
|
+
import { toPayPal, toPayPalValue, type PayPalAmountOptions } from '../paypal.js';
|
|
7
|
+
|
|
8
|
+
export * from '../paypal.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/** The exact `value` string for PayPal: `money('1000', 'HUF').toPayPalValue()` is '1000'. */
|
|
13
|
+
toPayPalValue(options?: PayPalAmountOptions): string;
|
|
14
|
+
/** A PayPal `money` object: `{ currency_code, value }`. */
|
|
15
|
+
toPayPal(options?: PayPalAmountOptions): { currency_code: string; value: string };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
extendMoney(
|
|
20
|
+
{
|
|
21
|
+
toPayPalValue(this: Money, options?: PayPalAmountOptions) {
|
|
22
|
+
return toPayPalValue(this, options);
|
|
23
|
+
},
|
|
24
|
+
toPayPal(this: Money, options?: PayPalAmountOptions) {
|
|
25
|
+
return toPayPal(this, options);
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{ owner: '@ducatjs/money/paypal' },
|
|
29
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ducatjs/money/prisma`: Prisma and SQL column helpers. Importing this module adds
|
|
3
|
+
* `toDecimalValue`.
|
|
4
|
+
*/
|
|
5
|
+
import { extendMoney, type Money } from '../money.js';
|
|
6
|
+
import { toDecimalValue } from '../prisma.js';
|
|
7
|
+
|
|
8
|
+
export * from '../prisma.js';
|
|
9
|
+
|
|
10
|
+
declare module '../money.js' {
|
|
11
|
+
interface Money<C extends string> {
|
|
12
|
+
/** A Decimal for a NUMERIC column: `m.toDecimalValue(Prisma.Decimal)`. */
|
|
13
|
+
toDecimalValue<D>(Decimal: new (value: string) => D): D;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
extendMoney(
|
|
18
|
+
{
|
|
19
|
+
toDecimalValue(this: Money, Decimal: new (value: string) => unknown) {
|
|
20
|
+
return toDecimalValue(this, Decimal);
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{ owner: '@ducatjs/money/prisma' },
|
|
24
|
+
);
|