@arki/money 0.0.0-stage → 0.0.4

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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +238 -2
  3. package/dist/bag.d.ts +48 -0
  4. package/dist/bag.d.ts.map +1 -0
  5. package/dist/bag.js +110 -0
  6. package/dist/bag.js.map +1 -0
  7. package/dist/currency.d.ts +64 -0
  8. package/dist/currency.d.ts.map +1 -0
  9. package/dist/currency.js +148 -0
  10. package/dist/currency.js.map +1 -0
  11. package/dist/data/iso4217.d.ts +9 -0
  12. package/dist/data/iso4217.d.ts.map +1 -0
  13. package/dist/data/iso4217.js +11 -0
  14. package/dist/data/iso4217.js.map +1 -0
  15. package/dist/drizzle/config.d.ts +27 -0
  16. package/dist/drizzle/config.d.ts.map +1 -0
  17. package/dist/drizzle/config.js +16 -0
  18. package/dist/drizzle/config.js.map +1 -0
  19. package/dist/drizzle/mysql.d.ts +36 -0
  20. package/dist/drizzle/mysql.d.ts.map +1 -0
  21. package/dist/drizzle/mysql.js +45 -0
  22. package/dist/drizzle/mysql.js.map +1 -0
  23. package/dist/drizzle/pg.d.ts +38 -0
  24. package/dist/drizzle/pg.d.ts.map +1 -0
  25. package/dist/drizzle/pg.js +49 -0
  26. package/dist/drizzle/pg.js.map +1 -0
  27. package/dist/drizzle/sqlite.d.ts +38 -0
  28. package/dist/drizzle/sqlite.d.ts.map +1 -0
  29. package/dist/drizzle/sqlite.js +45 -0
  30. package/dist/drizzle/sqlite.js.map +1 -0
  31. package/dist/drizzle.d.ts +56 -0
  32. package/dist/drizzle.d.ts.map +1 -0
  33. package/dist/drizzle.js +77 -0
  34. package/dist/drizzle.js.map +1 -0
  35. package/dist/errors.d.ts +32 -0
  36. package/dist/errors.d.ts.map +1 -0
  37. package/dist/errors.js +42 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/exact.d.ts +20 -0
  40. package/dist/exact.d.ts.map +1 -0
  41. package/dist/exact.js +23 -0
  42. package/dist/exact.js.map +1 -0
  43. package/dist/exchange.d.ts +84 -0
  44. package/dist/exchange.d.ts.map +1 -0
  45. package/dist/exchange.js +215 -0
  46. package/dist/exchange.js.map +1 -0
  47. package/dist/format.d.ts +41 -0
  48. package/dist/format.d.ts.map +1 -0
  49. package/dist/format.js +122 -0
  50. package/dist/format.js.map +1 -0
  51. package/dist/index.d.ts +7 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +4 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/internal/columns.d.ts +25 -0
  56. package/dist/internal/columns.d.ts.map +1 -0
  57. package/dist/internal/columns.js +47 -0
  58. package/dist/internal/columns.js.map +1 -0
  59. package/dist/internal/units.d.ts +66 -0
  60. package/dist/internal/units.d.ts.map +1 -0
  61. package/dist/internal/units.js +205 -0
  62. package/dist/internal/units.js.map +1 -0
  63. package/dist/money.d.ts +180 -0
  64. package/dist/money.d.ts.map +1 -0
  65. package/dist/money.js +577 -0
  66. package/dist/money.js.map +1 -0
  67. package/dist/parse.d.ts +53 -0
  68. package/dist/parse.d.ts.map +1 -0
  69. package/dist/parse.js +222 -0
  70. package/dist/parse.js.map +1 -0
  71. package/dist/provider.d.ts +22 -0
  72. package/dist/provider.d.ts.map +1 -0
  73. package/dist/provider.js +56 -0
  74. package/dist/provider.js.map +1 -0
  75. package/dist/rational.d.ts +67 -0
  76. package/dist/rational.d.ts.map +1 -0
  77. package/dist/rational.js +169 -0
  78. package/dist/rational.js.map +1 -0
  79. package/dist/stripe.d.ts +37 -0
  80. package/dist/stripe.d.ts.map +1 -0
  81. package/dist/stripe.js +75 -0
  82. package/dist/stripe.js.map +1 -0
  83. package/dist/zod.d.ts +54 -0
  84. package/dist/zod.d.ts.map +1 -0
  85. package/dist/zod.js +96 -0
  86. package/dist/zod.js.map +1 -0
  87. package/package.json +137 -4
  88. package/src/bag.ts +128 -0
  89. package/src/currency.ts +174 -0
  90. package/src/data/iso4217.ts +13 -0
  91. package/src/drizzle/config.ts +39 -0
  92. package/src/drizzle/mysql.ts +61 -0
  93. package/src/drizzle/pg.ts +64 -0
  94. package/src/drizzle/sqlite.ts +61 -0
  95. package/src/errors.ts +61 -0
  96. package/src/exact.ts +29 -0
  97. package/src/exchange.ts +280 -0
  98. package/src/format.ts +148 -0
  99. package/src/index.ts +16 -0
  100. package/src/internal/columns.ts +74 -0
  101. package/src/internal/units.ts +223 -0
  102. package/src/money.ts +692 -0
  103. package/src/parse.ts +278 -0
  104. package/src/provider.ts +67 -0
  105. package/src/rational.ts +214 -0
  106. package/src/stripe.ts +84 -0
  107. package/src/zod.ts +123 -0
package/dist/money.js ADDED
@@ -0,0 +1,577 @@
1
+ /**
2
+ * Exact money. A `Money` is a whole number of units, a scale (how many of the
3
+ * digits are decimals) and a currency: `19.99 EUR` is `1999` units at scale 2.
4
+ *
5
+ * Rules that protect you from silent loss:
6
+ * - Nothing rounds unless you pass a rounding mode. An operation whose exact
7
+ * result does not fit throws `RoundingNecessaryError`.
8
+ * - Mixing currencies throws `CurrencyMismatchError`. With literal codes the
9
+ * compiler already rejects it: `Money<'EUR'>` cannot be added to `Money<'USD'>`.
10
+ * - `allocate` and `split` return parts that add back to the whole exactly.
11
+ * - A `Money` never becomes a float by accident: `+price` throws.
12
+ *
13
+ * Speed: units are a plain `number` while they are a safe integer (up to 90
14
+ * trillion in a two-decimal currency) and a `bigint` only beyond that. Values
15
+ * are immutable through `readonly` and a private constructor; they are not
16
+ * frozen, because `Object.freeze` costs more per operation than the arithmetic.
17
+ */
18
+ import { DivisionByZeroError, EmptyDataError, InvalidArgumentError, NumberFormatError, NumericRangeError, ResourceLimitError, RoundingNecessaryError, } from '@arki/math/errors';
19
+ import { assertSameCurrency, resolveCurrency, toCurrency } from './currency.js';
20
+ import { addUnits, canon, compareUnits, MAX_INPUT_LENGTH, MAX_PARTS, MAX_SCALE, mulDiv, mulUnits, negUnits, parseDecimal, parseNumber, pow10, quantize, } from './internal/units.js';
21
+ const BRAND = Symbol('Money');
22
+ const MAX = Number.MAX_SAFE_INTEGER;
23
+ const INTEGER = /^[+-]?\d+$/;
24
+ // `read()` leaves a factor's fraction here instead of allocating an object.
25
+ let num = 0;
26
+ let den = 1;
27
+ /** A multiplier read once, for loops: `const vat = factor('0.19')`. */
28
+ export class Factor {
29
+ numerator;
30
+ /** Always positive. */
31
+ denominator;
32
+ constructor(numerator, denominator, brand) {
33
+ if (brand !== BRAND)
34
+ throw new TypeError('Use factor(value) instead of new Factor()');
35
+ this.numerator = numerator;
36
+ this.denominator = denominator;
37
+ }
38
+ /** @internal */
39
+ static create(numerator, denominator) {
40
+ return new Factor(numerator, denominator, BRAND);
41
+ }
42
+ }
43
+ /** Prepares a multiplier once so `times` skips parsing: `price.times(vat, 'halfEven')`. */
44
+ export function factor(value) {
45
+ read(value);
46
+ return Factor.create(num, den);
47
+ }
48
+ function read(value) {
49
+ if (typeof value === 'number') {
50
+ if (Number.isSafeInteger(value)) {
51
+ num = value + 0;
52
+ den = 1;
53
+ return;
54
+ }
55
+ const parsed = parseNumber(value);
56
+ num = parsed.coefficient;
57
+ den = pow10(parsed.fraction);
58
+ return;
59
+ }
60
+ if (typeof value === 'string') {
61
+ const parsed = parseDecimal(value);
62
+ num = parsed.coefficient;
63
+ den = pow10(parsed.fraction);
64
+ return;
65
+ }
66
+ if (typeof value === 'bigint') {
67
+ num = canon(value);
68
+ den = 1;
69
+ return;
70
+ }
71
+ if (value instanceof Factor) {
72
+ num = value.numerator;
73
+ den = value.denominator;
74
+ return;
75
+ }
76
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- plain JavaScript can pass null
77
+ if (typeof value === 'object' && value !== null) {
78
+ if ('coefficient' in value && typeof value.coefficient === 'bigint' && typeof value.scale === 'number') {
79
+ if (!Number.isInteger(value.scale) || value.scale < 0 || value.scale > MAX_INPUT_LENGTH * 10) {
80
+ throw new InvalidArgumentError(`Unsupported decimal scale ${value.scale}`);
81
+ }
82
+ num = canon(value.coefficient);
83
+ den = pow10(value.scale);
84
+ return;
85
+ }
86
+ if ('numerator' in value && typeof value.numerator === 'bigint' && typeof value.denominator === 'bigint') {
87
+ if (value.denominator === 0n)
88
+ throw new DivisionByZeroError('A ratio cannot have a zero denominator');
89
+ const negative = value.denominator < 0n;
90
+ num = canon(negative ? -value.numerator : value.numerator);
91
+ den = canon(negative ? -value.denominator : value.denominator);
92
+ return;
93
+ }
94
+ }
95
+ throw new TypeError('Expected a number, string, bigint, Decimal, Rational or Factor');
96
+ }
97
+ function checkScale(scale) {
98
+ if (!Number.isInteger(scale) || scale < 0 || scale > MAX_SCALE) {
99
+ throw new InvalidArgumentError(`A scale is a whole number from 0 to ${MAX_SCALE}, got ${scale}`);
100
+ }
101
+ return scale;
102
+ }
103
+ function refuseCoercion() {
104
+ throw new TypeError('Money cannot be turned into a number implicitly; use toDecimalString(), toMinorUnits() or toNumber()');
105
+ }
106
+ /** An immutable amount of money. Create one with `money()` or the `Money.*` factories. */
107
+ export class Money {
108
+ /** The amount as a whole number of `10^-scale` units, in canonical form: a `number` exactly when it is a safe integer. */
109
+ units;
110
+ /** Number of decimals the amount carries. Equals `currency.scale` unless chosen otherwise. */
111
+ scale;
112
+ currency;
113
+ constructor(units, scale, currency, brand) {
114
+ if (brand !== BRAND)
115
+ throw new TypeError('Use money(amount, currency) instead of new Money()');
116
+ this.units = units;
117
+ this.scale = scale;
118
+ this.currency = currency;
119
+ }
120
+ /** @internal Builds a value from already-validated parts. */
121
+ static create(units, scale, currency) {
122
+ return new Money(units, scale, currency, BRAND);
123
+ }
124
+ // Construction -----------------------------------------------------------
125
+ /**
126
+ * `Money.of('19.99', 'EUR')`. Extra digits throw `RoundingNecessaryError`
127
+ * unless `options.rounding` is given: `Money.of('1.005', 'EUR', { rounding: 'halfEven' })` → `1.00 EUR`.
128
+ * A `Money` input must be in the same currency; this also narrows `Money<string>` to `Money<'EUR'>`.
129
+ */
130
+ static of(amount, currency, options) {
131
+ const cur = toCurrency(currency);
132
+ const scale = options?.scale === undefined ? cur.scale : checkScale(options.scale);
133
+ const rounding = options?.rounding;
134
+ if (amount instanceof Money) {
135
+ assertSameCurrency(amount.currency, cur);
136
+ return new Money(quantize(amount.units, amount.scale, scale, rounding), scale, cur, BRAND);
137
+ }
138
+ read(amount);
139
+ return new Money(mulDiv(num, pow10(scale), den, rounding), scale, cur, BRAND);
140
+ }
141
+ /**
142
+ * From whole minor units: `Money.fromMinor(1999, 'EUR')` → `19.99 EUR`. Accepts a
143
+ * safe-integer `number`, a `bigint`, or an integer string (as databases return
144
+ * `BIGINT`). `scale` says how many decimals the units carry; it defaults to the currency's.
145
+ */
146
+ static fromMinor(units, currency, scale) {
147
+ const cur = toCurrency(currency);
148
+ return new Money(toUnits(units), scale === undefined ? cur.scale : checkScale(scale), cur, BRAND);
149
+ }
150
+ /** Zero in this currency. */
151
+ static zero(currency, scale) {
152
+ const cur = toCurrency(currency);
153
+ return new Money(0, scale === undefined ? cur.scale : checkScale(scale), cur, BRAND);
154
+ }
155
+ /**
156
+ * Reads what `toString()` writes: `'19.99 EUR'`, also `'EUR 19.99'`. Keeps the
157
+ * text's decimals when there are more than the currency's (`'1.2345 EUR'`
158
+ * stays at scale 4). Pass `currencies` to resolve custom codes.
159
+ */
160
+ static parse(text, currencies) {
161
+ if (typeof text !== 'string')
162
+ throw new TypeError('Money.parse expects a string');
163
+ const parts = text.trim().split(/\s+/);
164
+ const [first = '', second = ''] = parts;
165
+ if (parts.length !== 2) {
166
+ throw new NumberFormatError(`Cannot read ${JSON.stringify(text.slice(0, 40))} as money; expected '19.99 EUR'`);
167
+ }
168
+ const amountFirst = /^[+-]?\d/.test(first);
169
+ return fromText(amountFirst ? first : second, resolveCurrency(amountFirst ? second : first, currencies));
170
+ }
171
+ /** Reads `{ amount: '19.99', currency: 'EUR' }`, keeping the amount's decimals. Validates the shape. */
172
+ static fromJSON(value, currencies) {
173
+ if (typeof value !== 'object' || value === null || !('amount' in value) || !('currency' in value)) {
174
+ throw new InvalidArgumentError('Expected { amount: string, currency: string }');
175
+ }
176
+ const { amount, currency } = value;
177
+ if (typeof amount !== 'string' || typeof currency !== 'string') {
178
+ throw new InvalidArgumentError('Expected { amount: string, currency: string }');
179
+ }
180
+ return fromText(amount, resolveCurrency(currency, currencies));
181
+ }
182
+ /** Comparator for sorting: `prices.sort(Money.compare)`. Throws on mixed currencies. */
183
+ static compare(a, b) {
184
+ return a.compareTo(b);
185
+ }
186
+ // Arithmetic -------------------------------------------------------------
187
+ /** Exact sum. Different scales are aligned upward, never rounded. */
188
+ plus(other) {
189
+ const cur = this.currency;
190
+ if (cur !== other.currency)
191
+ assertSameCurrency(cur, other.currency);
192
+ const scale = this.scale;
193
+ if (scale !== other.scale)
194
+ return combine(this, other, false);
195
+ const a = this.units;
196
+ const b = other.units;
197
+ if (typeof a === 'number' && typeof b === 'number') {
198
+ const sum = a + b;
199
+ if (sum <= MAX && sum >= -MAX)
200
+ return new Money(sum, scale, cur, BRAND);
201
+ }
202
+ return new Money(addUnits(a, b), scale, cur, BRAND);
203
+ }
204
+ /** Exact difference. Different scales are aligned upward, never rounded. */
205
+ minus(other) {
206
+ const cur = this.currency;
207
+ if (cur !== other.currency)
208
+ assertSameCurrency(cur, other.currency);
209
+ const scale = this.scale;
210
+ if (scale !== other.scale)
211
+ return combine(this, other, true);
212
+ const a = this.units;
213
+ const b = other.units;
214
+ if (typeof a === 'number' && typeof b === 'number') {
215
+ const difference = a - b;
216
+ if (difference <= MAX && difference >= -MAX)
217
+ return new Money(difference, scale, cur, BRAND);
218
+ }
219
+ return new Money(addUnits(a, negUnits(b)), scale, cur, BRAND);
220
+ }
221
+ /**
222
+ * Multiplies and keeps this scale. `money('10.00', 'EUR').times(3)` → `30.00`.
223
+ * `times('1.19')` on `9.99` is `11.8881`, which does not fit two decimals, so
224
+ * it throws unless you pass a rounding mode: `times('1.19', 'halfEven')` → `11.89`.
225
+ */
226
+ times(multiplier, rounding) {
227
+ if (typeof multiplier === 'number' && Number.isSafeInteger(multiplier)) {
228
+ return new Money(mulUnits(this.units, multiplier), this.scale, this.currency, BRAND);
229
+ }
230
+ read(multiplier);
231
+ return new Money(mulDiv(this.units, num, den, rounding), this.scale, this.currency, BRAND);
232
+ }
233
+ /** Divides and keeps this scale. Inexact results need a rounding mode. Zero throws `DivisionByZeroError`. */
234
+ dividedBy(divisor, rounding) {
235
+ read(divisor);
236
+ const n = num;
237
+ const d = den;
238
+ if (n === 0)
239
+ throw new DivisionByZeroError('Division by zero');
240
+ const units = n < 0 ? mulDiv(negUnits(this.units), d, negUnits(n), rounding) : mulDiv(this.units, d, n, rounding);
241
+ return new Money(units, this.scale, this.currency, BRAND);
242
+ }
243
+ /** `money(200, 'EUR').percentage(15)` → `30.00 EUR`. Same as `times(percent / 100)`. */
244
+ percentage(percent, rounding) {
245
+ read(percent);
246
+ return new Money(mulDiv(this.units, num, mulUnits(den, 100), rounding), this.scale, this.currency, BRAND);
247
+ }
248
+ negated() {
249
+ return new Money(negUnits(this.units), this.scale, this.currency, BRAND);
250
+ }
251
+ abs() {
252
+ return this.units < 0 ? this.negated() : this;
253
+ }
254
+ /** Changes the number of decimals. Dropping non-zero digits needs a rounding mode. */
255
+ toScale(scale, rounding) {
256
+ checkScale(scale);
257
+ if (scale === this.scale)
258
+ return this;
259
+ return new Money(quantize(this.units, this.scale, scale, rounding), scale, this.currency, BRAND);
260
+ }
261
+ /**
262
+ * Rounds to a multiple of `step`, for cash: `chf.roundToStep('0.05', 'halfUp')`.
263
+ * Cash steps are set by each country's law (CHF 0.05, SEK 1, EUR 0.05 in some
264
+ * euro countries), so the package does not guess them. The step must fit this scale.
265
+ */
266
+ roundToStep(step, rounding) {
267
+ read(step);
268
+ if (!(num > 0))
269
+ throw new InvalidArgumentError('A rounding step must be positive');
270
+ let stepUnits;
271
+ try {
272
+ stepUnits = mulDiv(num, pow10(this.scale), den);
273
+ }
274
+ catch (error) {
275
+ if (!(error instanceof RoundingNecessaryError))
276
+ throw error;
277
+ throw new InvalidArgumentError(`The step has more decimals than this amount's ${this.scale}`, { cause: error });
278
+ }
279
+ const units = mulUnits(mulDiv(this.units, 1, stepUnits, rounding), stepUnits);
280
+ return new Money(units, this.scale, this.currency, BRAND);
281
+ }
282
+ // Allocation -------------------------------------------------------------
283
+ /**
284
+ * Splits by ratios into parts that add back to this amount exactly:
285
+ * `money(100, 'EUR').allocate([1, 1, 1])` → `[33.34, 33.33, 33.33]`.
286
+ * Ratios are non-negative numbers, bigints or decimal strings, not all zero.
287
+ * A negative amount is split like a positive one and each part re-signed.
288
+ */
289
+ allocate(ratios, options) {
290
+ const count = ratios.length;
291
+ if (count === 0)
292
+ throw new InvalidArgumentError('allocate needs at least one ratio');
293
+ if (count > MAX_PARTS)
294
+ throw new ResourceLimitError(`allocate makes at most ${MAX_PARTS} parts`);
295
+ const coefficients = [];
296
+ const fractions = [];
297
+ let common = 0;
298
+ for (const ratio of ratios) {
299
+ const parsed = typeof ratio === 'number'
300
+ ? parseNumber(ratio)
301
+ : typeof ratio === 'string'
302
+ ? parseDecimal(ratio)
303
+ : typeof ratio === 'bigint'
304
+ ? { coefficient: canon(ratio), fraction: 0 }
305
+ : badRatio();
306
+ if (parsed.coefficient < 0)
307
+ throw new InvalidArgumentError(`Ratios must not be negative, got ${String(ratio)}`);
308
+ coefficients.push(parsed.coefficient);
309
+ fractions.push(parsed.fraction);
310
+ if (parsed.fraction > common)
311
+ common = parsed.fraction;
312
+ }
313
+ const weights = [];
314
+ let total = 0;
315
+ for (let i = 0; i < count; i++) {
316
+ const weight = mulUnits(coefficients[i] ?? 0, pow10(common - (fractions[i] ?? 0)));
317
+ weights.push(weight);
318
+ total = addUnits(total, weight);
319
+ }
320
+ if (total === 0)
321
+ throw new InvalidArgumentError('Ratios must not all be zero');
322
+ return distribute(this, weights, total, options?.remainder ?? 'largest');
323
+ }
324
+ /** Splits into `parts` equal shares that differ by at most one unit: `money(10, 'EUR').split(3)` → `[3.34, 3.33, 3.33]`. */
325
+ split(parts, options) {
326
+ if (!Number.isInteger(parts) || parts < 1)
327
+ throw new InvalidArgumentError(`split needs a whole number of parts ≥ 1, got ${parts}`);
328
+ if (parts > MAX_PARTS)
329
+ throw new ResourceLimitError(`split makes at most ${MAX_PARTS} parts`);
330
+ const negative = this.units < 0;
331
+ const magnitude = negative ? negUnits(this.units) : this.units;
332
+ const share = mulDiv(magnitude, 1, parts, 'down');
333
+ const left = Number(addUnits(magnitude, negUnits(mulUnits(share, parts))));
334
+ const bigger = addUnits(share, 1);
335
+ const fromEnd = options?.remainder === 'last';
336
+ const result = [];
337
+ for (let i = 0; i < parts; i++) {
338
+ const gets = fromEnd ? i >= parts - left : i < left;
339
+ const units = gets ? bigger : share;
340
+ result.push(new Money(negative ? negUnits(units) : units, this.scale, this.currency, BRAND));
341
+ }
342
+ return result;
343
+ }
344
+ // Comparison -------------------------------------------------------------
345
+ /** Compares values across scales (`1.5` equals `1.50`). Throws on mixed currencies. */
346
+ compareTo(other) {
347
+ if (this.currency !== other.currency)
348
+ assertSameCurrency(this.currency, other.currency);
349
+ if (this.scale === other.scale)
350
+ return compareUnits(this.units, other.units);
351
+ const scale = Math.max(this.scale, other.scale);
352
+ return compareUnits(mulUnits(this.units, pow10(scale - this.scale)), mulUnits(other.units, pow10(scale - other.scale)));
353
+ }
354
+ eq(other) {
355
+ return this.compareTo(other) === 0;
356
+ }
357
+ lt(other) {
358
+ return this.compareTo(other) < 0;
359
+ }
360
+ lte(other) {
361
+ return this.compareTo(other) <= 0;
362
+ }
363
+ gt(other) {
364
+ return this.compareTo(other) > 0;
365
+ }
366
+ gte(other) {
367
+ return this.compareTo(other) >= 0;
368
+ }
369
+ isZero() {
370
+ return this.units === 0;
371
+ }
372
+ isPositive() {
373
+ return this.units > 0;
374
+ }
375
+ isNegative() {
376
+ return this.units < 0;
377
+ }
378
+ sign() {
379
+ return compareUnits(this.units, 0);
380
+ }
381
+ /** Same currency. Never throws. */
382
+ hasSameCurrency(other) {
383
+ return this.currency.eq(other.currency);
384
+ }
385
+ // Output -----------------------------------------------------------------
386
+ /** Units at the currency's scale: `19.99 EUR` → `1999`. Throws `RoundingNecessaryError` if sub-cent digits are not zero. */
387
+ toMinorUnits() {
388
+ return quantize(this.units, this.scale, this.currency.scale);
389
+ }
390
+ /** `toMinorUnits()` as a `bigint`. */
391
+ toMinorBigInt() {
392
+ return BigInt(this.toMinorUnits());
393
+ }
394
+ /** `toMinorUnits()` as a `number`, as payment APIs want. Throws `NumericRangeError` past 2^53. */
395
+ toMinorNumber() {
396
+ const units = this.toMinorUnits();
397
+ if (typeof units !== 'number')
398
+ throw new NumericRangeError(`${this.toString()} has too many minor units for a number`);
399
+ return units;
400
+ }
401
+ /** Plain decimal text with exactly `scale` decimals: `'19.99'`, `'-0.50'`, `'1000'` for JPY. For databases. */
402
+ toDecimalString() {
403
+ const units = this.units;
404
+ const negative = units < 0;
405
+ let digits = String(negative ? negUnits(units) : units);
406
+ const scale = this.scale;
407
+ if (scale === 0)
408
+ return negative ? `-${digits}` : digits;
409
+ if (digits.length <= scale)
410
+ digits = '0'.repeat(scale - digits.length + 1) + digits;
411
+ const text = `${digits.slice(0, -scale)}.${digits.slice(-scale)}`;
412
+ return negative ? `-${text}` : text;
413
+ }
414
+ /** The nearest double. For charts and display math only, never for more money math. */
415
+ toNumber() {
416
+ return Number(this.toDecimalString());
417
+ }
418
+ /** `'19.99 EUR'`. Locale-free; `Money.parse` reads it back. */
419
+ toString() {
420
+ return `${this.toDecimalString()} ${this.currency.code}`;
421
+ }
422
+ /** `{ amount: '19.99', currency: 'EUR' }`. The amount is a string, so no digit is ever lost. */
423
+ toJSON() {
424
+ return { amount: this.toDecimalString(), currency: this.currency.code };
425
+ }
426
+ /** Throws. A `Money` never silently becomes a float. */
427
+ valueOf() {
428
+ return refuseCoercion();
429
+ }
430
+ [Symbol.toPrimitive](hint) {
431
+ return hint === 'string' ? this.toString() : refuseCoercion();
432
+ }
433
+ // A getter lives on the prototype; a field would add a slot to every Money.
434
+ // eslint-disable-next-line @typescript-eslint/class-literal-property-style
435
+ get [Symbol.toStringTag]() {
436
+ return 'Money';
437
+ }
438
+ [Symbol.for('nodejs.util.inspect.custom')]() {
439
+ return `Money(${this.toString()})`;
440
+ }
441
+ [Symbol.for('Deno.customInspect')]() {
442
+ return `Money(${this.toString()})`;
443
+ }
444
+ }
445
+ function badRatio() {
446
+ throw new TypeError('Ratios must be numbers, bigints or decimal strings');
447
+ }
448
+ function toUnits(value) {
449
+ if (typeof value === 'number') {
450
+ if (!Number.isSafeInteger(value))
451
+ throw new NumericRangeError(`Minor units must be a safe integer, got ${value}`);
452
+ return value + 0;
453
+ }
454
+ if (typeof value === 'bigint')
455
+ return canon(value);
456
+ if (typeof value === 'string' && value.length <= MAX_INPUT_LENGTH && INTEGER.test(value))
457
+ return canon(BigInt(value));
458
+ throw new NumberFormatError(`Minor units must be a whole number, got ${JSON.stringify(String(value).slice(0, 40))}`);
459
+ }
460
+ function fromText(text, currency) {
461
+ const parsed = parseDecimal(text);
462
+ const scale = checkScale(Math.max(parsed.fraction, currency.scale));
463
+ return Money.create(quantize(parsed.coefficient, parsed.fraction, scale), scale, currency);
464
+ }
465
+ function combine(a, b, subtract) {
466
+ const scale = Math.max(a.scale, b.scale);
467
+ const left = mulUnits(a.units, pow10(scale - a.scale));
468
+ const right = mulUnits(b.units, pow10(scale - b.scale));
469
+ return Money.create(addUnits(left, subtract ? negUnits(right) : right), scale, a.currency);
470
+ }
471
+ function distribute(whole, weights, total, policy) {
472
+ const negative = whole.units < 0;
473
+ const magnitude = negative ? negUnits(whole.units) : whole.units;
474
+ const count = weights.length;
475
+ const shares = [];
476
+ const rests = [];
477
+ let given = 0;
478
+ for (let i = 0; i < count; i++) {
479
+ const exact = mulUnits(magnitude, weights[i] ?? 0);
480
+ const share = mulDiv(exact, 1, total, 'down');
481
+ shares.push(share);
482
+ rests.push(addUnits(exact, negUnits(mulUnits(share, total))));
483
+ given = addUnits(given, share);
484
+ }
485
+ // Fewer than `count` units are left, and only parts with a non-zero rest can need one.
486
+ let left = Number(addUnits(magnitude, negUnits(given)));
487
+ if (left > 0) {
488
+ const order = [];
489
+ for (let i = 0; i < count; i++)
490
+ if (weights[i] !== 0)
491
+ order.push(i);
492
+ if (policy === 'largest')
493
+ order.sort((x, y) => compareUnits(rests[y] ?? 0, rests[x] ?? 0) || x - y);
494
+ else if (policy === 'last')
495
+ order.reverse();
496
+ for (const index of order) {
497
+ if (left === 0)
498
+ break;
499
+ shares[index] = addUnits(shares[index] ?? 0, 1);
500
+ left -= 1;
501
+ }
502
+ }
503
+ return shares.map(share => Money.create(negative ? negUnits(share) : share, whole.scale, whole.currency));
504
+ }
505
+ // Shorthands and aggregates ------------------------------------------------
506
+ /** Shorthand for `Money.of`: `money('19.99', 'EUR')`. */
507
+ export function money(amount, currency, options) {
508
+ return Money.of(amount, currency, options);
509
+ }
510
+ export function isMoney(value) {
511
+ return value instanceof Money;
512
+ }
513
+ /**
514
+ * Exact total of one currency, with one allocation for the result. An empty
515
+ * list needs `currency` and returns zero; otherwise it throws `InvalidArgumentError`.
516
+ */
517
+ export function sum(items, currency) {
518
+ let cur = currency === undefined ? undefined : toCurrency(currency);
519
+ let scale = cur?.scale ?? -1;
520
+ let units = 0;
521
+ for (const item of items) {
522
+ if (cur === undefined) {
523
+ cur = item.currency;
524
+ scale = item.scale;
525
+ }
526
+ else if (cur !== item.currency) {
527
+ assertSameCurrency(cur, item.currency);
528
+ }
529
+ let value = item.units;
530
+ if (item.scale > scale) {
531
+ units = mulUnits(units, pow10(item.scale - scale));
532
+ scale = item.scale;
533
+ }
534
+ else if (item.scale < scale) {
535
+ value = mulUnits(value, pow10(scale - item.scale));
536
+ }
537
+ if (typeof units === 'number' && typeof value === 'number') {
538
+ const next = units + value;
539
+ units = next <= MAX && next >= -MAX ? next : addUnits(units, value);
540
+ }
541
+ else {
542
+ units = addUnits(units, value);
543
+ }
544
+ }
545
+ if (cur === undefined)
546
+ throw new InvalidArgumentError('sum of an empty list needs a currency');
547
+ return Money.create(units, scale, cur);
548
+ }
549
+ /** Mean of one currency. Inexact results need a rounding mode. An empty list throws `EmptyDataError`. */
550
+ export function average(items, rounding) {
551
+ const list = [...items];
552
+ if (list.length === 0)
553
+ throw new EmptyDataError('average of an empty list');
554
+ return sum(list).dividedBy(list.length, rounding);
555
+ }
556
+ /** The smallest value; ties return the first. */
557
+ export function min(first, ...rest) {
558
+ let best = first;
559
+ for (const item of rest)
560
+ if (item.lt(best))
561
+ best = item;
562
+ return best;
563
+ }
564
+ /** The largest value; ties return the first. */
565
+ export function max(first, ...rest) {
566
+ let best = first;
567
+ for (const item of rest)
568
+ if (item.gt(best))
569
+ best = item;
570
+ return best;
571
+ }
572
+ /** @internal Reads an amount or factor as an exact fraction whose denominator is positive. */
573
+ export function toFraction(value) {
574
+ read(value);
575
+ return [num, den];
576
+ }
577
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACL,QAAQ,EACR,KAAK,EACL,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,KAAK,EACL,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAwC7B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACpC,MAAM,OAAO,GAAG,YAAY,CAAC;AAE7B,4EAA4E;AAC5E,IAAI,GAAG,GAAU,CAAC,CAAC;AACnB,IAAI,GAAG,GAAU,CAAC,CAAC;AAEnB,uEAAuE;AACvE,MAAM,OAAO,MAAM;IACR,SAAS,CAAQ;IAC1B,uBAAuB;IACd,WAAW,CAAQ;IAE5B,YAAoB,SAAgB,EAAE,WAAkB,EAAE,KAAmB;QAC3E,IAAI,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;QACtF,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,gBAAgB;IAChB,MAAM,CAAC,MAAM,CAAC,SAAgB,EAAE,WAAkB;QAChD,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;CACF;AAED,2FAA2F;AAC3F,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,IAAI,CAAC,KAAK,CAAC,CAAC;IACZ,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,IAAI,CAAC,KAAkB;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC;YAChB,GAAG,GAAG,CAAC,CAAC;YACR,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;QACzB,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;QACzB,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACnB,GAAG,GAAG,CAAC,CAAC;QACR,OAAO;IACT,CAAC;IACD,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;QAC5B,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC;QACxB,OAAO;IACT,CAAC;IACD,yGAAyG;IACzG,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,IAAI,aAAa,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,gBAAgB,GAAG,EAAE,EAAE,CAAC;gBAC7F,MAAM,IAAI,oBAAoB,CAAC,6BAA6B,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC7E,CAAC;YACD,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC/B,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,WAAW,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACzG,IAAI,KAAK,CAAC,WAAW,KAAK,EAAE;gBAAE,MAAM,IAAI,mBAAmB,CAAC,wCAAwC,CAAC,CAAC;YACtG,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC;YACxC,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC3D,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;IACH,CAAC;IACD,MAAM,IAAI,SAAS,CAAC,gEAAgE,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;QAC/D,MAAM,IAAI,oBAAoB,CAAC,uCAAuC,SAAS,SAAS,KAAK,EAAE,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,IAAI,SAAS,CACjB,sGAAsG,CACvG,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,OAAO,KAAK;IAChB,0HAA0H;IACjH,KAAK,CAAQ;IACtB,8FAA8F;IACrF,KAAK,CAAS;IACd,QAAQ,CAAc;IAE/B,YAAoB,KAAY,EAAE,KAAa,EAAE,QAAqB,EAAE,KAAmB;QACzF,IAAI,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;QAC/F,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,MAAM,CAAmB,KAAY,EAAE,KAAa,EAAE,QAAqB;QAChF,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,2EAA2E;IAE3E;;;;OAIG;IACH,MAAM,CAAC,EAAE,CACP,MAAsB,EACtB,QAAyB,EACzB,OAAsB;QAEtB,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;QACnC,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;YAC5B,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACzC,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,CAAC;QACb,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAChF,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS,CACd,KAA+B,EAC/B,QAAyB,EACzB,KAAc;QAEd,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACpG,CAAC;IAED,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CAAyB,QAAyB,EAAE,KAAc;QAC3E,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACvF,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,IAAY,EAAE,UAAgC;QACzD,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,SAAS,CAAC,8BAA8B,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;QACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,iBAAiB,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iCAAiC,CAAC,CAAC;QACjH,CAAC;QACD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3G,CAAC;IAED,wGAAwG;IACxG,MAAM,CAAC,QAAQ,CAAC,KAAc,EAAE,UAAgC;QAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;YAClG,MAAM,IAAI,oBAAoB,CAAC,+CAA+C,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QACnC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/D,MAAM,IAAI,oBAAoB,CAAC,+CAA+C,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,wFAAwF;IACxF,MAAM,CAAC,OAAO,CAAa,CAAQ,EAAE,CAAQ;QAC3C,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,2EAA2E;IAE3E,qEAAqE;IACrE,IAAI,CAAC,KAAe;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,IAAI,GAAG,KAAK,KAAK,CAAC,QAAQ;YAAE,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,KAAK,KAAK,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnD,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YAClB,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,KAAe;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,IAAI,GAAG,KAAK,KAAK,CAAC,QAAQ;YAAE,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,KAAK,KAAK,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnD,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,IAAI,UAAU,IAAI,GAAG,IAAI,UAAU,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAuB,EAAE,QAAuB;QACpD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;YACvE,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,CAAC;QACjB,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7F,CAAC;IAED,6GAA6G;IAC7G,SAAS,CAAC,OAAoB,EAAE,QAAuB;QACrD,IAAI,CAAC,OAAO,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,GAAG,CAAC;QACd,MAAM,CAAC,GAAG,GAAG,CAAC;QACd,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClH,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,wFAAwF;IACxF,UAAU,CAAC,OAAoB,EAAE,QAAuB;QACtD,IAAI,CAAC,OAAO,CAAC,CAAC;QACd,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5G,CAAC;IAED,OAAO;QACL,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAa,EAAE,QAAuB;QAC5C,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnG,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,IAAiB,EAAE,QAAuB;QACpD,IAAI,CAAC,IAAI,CAAC,CAAC;QACX,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YAAE,MAAM,IAAI,oBAAoB,CAAC,kCAAkC,CAAC,CAAC;QACnF,IAAI,SAAgB,CAAC;QACrB,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,sBAAsB,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC5D,MAAM,IAAI,oBAAoB,CAAC,iDAAiD,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAClH,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;QAC9E,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,2EAA2E;IAE3E;;;;;OAKG;IACH,QAAQ,CAAC,MAA6C,EAAE,OAAyB;QAC/E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,KAAK,KAAK,CAAC;YAAE,MAAM,IAAI,oBAAoB,CAAC,mCAAmC,CAAC,CAAC;QACrF,IAAI,KAAK,GAAG,SAAS;YAAE,MAAM,IAAI,kBAAkB,CAAC,0BAA0B,SAAS,QAAQ,CAAC,CAAC;QACjG,MAAM,YAAY,GAAY,EAAE,CAAC;QACjC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,MAAM,GACV,OAAO,KAAK,KAAK,QAAQ;gBACvB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC;gBACpB,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;oBACzB,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC;oBACrB,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;wBACzB,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;wBAC5C,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrB,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC;gBAAE,MAAM,IAAI,oBAAoB,CAAC,oCAAoC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChH,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACtC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,MAAM,CAAC,QAAQ,GAAG,MAAM;gBAAE,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QACzD,CAAC;QACD,MAAM,OAAO,GAAY,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAU,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,KAAK,KAAK,CAAC;YAAE,MAAM,IAAI,oBAAoB,CAAC,6BAA6B,CAAC,CAAC;QAC/E,OAAO,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,IAAI,SAAS,CAAC,CAAC;IAC3E,CAAC;IAED,4HAA4H;IAC5H,KAAK,CAAC,KAAa,EAAE,OAAyB;QAC5C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YACvC,MAAM,IAAI,oBAAoB,CAAC,gDAAgD,KAAK,EAAE,CAAC,CAAC;QAC1F,IAAI,KAAK,GAAG,SAAS;YAAE,MAAM,IAAI,kBAAkB,CAAC,uBAAuB,SAAS,QAAQ,CAAC,CAAC;QAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,EAAE,SAAS,KAAK,MAAM,CAAC;QAC9C,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACpD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,2EAA2E;IAE3E,uFAAuF;IACvF,SAAS,CAAC,KAAe;QACvB,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;YAAE,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxF,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;YAAE,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,YAAY,CACjB,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAC/C,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAClD,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,KAAe;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,EAAE,CAAC,KAAe;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,EAAE,CAAC,KAAe;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,IAAI;QACF,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,mCAAmC;IACnC,eAAe,CAAC,KAAY;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,2EAA2E;IAE3E,4HAA4H;IAC5H,YAAY;QACV,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC;IAED,sCAAsC;IACtC,aAAa;QACX,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,kGAAkG;IAClG,aAAa;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,MAAM,IAAI,iBAAiB,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,wCAAwC,CAAC,CAAC;QAC1F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,+GAA+G;IAC/G,eAAe;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;QAC3B,IAAI,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACzD,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;QACpF,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAClE,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACtC,CAAC;IAED,uFAAuF;IACvF,QAAQ;QACN,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,+DAA+D;IAC/D,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3D,CAAC;IAED,gGAAgG;IAChG,MAAM;QACJ,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC1E,CAAC;IAED,wDAAwD;IACxD,OAAO;QACL,OAAO,cAAc,EAAE,CAAC;IAC1B,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAY;QAC/B,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;IAChE,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QACxC,OAAO,SAAS,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;IACrC,CAAC;IAED,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAChC,OAAO,SAAS,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;IACrC,CAAC;CACF;AAED,SAAS,QAAQ;IACf,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,OAAO,CAAC,KAA+B;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,iBAAiB,CAAC,2CAA2C,KAAK,EAAE,CAAC,CAAC;QAClH,OAAO,KAAK,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtH,MAAM,IAAI,iBAAiB,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACvH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAkB;IAChD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,OAAO,CAAmB,CAAW,EAAE,CAAW,EAAE,QAAiB;IAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,UAAU,CACjB,KAAe,EACf,OAAyB,EACzB,KAAY,EACZ,MAAuB;IAEvB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAC7B,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAY,EAAE,CAAC;IAC1B,IAAI,KAAK,GAAU,CAAC,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,uFAAuF;IACvF,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;YAAE,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;aAC/F,IAAI,MAAM,KAAK,MAAM;YAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,IAAI,KAAK,CAAC;gBAAE,MAAM;YACtB,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAChD,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED,6EAA6E;AAE7E,yDAAyD;AACzD,MAAM,UAAU,KAAK,CACnB,MAAsB,EACtB,QAAyB,EACzB,OAAsB;IAEtB,OAAO,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAyB,KAAyB,EAAE,QAA0B;IAC/F,IAAI,GAAG,GAA4B,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7F,IAAI,KAAK,GAAG,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IAC7B,IAAI,KAAK,GAAU,CAAC,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;YACpB,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC;YACvB,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;YACnD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC;YAC9B,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC3D,MAAM,IAAI,GAAW,KAAK,GAAG,KAAK,CAAC;YACnC,KAAK,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,oBAAoB,CAAC,uCAAuC,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,OAAO,CAAyB,KAAyB,EAAE,QAAuB;IAChG,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,0BAA0B,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,GAAG,CAAyB,KAAe,EAAE,GAAG,IAAgB;IAC9E,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI;QAAE,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,GAAG,CAAyB,KAAe,EAAE,GAAG,IAAgB;IAC9E,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI;QAAE,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,IAAI,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,IAAI,CAAC,KAAK,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Strict parsing of money typed by people: `'1.234,56 €'` in German,
3
+ * `'$1,234.56'` in English, `'₹1,23,456.78'` in Indian English.
4
+ *
5
+ * The locale's separators, digits, minus sign and currency symbols come from
6
+ * `Intl.NumberFormat#formatToParts`. You always say which currency you expect,
7
+ * so `'$10'` never has to guess between US, Canadian or Australian dollars.
8
+ *
9
+ * Strict means it refuses instead of guessing: grouping in the wrong place
10
+ * (`'1,23,4'`), a decimal separator the locale does not use, two signs, mixed
11
+ * digit scripts, a different currency's symbol, or any trailing text all throw
12
+ * `NumberFormatError`. Text without grouping is always fine: `'1234.5'`.
13
+ *
14
+ * Runtimes without `formatToParts` (React Native's Hermes on iOS) throw
15
+ * `UnsupportedFeatureError`; pass `symbols` to parse without `Intl`.
16
+ */
17
+ import type { RoundingMode } from '@arki/math/rounding';
18
+ import type { CurrencyLike } from './currency.js';
19
+ import { Money } from './money.js';
20
+ export type ParseSymbols = {
21
+ /** Decimal separator, such as `','`. */
22
+ decimal: string;
23
+ /** Group separator, such as `'.'`. Omit when the input never has grouping. */
24
+ group?: string;
25
+ /** Digits per group: `[3]` for most locales, `[3, 2]` for Indian grouping. Defaults to `[3]`. */
26
+ groupSizes?: readonly [primary: number, secondary?: number];
27
+ /** Currency marks to accept besides the code, such as `['€']`. */
28
+ currency?: readonly string[];
29
+ };
30
+ export type ParseOptions = {
31
+ /** BCP 47 locale. Defaults to `'en-US'`; there is no global locale. */
32
+ locale?: string;
33
+ /** How to drop digits beyond the scale. Without it, extra digits throw `RoundingNecessaryError`. */
34
+ rounding?: RoundingMode;
35
+ /** Decimals to keep. Defaults to the currency's. */
36
+ scale?: number;
37
+ /** Separators to use instead of asking `Intl`, for runtimes without `formatToParts`. */
38
+ symbols?: ParseSymbols;
39
+ };
40
+ export type MoneyParser<C extends string> = {
41
+ /** Parses or throws `NumberFormatError` (bad text) or `RoundingNecessaryError` (too many decimals). */
42
+ parse(text: string): Money<C>;
43
+ /** Parses or returns `undefined`, for form validation. Still throws for runtime capability errors. */
44
+ tryParse(text: string): Money<C> | undefined;
45
+ };
46
+ /**
47
+ * Prepares the locale's grammar once, for forms and imports:
48
+ * `const parse = createMoneyParser('EUR', { locale: 'de-DE' }); parse.parse('1.234,56 €')`.
49
+ */
50
+ export declare function createMoneyParser<const C extends string>(currency: CurrencyLike<C>, options?: ParseOptions): MoneyParser<C>;
51
+ /** One-shot form of `createMoneyParser`: `parseMoney('1.234,56 €', 'EUR', { locale: 'de-DE' })`. */
52
+ export declare function parseMoney<const C extends string>(text: string, currency: CurrencyLike<C>, options?: ParseOptions): Money<C>;
53
+ //# sourceMappingURL=parse.d.ts.map