@ultimat3/money 31.4.2 → 31.5.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/package.json +3 -3
- package/src/convert.ts +10 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/money",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.5.0",
|
|
4
4
|
"description": "Integer minor units with an attached currency: arithmetic, allocation, rounding, Intl formatting",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ultimate",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"test": "bun test"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@ultimat3/core": "31.
|
|
48
|
-
"@ultimat3/schema": "31.
|
|
47
|
+
"@ultimat3/core": "31.5.0",
|
|
48
|
+
"@ultimat3/schema": "31.5.0"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/src/convert.ts
CHANGED
|
@@ -68,7 +68,7 @@ export function convert(
|
|
|
68
68
|
throw rateUnusable(amount.currency, target, 'rate');
|
|
69
69
|
}
|
|
70
70
|
// `at` is the audit trail: an Invalid Date threw a bare `RangeError` out of `toISOString`.
|
|
71
|
-
if (!(rate.at
|
|
71
|
+
if (!isValidDate(rate.at)) {
|
|
72
72
|
throw rateUnusable(amount.currency, target, 'at');
|
|
73
73
|
}
|
|
74
74
|
if (rate.ratio !== undefined && !isPositiveFraction(rate.ratio)) {
|
|
@@ -100,6 +100,11 @@ export function convert(
|
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/** A `Date` whose instant exists — `toISOString()` on any other throws a bare `RangeError`. */
|
|
104
|
+
function isValidDate(value: unknown): value is Date {
|
|
105
|
+
return value instanceof Date && !Number.isNaN(value.getTime());
|
|
106
|
+
}
|
|
107
|
+
|
|
103
108
|
/** Both terms positive BIGINTS — a provider's `{ numerator: 23 }` mixed a number into bigint maths. */
|
|
104
109
|
function isPositiveFraction(ratio: Fraction): boolean {
|
|
105
110
|
const { numerator, denominator } = ratio as { numerator: unknown; denominator: unknown };
|
|
@@ -130,8 +135,10 @@ export async function convertWith(
|
|
|
130
135
|
// The instant the parity was asserted, never `new Date(0)`: `ExchangeRate.at` is the audit
|
|
131
136
|
// trail, and a ledger row claiming its rate was observed on 1970-01-01 is a claim nobody
|
|
132
137
|
// made. The clock is injected for the same reason the rest of the framework injects one.
|
|
133
|
-
const at =
|
|
134
|
-
|
|
138
|
+
const at = options.at ?? (options.clock ?? systemClock).now();
|
|
139
|
+
// Screened exactly as `convert` screens `rate.at`: the same mistake, the same code.
|
|
140
|
+
if (!isValidDate(at)) throw rateUnusable(amount.currency, target, 'at');
|
|
141
|
+
return { amount, source: amount, rate: 1, at: at.toISOString(), provider: 'identity' };
|
|
135
142
|
}
|
|
136
143
|
const rate = await provider.rateFor(amount.currency, target, options.at);
|
|
137
144
|
if (rate === undefined) throw rateMissing(amount.currency, target);
|