@ducatjs/money 0.1.0 → 0.2.1
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/NOTICE +73 -0
- package/README.md +479 -62
- package/data/cash-rounding.json +123 -2
- package/data/cldr-cash.json +101 -0
- package/data/historic.json +78 -0
- package/data/iso4217-list-three.xml +1185 -0
- package/dist/adyen-fx.d.ts.map +1 -1
- package/dist/adyen-fx.js +22 -4
- package/dist/adyen-fx.js.map +1 -1
- package/dist/boc.d.ts +31 -0
- package/dist/boc.d.ts.map +1 -0
- package/dist/boc.js +114 -0
- package/dist/boc.js.map +1 -0
- package/dist/boe.d.ts +33 -0
- package/dist/boe.d.ts.map +1 -0
- package/dist/boe.js +114 -0
- package/dist/boe.js.map +1 -0
- package/dist/cash.d.ts +30 -1
- package/dist/cash.d.ts.map +1 -1
- package/dist/cash.js +50 -2
- package/dist/cash.js.map +1 -1
- package/dist/convert.d.ts +10 -9
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +13 -3
- package/dist/convert.js.map +1 -1
- package/dist/drizzle/mysql.d.ts +105 -0
- package/dist/drizzle/mysql.d.ts.map +1 -0
- package/dist/drizzle/mysql.js +60 -0
- package/dist/drizzle/mysql.js.map +1 -0
- package/dist/drizzle/pg.d.ts +103 -0
- package/dist/drizzle/pg.d.ts.map +1 -0
- package/dist/drizzle/pg.js +60 -0
- package/dist/drizzle/pg.js.map +1 -0
- package/dist/drizzle/sqlite.d.ts +102 -0
- package/dist/drizzle/sqlite.d.ts.map +1 -0
- package/dist/drizzle/sqlite.js +59 -0
- package/dist/drizzle/sqlite.js.map +1 -0
- package/dist/ecb.d.ts +37 -2
- package/dist/ecb.d.ts.map +1 -1
- package/dist/ecb.js +148 -10
- package/dist/ecb.js.map +1 -1
- package/dist/fed.d.ts +35 -0
- package/dist/fed.d.ts.map +1 -0
- package/dist/fed.js +134 -0
- package/dist/fed.js.map +1 -0
- package/dist/fetch.d.ts +45 -0
- package/dist/fetch.d.ts.map +1 -1
- package/dist/fetch.js +167 -24
- package/dist/fetch.js.map +1 -1
- package/dist/fn.d.ts +8 -1
- package/dist/fn.d.ts.map +1 -1
- package/dist/fn.js +8 -1
- package/dist/fn.js.map +1 -1
- package/dist/generated/cash.d.ts +2 -0
- package/dist/generated/cash.d.ts.map +1 -1
- package/dist/generated/cash.js +101 -0
- package/dist/generated/cash.js.map +1 -1
- package/dist/generated/historic.d.ts +337 -0
- package/dist/generated/historic.d.ts.map +1 -0
- package/dist/generated/historic.js +66 -0
- package/dist/generated/historic.js.map +1 -0
- package/dist/historic.d.ts +40 -0
- package/dist/historic.d.ts.map +1 -0
- package/dist/historic.js +43 -0
- package/dist/historic.js.map +1 -0
- package/dist/history.d.ts +96 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +213 -0
- package/dist/history.js.map +1 -0
- package/dist/hmrc.d.ts +28 -0
- package/dist/hmrc.d.ts.map +1 -0
- package/dist/hmrc.js +108 -0
- package/dist/hmrc.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kysely.d.ts +120 -0
- package/dist/kysely.d.ts.map +1 -0
- package/dist/kysely.js +309 -0
- package/dist/kysely.js.map +1 -0
- package/dist/money.d.ts +93 -9
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +135 -9
- package/dist/money.js.map +1 -1
- package/dist/parse.d.ts +45 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +290 -3
- package/dist/parse.js.map +1 -1
- package/dist/pg.d.ts +100 -0
- package/dist/pg.d.ts.map +1 -0
- package/dist/pg.js +343 -0
- package/dist/pg.js.map +1 -0
- package/dist/plugins/adyen.d.ts +1 -1
- package/dist/plugins/adyen.d.ts.map +1 -1
- package/dist/plugins/adyen.js.map +1 -1
- package/dist/plugins/all.d.ts +8 -1
- package/dist/plugins/all.d.ts.map +1 -1
- package/dist/plugins/all.js +8 -1
- package/dist/plugins/all.js.map +1 -1
- package/dist/plugins/allocate.d.ts +1 -1
- package/dist/plugins/allocate.d.ts.map +1 -1
- package/dist/plugins/allocate.js.map +1 -1
- package/dist/plugins/braintree.d.ts +1 -1
- package/dist/plugins/braintree.d.ts.map +1 -1
- package/dist/plugins/braintree.js.map +1 -1
- package/dist/plugins/cash.d.ts +1 -1
- package/dist/plugins/cash.d.ts.map +1 -1
- package/dist/plugins/cash.js.map +1 -1
- package/dist/plugins/checkout.d.ts +1 -1
- package/dist/plugins/checkout.d.ts.map +1 -1
- package/dist/plugins/checkout.js.map +1 -1
- package/dist/plugins/convert.d.ts +5 -5
- package/dist/plugins/convert.d.ts.map +1 -1
- package/dist/plugins/convert.js.map +1 -1
- package/dist/plugins/exact.d.ts +1 -1
- package/dist/plugins/exact.d.ts.map +1 -1
- package/dist/plugins/exact.js.map +1 -1
- package/dist/plugins/fixed.d.ts +1 -1
- package/dist/plugins/fixed.d.ts.map +1 -1
- package/dist/plugins/fixed.js.map +1 -1
- package/dist/plugins/format.d.ts +1 -1
- package/dist/plugins/format.d.ts.map +1 -1
- package/dist/plugins/format.js.map +1 -1
- package/dist/plugins/klarna.d.ts +1 -1
- package/dist/plugins/klarna.d.ts.map +1 -1
- package/dist/plugins/klarna.js.map +1 -1
- package/dist/plugins/paypal.d.ts +1 -1
- package/dist/plugins/paypal.d.ts.map +1 -1
- package/dist/plugins/paypal.js +0 -4
- package/dist/plugins/paypal.js.map +1 -1
- package/dist/plugins/prisma.d.ts +1 -1
- package/dist/plugins/prisma.d.ts.map +1 -1
- package/dist/plugins/prisma.js +0 -4
- package/dist/plugins/prisma.js.map +1 -1
- package/dist/plugins/stripe.d.ts +1 -1
- package/dist/plugins/stripe.d.ts.map +1 -1
- package/dist/plugins/stripe.js +0 -4
- package/dist/plugins/stripe.js.map +1 -1
- package/dist/plugins/tax.d.ts +6 -6
- package/dist/plugins/tax.d.ts.map +1 -1
- package/dist/plugins/tax.js.map +1 -1
- package/dist/policy.d.ts +34 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +90 -0
- package/dist/policy.js.map +1 -0
- package/dist/prisma.d.ts +25 -14
- package/dist/prisma.d.ts.map +1 -1
- package/dist/prisma.js +29 -19
- package/dist/prisma.js.map +1 -1
- package/dist/provider.d.ts +21 -7
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +51 -11
- package/dist/provider.js.map +1 -1
- package/dist/rate-text.d.ts +38 -0
- package/dist/rate-text.d.ts.map +1 -0
- package/dist/rate-text.js +143 -0
- package/dist/rate-text.js.map +1 -0
- package/dist/rate.d.ts +61 -5
- package/dist/rate.d.ts.map +1 -1
- package/dist/rate.js +133 -33
- package/dist/rate.js.map +1 -1
- package/dist/rounding.js +1 -1
- package/dist/rounding.js.map +1 -1
- package/dist/schema.d.ts +43 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +77 -0
- package/dist/schema.js.map +1 -0
- package/dist/sql.d.ts +54 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +131 -0
- package/dist/sql.js.map +1 -0
- package/dist/tax.d.ts +13 -9
- package/dist/tax.d.ts.map +1 -1
- package/dist/tax.js +20 -4
- package/dist/tax.js.map +1 -1
- package/dist/testing/arbitraries.d.ts +43 -0
- package/dist/testing/arbitraries.d.ts.map +1 -0
- package/dist/testing/arbitraries.js +98 -0
- package/dist/testing/arbitraries.js.map +1 -0
- package/dist/testing/index.d.ts +67 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +159 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/jest.d.ts +2 -0
- package/dist/testing/jest.d.ts.map +1 -0
- package/dist/testing/jest.js +15 -0
- package/dist/testing/jest.js.map +1 -0
- package/dist/testing/vitest.d.ts +7 -0
- package/dist/testing/vitest.d.ts.map +1 -0
- package/dist/testing/vitest.js +12 -0
- package/dist/testing/vitest.js.map +1 -0
- package/dist/valibot.d.ts +33 -0
- package/dist/valibot.d.ts.map +1 -0
- package/dist/valibot.js +61 -0
- package/dist/valibot.js.map +1 -0
- package/dist/zod.d.ts +36 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +58 -0
- package/dist/zod.js.map +1 -0
- package/package.json +116 -5
- package/src/adyen-fx.ts +25 -4
- package/src/boc.ts +136 -0
- package/src/boe.ts +131 -0
- package/src/cash.ts +70 -2
- package/src/convert.ts +33 -15
- package/src/drizzle/mysql.ts +78 -0
- package/src/drizzle/pg.ts +78 -0
- package/src/drizzle/sqlite.ts +70 -0
- package/src/ecb.ts +179 -13
- package/src/fed.ts +146 -0
- package/src/fetch.ts +207 -28
- package/src/fn.ts +14 -0
- package/src/generated/cash.ts +103 -0
- package/src/generated/historic.ts +67 -0
- package/src/historic.ts +77 -0
- package/src/history.ts +333 -0
- package/src/hmrc.ts +125 -0
- package/src/index.ts +4 -0
- package/src/kysely.ts +588 -0
- package/src/money.ts +210 -12
- package/src/parse.ts +371 -4
- package/src/pg.ts +410 -0
- package/src/plugins/adyen.ts +3 -2
- package/src/plugins/all.ts +10 -0
- package/src/plugins/allocate.ts +3 -2
- package/src/plugins/braintree.ts +3 -2
- package/src/plugins/cash.ts +3 -2
- package/src/plugins/checkout.ts +3 -2
- package/src/plugins/convert.ts +6 -6
- package/src/plugins/exact.ts +3 -2
- package/src/plugins/fixed.ts +3 -2
- package/src/plugins/format.ts +3 -2
- package/src/plugins/klarna.ts +3 -2
- package/src/plugins/paypal.ts +3 -2
- package/src/plugins/prisma.ts +3 -2
- package/src/plugins/stripe.ts +3 -2
- package/src/plugins/tax.ts +11 -11
- package/src/policy.ts +124 -0
- package/src/prisma.ts +91 -10
- package/src/provider.ts +81 -16
- package/src/rate-text.ts +151 -0
- package/src/rate.ts +205 -36
- package/src/rounding.ts +1 -1
- package/src/schema.ts +119 -0
- package/src/sql.ts +178 -0
- package/src/tax.ts +40 -9
- package/src/testing/arbitraries.ts +134 -0
- package/src/testing/index.ts +247 -0
- package/src/testing/jest.ts +18 -0
- package/src/testing/vitest.ts +18 -0
- package/src/valibot.ts +87 -0
- package/src/zod.ts +78 -0
package/dist/provider.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CurrencyMismatchError } from './money.js';
|
|
2
|
-
import { exchangeRate, isRate, toIsoString } from './rate.js';
|
|
2
|
+
import { exchangeRate, hasEnded, hasStarted, isRate, toIsoString, } from './rate.js';
|
|
3
3
|
const DAY_MS = 86_400_000;
|
|
4
4
|
/** Thrown when no provider has a rate for the pair. */
|
|
5
5
|
export class RateUnavailableError extends Error {
|
|
@@ -58,9 +58,11 @@ export function identity() {
|
|
|
58
58
|
* A fixed table of rates: one base currency against many (ECB style), or a list of Rates. Only the
|
|
59
59
|
* pairs given are answered; wrap it in `reversed()` or `via()` for the others.
|
|
60
60
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
61
|
+
* A query with an `asOf` gets nothing from a rate that doesn't apply then: one dated after it, one
|
|
62
|
+
* published (`availableAt`) after it, or one whose `validUntil` has passed. Days are UTC days, and
|
|
63
|
+
* a date query covers the whole day: without an `availableAt`, a query at any time on the rate's
|
|
64
|
+
* own day gets the rate, even before the source published it (the ECB publishes at about 15:00
|
|
65
|
+
* UTC). Give `availableAt` to rule that out.
|
|
64
66
|
*
|
|
65
67
|
* const ecb = rateTable({ base: 'EUR', source: 'ECB', asOf: '2026-11-06', rates: { USD: '1.1165' } });
|
|
66
68
|
*/
|
|
@@ -71,11 +73,36 @@ export function rateTable(spec) {
|
|
|
71
73
|
rates = [...spec];
|
|
72
74
|
}
|
|
73
75
|
else {
|
|
74
|
-
rates =
|
|
76
|
+
rates = [];
|
|
77
|
+
const missing = [];
|
|
78
|
+
for (const [currency, entry] of Object.entries(spec.rates)) {
|
|
79
|
+
if (entry === null) {
|
|
80
|
+
missing.push(currency);
|
|
81
|
+
}
|
|
82
|
+
else if (isRate(entry)) {
|
|
83
|
+
// A ready-made Rate is looked up under its own pair, so it must be the one its key says.
|
|
84
|
+
if (entry.from !== spec.base || entry.to !== currency) {
|
|
85
|
+
throw new CurrencyMismatchError(`${spec.base}→${currency}`, `${entry.from}→${entry.to}`);
|
|
86
|
+
}
|
|
87
|
+
rates.push(entry);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
rates.push(exchangeRate(spec.base, currency, entry, spec));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
75
93
|
header.base = spec.base;
|
|
76
94
|
if (spec.asOf !== undefined) {
|
|
77
95
|
header.asOf = toIsoString(spec.asOf);
|
|
78
96
|
}
|
|
97
|
+
if (spec.availableAt !== undefined) {
|
|
98
|
+
header.availableAt = toIsoString(spec.availableAt);
|
|
99
|
+
}
|
|
100
|
+
if (spec.validUntil !== undefined) {
|
|
101
|
+
header.validUntil = toIsoString(spec.validUntil);
|
|
102
|
+
}
|
|
103
|
+
if (missing.length > 0) {
|
|
104
|
+
header.missing = missing;
|
|
105
|
+
}
|
|
79
106
|
}
|
|
80
107
|
const byPair = new Map();
|
|
81
108
|
for (const rate of rates) {
|
|
@@ -89,10 +116,9 @@ export function rateTable(spec) {
|
|
|
89
116
|
if (rate === undefined) {
|
|
90
117
|
return undefined;
|
|
91
118
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (askedBeforeRateExisted) {
|
|
119
|
+
// The table's own dates count too: a ready-made Rate entry doesn't carry them.
|
|
120
|
+
const asOf = query?.asOf;
|
|
121
|
+
if (asOf !== undefined && (!appliesAt(rate, asOf) || !appliesAt(header, asOf))) {
|
|
96
122
|
return undefined;
|
|
97
123
|
}
|
|
98
124
|
// The key matched, so the rate's currencies are exactly `from` and `to`.
|
|
@@ -100,6 +126,16 @@ export function rateTable(spec) {
|
|
|
100
126
|
},
|
|
101
127
|
};
|
|
102
128
|
}
|
|
129
|
+
/** Whether a rate (or a table) applies at `at`: dated, published and still valid then. */
|
|
130
|
+
function appliesAt(rate, at) {
|
|
131
|
+
if (rate.asOf !== undefined && dayOf(at) < dayOf(rate.asOf)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (rate.availableAt !== undefined && !hasStarted(rate.availableAt, at)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return rate.validUntil === undefined || !hasEnded(rate.validUntil, at);
|
|
138
|
+
}
|
|
103
139
|
function isRateList(spec) {
|
|
104
140
|
return Array.isArray(spec) && spec.every(isRate);
|
|
105
141
|
}
|
|
@@ -158,7 +194,9 @@ export function via(base, provider) {
|
|
|
158
194
|
* undefined when there is none. Days are UTC days. Loaded tables are cached by day. Misses and
|
|
159
195
|
* failures are not cached, so a table that isn't published yet is tried again next time. A loader
|
|
160
196
|
* that throws fails the lookup rather than falling back to an older day, so an outage doesn't
|
|
161
|
-
* silently become a stale rate. The rates carry the day they're from.
|
|
197
|
+
* silently become a stale rate. The rates carry the day they're from. A table with an
|
|
198
|
+
* `availableAt` after an instant asked for is passed over, so a lookup at 09:00 on a publication
|
|
199
|
+
* day gets the day before.
|
|
162
200
|
*
|
|
163
201
|
* const history = snapshots(async (day) => parseEcbXml(await readFile(`ecb/${day}.xml`, 'utf8'))[0]);
|
|
164
202
|
* const fx = await history.at('2026-11-08'); // a Sunday: Friday 2026-11-06's table
|
|
@@ -214,7 +252,9 @@ export function snapshots(load, options) {
|
|
|
214
252
|
// Sequential on purpose: stop at the first day that has a table, without loading older
|
|
215
253
|
// days. oxlint-disable-next-line no-await-in-loop
|
|
216
254
|
const table = await loadDay(day);
|
|
217
|
-
|
|
255
|
+
// A table not yet published at the instant asked for is passed over like a missing one.
|
|
256
|
+
const availableAt = table?.availableAt;
|
|
257
|
+
if (table !== undefined && (availableAt === undefined || hasStarted(availableAt, asOf))) {
|
|
218
258
|
return table;
|
|
219
259
|
}
|
|
220
260
|
}
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
* A published rate cell: the decimal text, or null when the source marks the value as missing
|
|
4
|
+
* (holidays, `ND`, `N/A`). Anything else throws SyntaxError: a cell that can't be read must not
|
|
5
|
+
* look like "not quoted".
|
|
6
|
+
*/
|
|
7
|
+
export declare function readRateCell(cell: string, where: string): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* @internal
|
|
10
|
+
* The published digits of a rate from a feed that strips trailing zeros, given the number of
|
|
11
|
+
* decimals the publisher states: '1.175' with 4 decimals is '1.1750'. Text with more decimals than
|
|
12
|
+
* stated is kept as it is, since dropping digits would change the rate.
|
|
13
|
+
*/
|
|
14
|
+
export declare function withDecimals(text: string, decimals: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
* The records of a CSV file, RFC 4180 style: a cell may be quoted ("a, b", with "" for a quote),
|
|
18
|
+
* and a quote anywhere else, or one left open, is a SyntaxError, so a stray quote can't swallow
|
|
19
|
+
* the lines after it. Blank lines are skipped.
|
|
20
|
+
*/
|
|
21
|
+
export declare function csvRows(text: string): string[][];
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
* Whether `text` is a real calendar day in ISO form. '2026-02-30' is not, although Date.parse rolls
|
|
25
|
+
* it over to 2 March.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isCalendarDay(text: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* @internal
|
|
30
|
+
* Records a currency's rate (or null, missing) for a day. The same currency twice on one day is
|
|
31
|
+
* either a repeat, which is fine, or a contradiction, which throws: a parser never picks one.
|
|
32
|
+
*/
|
|
33
|
+
export declare function addDayRate(days: Map<string, Record<string, string | null>>, day: string, currency: string, rate: string | null): void;
|
|
34
|
+
/** @internal Dated tables, newest first (ISO dates sort as strings). */
|
|
35
|
+
export declare function newestFirst<T extends {
|
|
36
|
+
readonly asOf?: string;
|
|
37
|
+
}>(tables: T[]): T[];
|
|
38
|
+
//# sourceMappingURL=rate-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-text.d.ts","sourceRoot":"","sources":["../src/rate-text.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYnE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAuDhD;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,EAChD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,IAAI,CAWN;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAElF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Reading rate cells from published files, shared by the source parsers so that every source
|
|
2
|
+
// handles missing values and stripped digits the same way.
|
|
3
|
+
// What sources write for "no value this day": blank (ECB CSV, BoE), ND (Fed H.10), N/A (ECB CSV),
|
|
4
|
+
// NA (IMF), and dashes and NaN in other files. Compared upper-cased.
|
|
5
|
+
const MISSING_MARKERS = new Set(['', 'ND', 'N/A', 'NA', 'N.A.', '-', '–', '—', 'NAN', 'NULL']);
|
|
6
|
+
const PLAIN_DECIMAL = /^\d+(?:\.\d+)?$/;
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
* A published rate cell: the decimal text, or null when the source marks the value as missing
|
|
10
|
+
* (holidays, `ND`, `N/A`). Anything else throws SyntaxError: a cell that can't be read must not
|
|
11
|
+
* look like "not quoted".
|
|
12
|
+
*/
|
|
13
|
+
export function readRateCell(cell, where) {
|
|
14
|
+
const text = cell.trim();
|
|
15
|
+
if (MISSING_MARKERS.has(text.toUpperCase())) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (!PLAIN_DECIMAL.test(text)) {
|
|
19
|
+
throw new SyntaxError(`Not a rate: ${JSON.stringify(cell)} (${where})`);
|
|
20
|
+
}
|
|
21
|
+
return text;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
* The published digits of a rate from a feed that strips trailing zeros, given the number of
|
|
26
|
+
* decimals the publisher states: '1.175' with 4 decimals is '1.1750'. Text with more decimals than
|
|
27
|
+
* stated is kept as it is, since dropping digits would change the rate.
|
|
28
|
+
*/
|
|
29
|
+
export function withDecimals(text, decimals) {
|
|
30
|
+
if (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > 30) {
|
|
31
|
+
throw new RangeError(`decimals must be an integer from 0 to 30, got ${decimals}`);
|
|
32
|
+
}
|
|
33
|
+
const point = text.indexOf('.');
|
|
34
|
+
const present = point === -1 ? 0 : text.length - point - 1;
|
|
35
|
+
if (present >= decimals) {
|
|
36
|
+
return text;
|
|
37
|
+
}
|
|
38
|
+
const integerPart = point === -1 ? text : text.slice(0, point);
|
|
39
|
+
const fraction = point === -1 ? '' : text.slice(point + 1);
|
|
40
|
+
return `${integerPart}.${fraction.padEnd(decimals, '0')}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @internal
|
|
44
|
+
* The records of a CSV file, RFC 4180 style: a cell may be quoted ("a, b", with "" for a quote),
|
|
45
|
+
* and a quote anywhere else, or one left open, is a SyntaxError, so a stray quote can't swallow
|
|
46
|
+
* the lines after it. Blank lines are skipped.
|
|
47
|
+
*/
|
|
48
|
+
export function csvRows(text) {
|
|
49
|
+
const rows = [];
|
|
50
|
+
let row = [];
|
|
51
|
+
let cell = '';
|
|
52
|
+
// 'start' of a cell, inside an unquoted one, inside quotes, or just after the closing quote
|
|
53
|
+
let state = 'start';
|
|
54
|
+
const endRow = () => {
|
|
55
|
+
row.push(cell);
|
|
56
|
+
if (row.length > 1 || row[0].trim() !== '') {
|
|
57
|
+
rows.push(row);
|
|
58
|
+
}
|
|
59
|
+
row = [];
|
|
60
|
+
cell = '';
|
|
61
|
+
state = 'start';
|
|
62
|
+
};
|
|
63
|
+
for (let i = 0; i < text.length; i++) {
|
|
64
|
+
const char = text[i];
|
|
65
|
+
if (state === 'quoted') {
|
|
66
|
+
if (char !== '"') {
|
|
67
|
+
cell += char;
|
|
68
|
+
}
|
|
69
|
+
else if (text[i + 1] === '"') {
|
|
70
|
+
cell += '"';
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
state = 'closed';
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (char === ',') {
|
|
79
|
+
row.push(cell);
|
|
80
|
+
cell = '';
|
|
81
|
+
state = 'start';
|
|
82
|
+
}
|
|
83
|
+
else if (char === '\n') {
|
|
84
|
+
endRow();
|
|
85
|
+
}
|
|
86
|
+
else if (char === '\r' && text[i + 1] === '\n') {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
else if (char === '"' && state === 'start') {
|
|
90
|
+
state = 'quoted';
|
|
91
|
+
}
|
|
92
|
+
else if (char === '"' || state === 'closed') {
|
|
93
|
+
throw new SyntaxError(`Malformed CSV: unexpected ${JSON.stringify(char)} on line ${rows.length + 1}`);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
cell += char;
|
|
97
|
+
state = 'plain';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (state === 'quoted') {
|
|
101
|
+
throw new SyntaxError('Malformed CSV: a quoted cell is never closed');
|
|
102
|
+
}
|
|
103
|
+
if (cell !== '' || row.length > 0) {
|
|
104
|
+
endRow();
|
|
105
|
+
}
|
|
106
|
+
return rows;
|
|
107
|
+
}
|
|
108
|
+
const ISO_DAY = /^(\d{4})-(\d\d)-(\d\d)$/;
|
|
109
|
+
/**
|
|
110
|
+
* @internal
|
|
111
|
+
* Whether `text` is a real calendar day in ISO form. '2026-02-30' is not, although Date.parse rolls
|
|
112
|
+
* it over to 2 March.
|
|
113
|
+
*/
|
|
114
|
+
export function isCalendarDay(text) {
|
|
115
|
+
const match = ISO_DAY.exec(text);
|
|
116
|
+
if (match === null) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const date = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])));
|
|
120
|
+
return date.toISOString().slice(0, 10) === text;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @internal
|
|
124
|
+
* Records a currency's rate (or null, missing) for a day. The same currency twice on one day is
|
|
125
|
+
* either a repeat, which is fine, or a contradiction, which throws: a parser never picks one.
|
|
126
|
+
*/
|
|
127
|
+
export function addDayRate(days, day, currency, rate) {
|
|
128
|
+
let rates = days.get(day);
|
|
129
|
+
if (rates === undefined) {
|
|
130
|
+
rates = {};
|
|
131
|
+
days.set(day, rates);
|
|
132
|
+
}
|
|
133
|
+
const earlier = rates[currency];
|
|
134
|
+
if (earlier !== undefined && earlier !== rate) {
|
|
135
|
+
throw new SyntaxError(`Two different values for ${currency} on ${day}: ${earlier} and ${rate}`);
|
|
136
|
+
}
|
|
137
|
+
rates[currency] = rate;
|
|
138
|
+
}
|
|
139
|
+
/** @internal Dated tables, newest first (ISO dates sort as strings). */
|
|
140
|
+
export function newestFirst(tables) {
|
|
141
|
+
return tables.sort((table, other) => other.asOf.localeCompare(table.asOf));
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=rate-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-text.js","sourceRoot":"","sources":["../src/rate-text.ts"],"names":[],"mappings":"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"}
|
package/dist/rate.d.ts
CHANGED
|
@@ -1,16 +1,41 @@
|
|
|
1
1
|
import { type Factor, type Ratio } from './decimal.js';
|
|
2
|
-
import { type CurrencyInput, type Money } from './money.js';
|
|
2
|
+
import { type CurrencyInput, type Money, type RoundingInput, type RoundingPolicy } from './money.js';
|
|
3
3
|
import { type RoundingMode } from './rounding.js';
|
|
4
4
|
/** How a rate was quoted. `inverse()` swaps 'bid' and 'ask'. */
|
|
5
5
|
export type RateType = 'mid' | 'bid' | 'ask' | (string & {});
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* How a source published a rate, kept with the Rate for audit and display. The published direction
|
|
8
|
+
* is `from` → `to`, or `to` → `from` when `inverted`.
|
|
9
|
+
*/
|
|
10
|
+
export interface RateQuote {
|
|
11
|
+
/** The number exactly as published, trailing zeros included ('136.80'). */
|
|
12
|
+
readonly rate: string;
|
|
13
|
+
/**
|
|
14
|
+
* How many units of the published direction's first currency the number is for: 100 for "NOK
|
|
15
|
+
* per 100 JPY". Omitted for 1.
|
|
16
|
+
*/
|
|
17
|
+
readonly per?: number;
|
|
18
|
+
/** The source quoted `to` → `from`; this Rate is its exact inverse. */
|
|
19
|
+
readonly inverted?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Where a rate came from. `asOf`, `availableAt` and `validUntil` are ISO-8601 dates ('2026-11-06')
|
|
23
|
+
* or instants.
|
|
8
24
|
*/
|
|
9
25
|
export interface RateInfo {
|
|
10
26
|
readonly source?: string;
|
|
27
|
+
/** The date or time the rate applies to. */
|
|
11
28
|
readonly asOf?: string | Date;
|
|
29
|
+
/**
|
|
30
|
+
* When the rate was published. A lookup for an earlier time doesn't get it, so a historical
|
|
31
|
+
* lookup sees only what was known then. A date means from the start of that UTC day.
|
|
32
|
+
*/
|
|
33
|
+
readonly availableAt?: string | Date;
|
|
34
|
+
/** The last date or time the rate applies to. A date is valid all day (UTC). */
|
|
12
35
|
readonly validUntil?: string | Date;
|
|
13
36
|
readonly type?: RateType;
|
|
37
|
+
/** The rate as the source published it. */
|
|
38
|
+
readonly quote?: RateQuote;
|
|
14
39
|
}
|
|
15
40
|
/** Options for converting an amount. */
|
|
16
41
|
export interface ConvertOptions {
|
|
@@ -34,8 +59,11 @@ export interface RateJSON {
|
|
|
34
59
|
rate: string;
|
|
35
60
|
source?: string;
|
|
36
61
|
asOf?: string;
|
|
62
|
+
availableAt?: string;
|
|
37
63
|
validUntil?: string;
|
|
38
64
|
type?: string;
|
|
65
|
+
/** Present only when it says more than `rate` does: a `per` or an inverted quote. */
|
|
66
|
+
quote?: RateQuote;
|
|
39
67
|
derivedFrom?: RateJSON[];
|
|
40
68
|
}
|
|
41
69
|
/**
|
|
@@ -44,6 +72,14 @@ export interface RateJSON {
|
|
|
44
72
|
* that times with different offsets compare correctly as strings.
|
|
45
73
|
*/
|
|
46
74
|
export declare function toIsoString(time: string | Date): string;
|
|
75
|
+
/**
|
|
76
|
+
* @internal
|
|
77
|
+
* Whether `time` has come by `at`. A date `at` means the whole of that UTC day, so anything on or
|
|
78
|
+
* before that day counts; a date `time` means the start of its day.
|
|
79
|
+
*/
|
|
80
|
+
export declare function hasStarted(time: string, at: string | Date): boolean;
|
|
81
|
+
/** @internal Whether `validUntil` (a date: valid all day, UTC) has passed at `at`. */
|
|
82
|
+
export declare function hasEnded(validUntil: string, at: string | Date): boolean;
|
|
47
83
|
/**
|
|
48
84
|
* minor × rate × 10^scaleShift, rounded once with `rounding`. This is the kernel of every
|
|
49
85
|
* conversion: `scaleShift` is the result scale minus the input scale. Pure, and `rate.den > 0` by
|
|
@@ -62,8 +98,10 @@ export declare class Rate<From extends string = string, To extends string = stri
|
|
|
62
98
|
readonly ratio: Ratio;
|
|
63
99
|
readonly source?: string;
|
|
64
100
|
readonly asOf?: string;
|
|
101
|
+
readonly availableAt?: string;
|
|
65
102
|
readonly validUntil?: string;
|
|
66
103
|
readonly type?: RateType;
|
|
104
|
+
readonly quote?: RateQuote;
|
|
67
105
|
readonly derivedFrom?: readonly Rate[];
|
|
68
106
|
/** @internal use exchangeRate() */
|
|
69
107
|
constructor(from: From, to: To, rate: Ratio, info?: RateInfo, derivedFrom?: readonly Rate[]);
|
|
@@ -83,7 +121,10 @@ export declare class Rate<From extends string = string, To extends string = stri
|
|
|
83
121
|
round(places: number, rounding?: RoundingMode): Rate<From, To>;
|
|
84
122
|
/** The rate with exactly `places` decimals, for display. The Rate itself keeps every digit. */
|
|
85
123
|
toDecimal(places: number, rounding?: RoundingMode): string;
|
|
86
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* The exact rate: '1.1165', or '2000/2233' when its decimal expansion doesn't terminate. A rate
|
|
126
|
+
* published one unit for one unit keeps the published digits ('136.80').
|
|
127
|
+
*/
|
|
87
128
|
toString(): string;
|
|
88
129
|
/** The rate, its metadata and its audit chain as JSON. `rateFromJSON` reverses it. */
|
|
89
130
|
toJSON(): RateJSON;
|
|
@@ -92,9 +133,24 @@ export declare class Rate<From extends string = string, To extends string = stri
|
|
|
92
133
|
* (UTC).
|
|
93
134
|
*/
|
|
94
135
|
isExpired(now?: string | Date): boolean;
|
|
95
|
-
/**
|
|
96
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Whether the rate had been published by `at`: always, without an `availableAt`. A date `at`
|
|
138
|
+
* means by the end of that UTC day.
|
|
139
|
+
*/
|
|
140
|
+
isAvailable(at: string | Date): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Converts `money`, rounding once: with a mode, to the target currency's exponent (or
|
|
143
|
+
* `options.scale`); with a rounding policy, to the policy's scale and increment.
|
|
144
|
+
*/
|
|
145
|
+
convert(money: Money<From>, rounding?: RoundingInput, options?: ConvertOptions): Money<To>;
|
|
97
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* @internal
|
|
149
|
+
* money × rate in `to`, rounded once by a policy. The amount is relabelled `to` at its own scale,
|
|
150
|
+
* so the policy rounds the product exactly as it would a multiplication in `to`: to its scale
|
|
151
|
+
* (default `to`'s exponent) and increment, checking its currency against `to`.
|
|
152
|
+
*/
|
|
153
|
+
export declare function convertWithPolicy<To extends string>(money: Money, to: To, rate: Ratio, policy: RoundingPolicy, options?: ConvertOptions): Money<To>;
|
|
98
154
|
/**
|
|
99
155
|
* An exact rate pinned to a currency pair, so converting the wrong currency is a type error. Give
|
|
100
156
|
* the rate as a decimal string ('1.1165', every digit kept), a "num/den" string, a bigint or a
|
package/dist/rate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate.d.ts","sourceRoot":"","sources":["../src/rate.ts"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,MAAM,EACX,KAAK,KAAK,EACX,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"rate.d.ts","sourceRoot":"","sources":["../src/rate.ts"],"names":[],"mappings":"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"}
|