@ducatjs/money 0.1.0 → 0.2.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.
Files changed (201) hide show
  1. package/README.md +479 -62
  2. package/data/cash-rounding.json +123 -2
  3. package/data/cldr-cash.json +101 -0
  4. package/data/historic.json +78 -0
  5. package/data/iso4217-list-three.xml +1185 -0
  6. package/dist/adyen-fx.d.ts.map +1 -1
  7. package/dist/adyen-fx.js +22 -4
  8. package/dist/adyen-fx.js.map +1 -1
  9. package/dist/boc.d.ts +31 -0
  10. package/dist/boc.d.ts.map +1 -0
  11. package/dist/boc.js +114 -0
  12. package/dist/boc.js.map +1 -0
  13. package/dist/boe.d.ts +33 -0
  14. package/dist/boe.d.ts.map +1 -0
  15. package/dist/boe.js +114 -0
  16. package/dist/boe.js.map +1 -0
  17. package/dist/cash.d.ts +30 -1
  18. package/dist/cash.d.ts.map +1 -1
  19. package/dist/cash.js +50 -2
  20. package/dist/cash.js.map +1 -1
  21. package/dist/convert.d.ts +10 -9
  22. package/dist/convert.d.ts.map +1 -1
  23. package/dist/convert.js +13 -3
  24. package/dist/convert.js.map +1 -1
  25. package/dist/drizzle/mysql.d.ts +105 -0
  26. package/dist/drizzle/mysql.d.ts.map +1 -0
  27. package/dist/drizzle/mysql.js +60 -0
  28. package/dist/drizzle/mysql.js.map +1 -0
  29. package/dist/drizzle/pg.d.ts +103 -0
  30. package/dist/drizzle/pg.d.ts.map +1 -0
  31. package/dist/drizzle/pg.js +60 -0
  32. package/dist/drizzle/pg.js.map +1 -0
  33. package/dist/drizzle/sqlite.d.ts +102 -0
  34. package/dist/drizzle/sqlite.d.ts.map +1 -0
  35. package/dist/drizzle/sqlite.js +59 -0
  36. package/dist/drizzle/sqlite.js.map +1 -0
  37. package/dist/ecb.d.ts +37 -2
  38. package/dist/ecb.d.ts.map +1 -1
  39. package/dist/ecb.js +148 -10
  40. package/dist/ecb.js.map +1 -1
  41. package/dist/fed.d.ts +35 -0
  42. package/dist/fed.d.ts.map +1 -0
  43. package/dist/fed.js +134 -0
  44. package/dist/fed.js.map +1 -0
  45. package/dist/fetch.d.ts +45 -0
  46. package/dist/fetch.d.ts.map +1 -1
  47. package/dist/fetch.js +167 -24
  48. package/dist/fetch.js.map +1 -1
  49. package/dist/fn.d.ts +8 -1
  50. package/dist/fn.d.ts.map +1 -1
  51. package/dist/fn.js +8 -1
  52. package/dist/fn.js.map +1 -1
  53. package/dist/generated/cash.d.ts +2 -0
  54. package/dist/generated/cash.d.ts.map +1 -1
  55. package/dist/generated/cash.js +101 -0
  56. package/dist/generated/cash.js.map +1 -1
  57. package/dist/generated/historic.d.ts +337 -0
  58. package/dist/generated/historic.d.ts.map +1 -0
  59. package/dist/generated/historic.js +66 -0
  60. package/dist/generated/historic.js.map +1 -0
  61. package/dist/historic.d.ts +40 -0
  62. package/dist/historic.d.ts.map +1 -0
  63. package/dist/historic.js +43 -0
  64. package/dist/historic.js.map +1 -0
  65. package/dist/history.d.ts +96 -0
  66. package/dist/history.d.ts.map +1 -0
  67. package/dist/history.js +213 -0
  68. package/dist/history.js.map +1 -0
  69. package/dist/hmrc.d.ts +28 -0
  70. package/dist/hmrc.d.ts.map +1 -0
  71. package/dist/hmrc.js +108 -0
  72. package/dist/hmrc.js.map +1 -0
  73. package/dist/index.d.ts +1 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +1 -1
  76. package/dist/index.js.map +1 -1
  77. package/dist/kysely.d.ts +120 -0
  78. package/dist/kysely.d.ts.map +1 -0
  79. package/dist/kysely.js +309 -0
  80. package/dist/kysely.js.map +1 -0
  81. package/dist/money.d.ts +93 -9
  82. package/dist/money.d.ts.map +1 -1
  83. package/dist/money.js +135 -9
  84. package/dist/money.js.map +1 -1
  85. package/dist/parse.d.ts +45 -1
  86. package/dist/parse.d.ts.map +1 -1
  87. package/dist/parse.js +290 -3
  88. package/dist/parse.js.map +1 -1
  89. package/dist/pg.d.ts +100 -0
  90. package/dist/pg.d.ts.map +1 -0
  91. package/dist/pg.js +343 -0
  92. package/dist/pg.js.map +1 -0
  93. package/dist/plugins/all.d.ts +8 -1
  94. package/dist/plugins/all.d.ts.map +1 -1
  95. package/dist/plugins/all.js +8 -1
  96. package/dist/plugins/all.js.map +1 -1
  97. package/dist/plugins/convert.d.ts +3 -4
  98. package/dist/plugins/convert.d.ts.map +1 -1
  99. package/dist/plugins/convert.js.map +1 -1
  100. package/dist/plugins/tax.d.ts +4 -5
  101. package/dist/plugins/tax.d.ts.map +1 -1
  102. package/dist/plugins/tax.js.map +1 -1
  103. package/dist/policy.d.ts +34 -0
  104. package/dist/policy.d.ts.map +1 -0
  105. package/dist/policy.js +90 -0
  106. package/dist/policy.js.map +1 -0
  107. package/dist/prisma.d.ts +25 -14
  108. package/dist/prisma.d.ts.map +1 -1
  109. package/dist/prisma.js +29 -19
  110. package/dist/prisma.js.map +1 -1
  111. package/dist/provider.d.ts +21 -7
  112. package/dist/provider.d.ts.map +1 -1
  113. package/dist/provider.js +51 -11
  114. package/dist/provider.js.map +1 -1
  115. package/dist/rate-text.d.ts +38 -0
  116. package/dist/rate-text.d.ts.map +1 -0
  117. package/dist/rate-text.js +143 -0
  118. package/dist/rate-text.js.map +1 -0
  119. package/dist/rate.d.ts +61 -5
  120. package/dist/rate.d.ts.map +1 -1
  121. package/dist/rate.js +133 -33
  122. package/dist/rate.js.map +1 -1
  123. package/dist/rounding.js +1 -1
  124. package/dist/rounding.js.map +1 -1
  125. package/dist/schema.d.ts +43 -0
  126. package/dist/schema.d.ts.map +1 -0
  127. package/dist/schema.js +77 -0
  128. package/dist/schema.js.map +1 -0
  129. package/dist/sql.d.ts +54 -0
  130. package/dist/sql.d.ts.map +1 -0
  131. package/dist/sql.js +131 -0
  132. package/dist/sql.js.map +1 -0
  133. package/dist/tax.d.ts +13 -9
  134. package/dist/tax.d.ts.map +1 -1
  135. package/dist/tax.js +20 -4
  136. package/dist/tax.js.map +1 -1
  137. package/dist/testing/arbitraries.d.ts +43 -0
  138. package/dist/testing/arbitraries.d.ts.map +1 -0
  139. package/dist/testing/arbitraries.js +98 -0
  140. package/dist/testing/arbitraries.js.map +1 -0
  141. package/dist/testing/index.d.ts +67 -0
  142. package/dist/testing/index.d.ts.map +1 -0
  143. package/dist/testing/index.js +159 -0
  144. package/dist/testing/index.js.map +1 -0
  145. package/dist/testing/jest.d.ts +2 -0
  146. package/dist/testing/jest.d.ts.map +1 -0
  147. package/dist/testing/jest.js +15 -0
  148. package/dist/testing/jest.js.map +1 -0
  149. package/dist/testing/vitest.d.ts +7 -0
  150. package/dist/testing/vitest.d.ts.map +1 -0
  151. package/dist/testing/vitest.js +12 -0
  152. package/dist/testing/vitest.js.map +1 -0
  153. package/dist/valibot.d.ts +33 -0
  154. package/dist/valibot.d.ts.map +1 -0
  155. package/dist/valibot.js +61 -0
  156. package/dist/valibot.js.map +1 -0
  157. package/dist/zod.d.ts +36 -0
  158. package/dist/zod.d.ts.map +1 -0
  159. package/dist/zod.js +58 -0
  160. package/dist/zod.js.map +1 -0
  161. package/package.json +116 -5
  162. package/src/adyen-fx.ts +25 -4
  163. package/src/boc.ts +136 -0
  164. package/src/boe.ts +131 -0
  165. package/src/cash.ts +70 -2
  166. package/src/convert.ts +33 -15
  167. package/src/drizzle/mysql.ts +78 -0
  168. package/src/drizzle/pg.ts +78 -0
  169. package/src/drizzle/sqlite.ts +70 -0
  170. package/src/ecb.ts +179 -13
  171. package/src/fed.ts +146 -0
  172. package/src/fetch.ts +207 -28
  173. package/src/fn.ts +14 -0
  174. package/src/generated/cash.ts +103 -0
  175. package/src/generated/historic.ts +67 -0
  176. package/src/historic.ts +77 -0
  177. package/src/history.ts +333 -0
  178. package/src/hmrc.ts +125 -0
  179. package/src/index.ts +4 -0
  180. package/src/kysely.ts +588 -0
  181. package/src/money.ts +210 -12
  182. package/src/parse.ts +371 -4
  183. package/src/pg.ts +410 -0
  184. package/src/plugins/all.ts +10 -0
  185. package/src/plugins/convert.ts +4 -5
  186. package/src/plugins/tax.ts +9 -10
  187. package/src/policy.ts +124 -0
  188. package/src/prisma.ts +91 -10
  189. package/src/provider.ts +81 -16
  190. package/src/rate-text.ts +151 -0
  191. package/src/rate.ts +205 -36
  192. package/src/rounding.ts +1 -1
  193. package/src/schema.ts +119 -0
  194. package/src/sql.ts +178 -0
  195. package/src/tax.ts +40 -9
  196. package/src/testing/arbitraries.ts +134 -0
  197. package/src/testing/index.ts +247 -0
  198. package/src/testing/jest.ts +18 -0
  199. package/src/testing/vitest.ts +18 -0
  200. package/src/valibot.ts +87 -0
  201. package/src/zod.ts +78 -0
@@ -0,0 +1,213 @@
1
+ import { rateTable, } from './provider.js';
2
+ import { ratio } from './decimal.js';
3
+ import { hasEnded, hasStarted, Rate, toIsoString } from './rate.js';
4
+ import { withDecimals } from './rate-text.js';
5
+ const DAY_MS = 86_400_000;
6
+ const PLAIN_DECIMAL = /^\d+(?:\.\d+)?$/;
7
+ /** The exact rate a quote stands for, in the Rate's own direction. */
8
+ function quoteRatio(quote) {
9
+ if (!PLAIN_DECIMAL.test(quote.rate)) {
10
+ throw new RangeError(`A quote is a plain decimal string, got ${quote.rate}`);
11
+ }
12
+ const per = quote.per ?? 1;
13
+ if (!Number.isSafeInteger(per) || per < 1) {
14
+ throw new RangeError(`A quote's per is a positive integer, got ${per}`);
15
+ }
16
+ const published = ratio(quote.rate);
17
+ if (quote.inverted === true) {
18
+ return ratio(published.den * BigInt(per), published.num);
19
+ }
20
+ return ratio(published.num, published.den * BigInt(per));
21
+ }
22
+ /**
23
+ * A Rate from a published quote: `per` units and the direction are applied exactly, and the quote
24
+ * is kept on the Rate.
25
+ *
26
+ * rateFromQuote('JPY', 'NOK', { rate: '6.50', per: 100 }) // JPY→NOK 0.065
27
+ * rateFromQuote('USD', 'EUR', { rate: '1.1650', inverted: true }) // USD→EUR 200/233
28
+ */
29
+ export function rateFromQuote(from, to, quote, info) {
30
+ const exact = quoteRatio(quote);
31
+ // Stored in one form: per 1 and inverted false are the same as leaving them out, and a quote
32
+ // without them prints its own digits.
33
+ const kept = { rate: quote.rate };
34
+ if (quote.per !== undefined && quote.per !== 1) {
35
+ kept.per = quote.per;
36
+ }
37
+ if (quote.inverted === true) {
38
+ kept.inverted = true;
39
+ }
40
+ return new Rate(from, to, exact, { ...info, quote: kept });
41
+ }
42
+ /**
43
+ * A rateTable from rates as a source published them: each is stored exactly in the table's
44
+ * direction, base → currency, and keeps its quote (`rate.quote`).
45
+ *
46
+ * const boc = quotedTable({ base: 'CAD', inverted: true, asOf: '2026-11-06', rates: { USD: '1.3654' } });
47
+ * boc.rate('CAD', 'USD')?.inverse().toString(); // '1.3654'
48
+ */
49
+ export function quotedTable(spec) {
50
+ const rates = {};
51
+ for (const [currency, entry] of Object.entries(spec.rates)) {
52
+ if (entry === null) {
53
+ rates[currency] = null;
54
+ continue;
55
+ }
56
+ let quoted;
57
+ if (typeof entry === 'string') {
58
+ quoted = { rate: entry };
59
+ }
60
+ else {
61
+ quoted = entry;
62
+ }
63
+ let text = quoted.rate.trim();
64
+ const decimals = quoted.decimals ?? spec.decimals;
65
+ if (decimals !== undefined) {
66
+ text = withDecimals(text, decimals);
67
+ }
68
+ const quote = { rate: text };
69
+ if (quoted.per !== undefined) {
70
+ quote.per = quoted.per;
71
+ }
72
+ if (quoted.inverted ?? spec.inverted ?? false) {
73
+ quote.inverted = true;
74
+ }
75
+ rates[currency] = rateFromQuote(spec.base, currency, quote, spec);
76
+ }
77
+ return rateTable({ ...spec, rates });
78
+ }
79
+ /** The UTC date ('2026-11-06') of a date, an instant (any offset) or a Date. */
80
+ function dayOf(time) {
81
+ return toIsoString(time).slice(0, 10);
82
+ }
83
+ /**
84
+ * Why a table can't answer the pair at the time asked for, or undefined when it can. The table's
85
+ * own dates are checked first; a table built from a list of Rates has none, so its rate's are.
86
+ */
87
+ function passOver(table, from, to, query, periodEnded) {
88
+ const asOf = query?.asOf;
89
+ if (periodEnded) {
90
+ return 'expired';
91
+ }
92
+ if (asOf !== undefined &&
93
+ table.availableAt !== undefined &&
94
+ !hasStarted(table.availableAt, asOf)) {
95
+ return 'notYetAvailable';
96
+ }
97
+ if (table.rate(from, to, query) !== undefined) {
98
+ return undefined;
99
+ }
100
+ if (table.missing?.includes(from) === true || table.missing?.includes(to) === true) {
101
+ return 'missing';
102
+ }
103
+ const held = table.rates.find((rate) => rate.from === from && rate.to === to);
104
+ if (held !== undefined && asOf !== undefined) {
105
+ if (held.isExpired(asOf)) {
106
+ return 'expired';
107
+ }
108
+ if (!held.isAvailable(asOf)) {
109
+ return 'notYetAvailable';
110
+ }
111
+ }
112
+ return 'notQuoted';
113
+ }
114
+ /** The ISO date `count` days before `day`. */
115
+ function daysBefore(day, count) {
116
+ return new Date(Date.parse(`${day}T00:00:00Z`) - count * DAY_MS).toISOString().slice(0, 10);
117
+ }
118
+ /**
119
+ * A provider over many dated tables, such as a date range loaded in one call: for each lookup it
120
+ * takes the latest table at or before `asOf` that has the pair, published by then and still
121
+ * valid, looking back up to `lookback` days. Each currency pair falls back on its own, so a
122
+ * currency missing on a holiday comes from the day before while the others stay current; the
123
+ * Rate's `asOf` says which day it is from. Without an `asOf`, the newest table with the pair
124
+ * answers. `lookup` reports why a lookup fell back.
125
+ *
126
+ * const history = rateHistory(parseEcbXml(xml90Days));
127
+ * history.rate('EUR', 'USD', { asOf: '2026-11-08' }); // Sunday: Friday's rate
128
+ * history.lookup('EUR', 'USD', { asOf: '2026-11-08' }).skipped;
129
+ * // [{ day: '2026-11-08', reason: 'noTable' }, { day: '2026-11-07', reason: 'noTable' }]
130
+ */
131
+ export function rateHistory(tables, options) {
132
+ const lookback = options?.lookback ?? 4;
133
+ if (!Number.isSafeInteger(lookback) || lookback < 0) {
134
+ throw new RangeError(`lookback must be a non-negative integer, got ${lookback}`);
135
+ }
136
+ const dated = [];
137
+ for (const table of tables) {
138
+ if (table.asOf === undefined) {
139
+ throw new RangeError('rateHistory needs tables with an asOf');
140
+ }
141
+ dated.push({ day: dayOf(table.asOf), table });
142
+ }
143
+ // Newest first; a stable sort keeps the caller's order within a day.
144
+ dated.sort((entry, other) => (other.day < entry.day ? -1 : Number(other.day > entry.day)));
145
+ const hasPeriods = dated.some((entry) => entry.table.validUntil !== undefined);
146
+ function lookup(from, to, query) {
147
+ const asOf = query?.asOf;
148
+ const skipped = [];
149
+ let firstDay;
150
+ if (asOf !== undefined) {
151
+ firstDay = dayOf(asOf);
152
+ }
153
+ else {
154
+ firstDay = dated[0]?.day;
155
+ }
156
+ if (firstDay === undefined) {
157
+ return { rate: undefined, skipped };
158
+ }
159
+ const lastDay = daysBefore(firstDay, lookback);
160
+ // The newest day of the lookback window not yet accounted for by a daily table.
161
+ let expectedDay = firstDay;
162
+ for (const { day, table } of dated) {
163
+ if (day > firstDay) {
164
+ continue;
165
+ }
166
+ const periodEnded = asOf !== undefined && table.validUntil !== undefined && hasEnded(table.validUntil, asOf);
167
+ const coversPeriod = table.validUntil !== undefined && !periodEnded;
168
+ if (day < lastDay && !coversPeriod) {
169
+ // Older daily tables are out of the window; an older period table may still cover it.
170
+ if (!hasPeriods) {
171
+ break;
172
+ }
173
+ continue;
174
+ }
175
+ // Days between the last table and this one had no table. A period table that answers
176
+ // covers them, so for one they count only once it turns out not to answer.
177
+ // An older period table comes after every day of the window, so all of them are gaps.
178
+ const inWindow = day >= lastDay;
179
+ const accountedTo = inWindow ? day : daysBefore(lastDay, 1);
180
+ const gaps = [];
181
+ for (let gap = expectedDay; gap > accountedTo; gap = daysBefore(gap, 1)) {
182
+ gaps.push({ day: gap, reason: 'noTable' });
183
+ }
184
+ if (!coversPeriod) {
185
+ skipped.push(...gaps);
186
+ }
187
+ const reason = passOver(table, from, to, query, periodEnded);
188
+ if (reason === undefined) {
189
+ return { rate: table.rate(from, to, query), skipped };
190
+ }
191
+ if (coversPeriod) {
192
+ skipped.push(...gaps);
193
+ }
194
+ skipped.push({ day, reason });
195
+ if (accountedTo <= expectedDay) {
196
+ expectedDay = inWindow ? daysBefore(day, 1) : accountedTo;
197
+ }
198
+ }
199
+ // Days left in the window without any table at all.
200
+ for (let gap = expectedDay; gap >= lastDay; gap = daysBefore(gap, 1)) {
201
+ skipped.push({ day: gap, reason: 'noTable' });
202
+ }
203
+ return { rate: undefined, skipped };
204
+ }
205
+ return {
206
+ tables: dated.map((entry) => entry.table),
207
+ rate(from, to, query) {
208
+ return lookup(from, to, query).rate;
209
+ },
210
+ lookup,
211
+ };
212
+ }
213
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
package/dist/hmrc.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { type RateTable } from './provider.js';
2
+ /** Options for parseHmrcMonthlyCsv. */
3
+ export interface HmrcOptions {
4
+ /**
5
+ * When each period's rates were published, or false for none. Default: the end (UTC) of the
6
+ * Wednesday before the penultimate Thursday of the month before, when HMRC publishes them.
7
+ */
8
+ readonly availableAt?: false | ((start: string) => string | Date);
9
+ }
10
+ /**
11
+ * Parses HMRC's monthly exchange rates CSV (trade-tariff.service.gov.uk, under the Open
12
+ * Government Licence) into one GBP-based table per period, newest first. Each is valid for its
13
+ * calendar month: `asOf` is the start date and `validUntil` the end date, so a `rateHistory` of
14
+ * them answers any day of the month (see @ducatjs/money/convert/history). Rates are currency units
15
+ * per £1, with `source: 'HMRC'` and `type: 'customs'`, four decimals as published. HMRC publishes
16
+ * each month's file in the month before, on the Wednesday before its penultimate Thursday (the
17
+ * `publication_date` that https://www.trade-tariff.service.gov.uk/api/v2/exchange_rates/
18
+ * period_lists/2026?filter[type]=monthly gives for each file); `availableAt` is the end of that
19
+ * UTC day. Several countries share a code (the CFA francs, AED, XCD): their rows must agree.
20
+ * HMRC never leaves a rate blank, so a blank or missing-value cell throws SyntaxError, as does any
21
+ * other row that can't be read. A file may hold several periods; they may overlap (a mid-month
22
+ * amendment, say), and `rateHistory` then uses the one that started last.
23
+ *
24
+ * const [november] = parseHmrcMonthlyCsv(await readFile('monthly_csv_2026-11.csv', 'utf8'));
25
+ * november.rate('GBP', 'EUR', { asOf: '2026-11-15' })?.toString(); // '1.1930'
26
+ */
27
+ export declare function parseHmrcMonthlyCsv(csv: string, options?: HmrcOptions): RateTable[];
28
+ //# sourceMappingURL=hmrc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmrc.d.ts","sourceRoot":"","sources":["../src/hmrc.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAmC1D,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC;CACnE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CA6DnF"}
package/dist/hmrc.js ADDED
@@ -0,0 +1,108 @@
1
+ // `@ducatjs/money/convert/hmrc`: an offline parser for HMRC's monthly exchange rates, the UK's
2
+ // rates for customs and VAT. No I/O: download the CSV yourself.
3
+ import { rateTable } from './provider.js';
4
+ import { addDayRate, csvRows, isCalendarDay, newestFirst, readRateCell } from './rate-text.js';
5
+ const UK_DATE = /^(\d\d)\/(\d\d)\/(\d{4})$/;
6
+ const COLUMNS = ['Currency Code', 'Currency Units per £1', 'Start date', 'End date'];
7
+ function notHmrc(why) {
8
+ throw new SyntaxError(`Not an HMRC monthly exchange rates CSV file: ${why}`);
9
+ }
10
+ /** 'DD/MM/YYYY' as an ISO date, or SyntaxError. */
11
+ function isoDate(text) {
12
+ const match = UK_DATE.exec(text.trim());
13
+ const day = match === null ? '' : `${match[3]}-${match[2]}-${match[1]}`;
14
+ if (!isCalendarDay(day)) {
15
+ notHmrc(`bad date ${JSON.stringify(text)}`);
16
+ }
17
+ return day;
18
+ }
19
+ /**
20
+ * When a month's rates are public: the end of the day HMRC publishes them, the Wednesday before the
21
+ * penultimate Thursday of the month before. The trade tariff service's API gives that Wednesday as
22
+ * the `publication_date` of every monthly file from January 2024 to November 2026; it gives no
23
+ * time of day, so the end of that UTC day is the earliest moment that is never too early. That
24
+ * instant is the start of the penultimate Thursday.
25
+ */
26
+ function publishedBy(start) {
27
+ // The last day of the previous month, then back to its last Thursday, then a week before that.
28
+ const lastDay = new Date(Date.UTC(Number(start.slice(0, 4)), Number(start.slice(5, 7)) - 1, 0));
29
+ const backToThursday = (lastDay.getUTCDay() - 4 + 7) % 7;
30
+ lastDay.setUTCDate(lastDay.getUTCDate() - backToThursday - 7);
31
+ return lastDay.toISOString();
32
+ }
33
+ /**
34
+ * Parses HMRC's monthly exchange rates CSV (trade-tariff.service.gov.uk, under the Open
35
+ * Government Licence) into one GBP-based table per period, newest first. Each is valid for its
36
+ * calendar month: `asOf` is the start date and `validUntil` the end date, so a `rateHistory` of
37
+ * them answers any day of the month (see @ducatjs/money/convert/history). Rates are currency units
38
+ * per £1, with `source: 'HMRC'` and `type: 'customs'`, four decimals as published. HMRC publishes
39
+ * each month's file in the month before, on the Wednesday before its penultimate Thursday (the
40
+ * `publication_date` that https://www.trade-tariff.service.gov.uk/api/v2/exchange_rates/
41
+ * period_lists/2026?filter[type]=monthly gives for each file); `availableAt` is the end of that
42
+ * UTC day. Several countries share a code (the CFA francs, AED, XCD): their rows must agree.
43
+ * HMRC never leaves a rate blank, so a blank or missing-value cell throws SyntaxError, as does any
44
+ * other row that can't be read. A file may hold several periods; they may overlap (a mid-month
45
+ * amendment, say), and `rateHistory` then uses the one that started last.
46
+ *
47
+ * const [november] = parseHmrcMonthlyCsv(await readFile('monthly_csv_2026-11.csv', 'utf8'));
48
+ * november.rate('GBP', 'EUR', { asOf: '2026-11-15' })?.toString(); // '1.1930'
49
+ */
50
+ export function parseHmrcMonthlyCsv(csv, options) {
51
+ const [header, ...rows] = csvRows(csv.charCodeAt(0) === 0xfeff ? csv.slice(1) : csv);
52
+ const names = (header ?? []).map((name) => name.trim());
53
+ const index = COLUMNS.map((name) => names.indexOf(name));
54
+ if (index.some((i) => i === -1)) {
55
+ notHmrc(`the columns are ${names.join(', ')}`);
56
+ }
57
+ const [codeAt, rateAt, startAt, endAt] = index;
58
+ if (rows.length === 0) {
59
+ notHmrc('no rates');
60
+ }
61
+ // Periods by their start and end; within one, rates by code.
62
+ const periods = new Map();
63
+ for (const cells of rows) {
64
+ if (cells.length !== names.length) {
65
+ notHmrc(`a row has ${cells.length} cells, the header ${names.length}`);
66
+ }
67
+ const code = cells[codeAt].trim();
68
+ if (!/^[A-Z]{3}$/.test(code) || code === 'GBP') {
69
+ notHmrc(`bad currency code ${JSON.stringify(code)}`);
70
+ }
71
+ const start = isoDate(cells[startAt]);
72
+ const end = isoDate(cells[endAt]);
73
+ if (end < start) {
74
+ notHmrc(`${code} ends on ${end}, before it starts on ${start}`);
75
+ }
76
+ const key = `${start}/${end}`;
77
+ let codes = periods.get(key);
78
+ if (codes === undefined) {
79
+ codes = new Map();
80
+ periods.set(key, codes);
81
+ }
82
+ const where = `${code} from ${start}`;
83
+ const rate = readRateCell(cells[rateAt], where);
84
+ if (rate === null) {
85
+ notHmrc(`no rate for ${where}`);
86
+ }
87
+ addDayRate(codes, start, code, rate);
88
+ }
89
+ const tables = [];
90
+ for (const [key, codes] of periods) {
91
+ const [start, end] = key.split('/');
92
+ const rates = codes.get(start);
93
+ if (!Object.values(rates).some((rate) => rate !== null)) {
94
+ continue;
95
+ }
96
+ let availableAt;
97
+ if (options?.availableAt === undefined) {
98
+ availableAt = publishedBy(start);
99
+ }
100
+ else if (options.availableAt !== false) {
101
+ availableAt = options.availableAt(start);
102
+ }
103
+ const info = { base: 'GBP', source: 'HMRC', type: 'customs', asOf: start, validUntil: end };
104
+ tables.push(rateTable({ ...info, ...(availableAt === undefined ? {} : { availableAt }), rates }));
105
+ }
106
+ return newestFirst(tables);
107
+ }
108
+ //# sourceMappingURL=hmrc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmrc.js","sourceRoot":"","sources":["../src/hmrc.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * formatting, parsing and the processor and database views are opt-in modules
6
6
  * (`@ducatjs/money/allocate`, `@ducatjs/money/tax`, ...; `@ducatjs/money/all` for everything).
7
7
  */
8
- export { money, fromMinor, zero, fromJSON, isMoney, extendMoney, type ExtendMoneyOptions, sum, ratio, CurrencyMismatchError, type Money, type MoneyJSON, type MoneyOptions, type CurrencyInput, type Factor, type Ratio, } from './money.js';
8
+ export { money, fromMinor, zero, fromJSON, isMoney, isMoneyIn, assertCurrency, extendMoney, type ExtendMoneyOptions, sum, ratio, CurrencyMismatchError, type RoundingPolicy, type RoundingInput, type Money, type MoneyJSON, type MoneyOptions, type CurrencyInput, type Factor, type Ratio, } from './money.js';
9
9
  export { DEFAULT_ROUNDING, Rounding, RoundingError, type RoundingMode } from './rounding.js';
10
10
  export { currencyExponent, defineCurrency, isCurrency, ISO_EXPONENTS, ISO_4217_PUBLISHED, ISO_NON_MONETARY, type CurrencyCode, type IsoCurrencyCode, type CustomCurrencies, } from './currency.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,WAAW,EACX,KAAK,kBAAkB,EACvB,GAAG,EACH,KAAK,EACL,qBAAqB,EACrB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,KAAK,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,EACvB,GAAG,EACH,KAAK,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,KAAK,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * formatting, parsing and the processor and database views are opt-in modules
6
6
  * (`@ducatjs/money/allocate`, `@ducatjs/money/tax`, ...; `@ducatjs/money/all` for everything).
7
7
  */
8
- export { money, fromMinor, zero, fromJSON, isMoney, extendMoney, sum, ratio, CurrencyMismatchError, } from './money.js';
8
+ export { money, fromMinor, zero, fromJSON, isMoney, isMoneyIn, assertCurrency, extendMoney, sum, ratio, CurrencyMismatchError, } from './money.js';
9
9
  export { DEFAULT_ROUNDING, Rounding, RoundingError } from './rounding.js';
10
10
  export { currencyExponent, defineCurrency, isCurrency, ISO_EXPONENTS, ISO_4217_PUBLISHED, ISO_NON_MONETARY, } from './currency.js';
11
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,WAAW,EAEX,GAAG,EACH,KAAK,EACL,qBAAqB,GAOtB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAqB,MAAM,eAAe,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GAIjB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,cAAc,EACd,WAAW,EAEX,GAAG,EACH,KAAK,EACL,qBAAqB,GAStB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAqB,MAAM,eAAe,CAAC;AAC7F,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GAIjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * `@ducatjs/money/kysely`: Money in Kysely queries, without the plugin having to understand query
3
+ * shapes. A money value is selected as a self-describing JSON object built in SQL (marked, with the
4
+ * amount as exact text and the currency), and `MoneyResultPlugin` turns exactly those objects into
5
+ * Money, wherever they appear: unions, CTEs, subqueries, nested JSON, every `stream()` chunk, and
6
+ * under `CamelCasePlugin`. A raw column is never typed as Money.
7
+ *
8
+ * const money = moneyHelpers('postgres');
9
+ * const db = new Kysely<Database>({ dialect, plugins: [new MoneyResultPlugin()] });
10
+ *
11
+ * await db.insertInto('payments').values({ id: 1, ...setMoney(fee, 'amount_minor', 'currency') });
12
+ * await db
13
+ * .selectFrom('payments')
14
+ * .select((eb) => money.selectMoney(eb, 'amount_minor', 'currency').as('fee'))
15
+ * .where((eb) => money.compareMoney(eb, 'amount_minor', 'currency', '>=', fee))
16
+ * .execute();
17
+ */
18
+ import { type ColumnType, type Expression, type ExpressionBuilder, type ExtractTypeFromReferenceExpression, type KyselyPlugin, type PluginTransformQueryArgs, type PluginTransformResultArgs, type QueryResult, type RawBuilder, type ReferenceExpression, type RootOperationNode, type SqlBool, type UnknownRow } from 'kysely';
19
+ import { type CurrencyInput, type Money } from './money.js';
20
+ import { type DecimalColumnSize } from './sql.js';
21
+ export { DEFAULT_DECIMAL_SIZE, type DecimalColumnSize } from './sql.js';
22
+ /** The SQL dialects the helpers can build JSON objects and exact casts for. */
23
+ export type MoneyDialect = 'postgres' | 'mysql' | 'sqlite';
24
+ /**
25
+ * A BIGINT (SQLite INTEGER) column of minor units. Drivers return it as a string, a number or a
26
+ * bigint; `setMoney` writes integer strings, which every driver binds exactly.
27
+ */
28
+ export type MinorUnitsColumn = ColumnType<string | number | bigint, string | bigint, string | bigint>;
29
+ /** A NUMERIC/DECIMAL (SQLite TEXT) column holding the exact decimal as a string. */
30
+ export type DecimalAmountColumn = ColumnType<string, string, string>;
31
+ /** A currency that is fixed for a column instead of stored in another column: `fixed('EUR')`. */
32
+ export interface FixedCurrency<C extends string> {
33
+ readonly fixed: C;
34
+ }
35
+ /** Marks a column's currency as fixed: `selectMoney(eb, 'total_minor', fixed('EUR'))`. */
36
+ export declare function fixed<const C extends CurrencyInput>(currency: C): FixedCurrency<C>;
37
+ /** The comparison operators `compareMoney` supports. */
38
+ export type MoneyComparison = '=' | '<>' | '<' | '<=' | '>' | '>=';
39
+ /** `Money<C>`, or `Money<C> | null` when the amount column is nullable. */
40
+ type MoneyFor<Amount, C extends string> = null extends Amount ? Money<C> | null : Money<C>;
41
+ /**
42
+ * Column values for an insert or update: the minor units as an integer string, and the currency
43
+ * (unless it is fixed for the column, in which case the Money must be in it).
44
+ *
45
+ * .values({ id: 1, ...setMoney(fee, 'amount_minor', 'currency') })
46
+ * .set(setMoney(total, 'total_minor', fixed('EUR')))
47
+ */
48
+ export declare function setMoney<const A extends string, const K extends string>(money: Money, amount: A, currency: K): {
49
+ [P in A | K]: string;
50
+ };
51
+ export declare function setMoney<const A extends string, const C extends string>(money: Money<NoInfer<C>>, amount: A, currency: FixedCurrency<C>): {
52
+ [P in A]: string;
53
+ };
54
+ /**
55
+ * Like `setMoney`, for a NUMERIC/DECIMAL amount column: the exact decimal. Pass the column's size
56
+ * (NUMERIC(19,4) by default) so that a value it would round or clamp throws instead. On SQLite,
57
+ * where decimals are TEXT, the size only limits what is written.
58
+ */
59
+ export declare function setDecimalMoney<const A extends string, const K extends string>(money: Money, amount: A, currency: K, size?: DecimalColumnSize): {
60
+ [P in A | K]: string;
61
+ };
62
+ export declare function setDecimalMoney<const A extends string, const C extends string>(money: Money<NoInfer<C>>, amount: A, currency: FixedCurrency<C>, size?: DecimalColumnSize): {
63
+ [P in A]: string;
64
+ };
65
+ /** The money helpers for one dialect, from `moneyHelpers`. */
66
+ export interface MoneyHelpers {
67
+ /**
68
+ * The Money in an amount column of minor units, with the currency from a column or `fixed()`.
69
+ * Typed `Money<C>`, or `Money<C> | null` for a nullable amount column; needs `MoneyResultPlugin`.
70
+ *
71
+ * .select((eb) => money.selectMoney(eb, 'p.amount_minor', 'p.currency').as('paid'))
72
+ */
73
+ selectMoney<DB, TB extends keyof DB, RA extends ReferenceExpression<DB, TB>>(eb: ExpressionBuilder<DB, TB>, amount: RA, currency: ReferenceExpression<DB, TB>): RawBuilder<MoneyFor<ExtractTypeFromReferenceExpression<DB, TB, RA>, CurrencyInput>>;
74
+ selectMoney<DB, TB extends keyof DB, RA extends ReferenceExpression<DB, TB>, C extends string>(eb: ExpressionBuilder<DB, TB>, amount: RA, currency: FixedCurrency<C>): RawBuilder<MoneyFor<ExtractTypeFromReferenceExpression<DB, TB, RA>, C>>;
75
+ /** Like `selectMoney`, for a NUMERIC/DECIMAL (SQLite TEXT) amount column. */
76
+ selectDecimalMoney<DB, TB extends keyof DB, RA extends ReferenceExpression<DB, TB>>(eb: ExpressionBuilder<DB, TB>, amount: RA, currency: ReferenceExpression<DB, TB>): RawBuilder<MoneyFor<ExtractTypeFromReferenceExpression<DB, TB, RA>, CurrencyInput>>;
77
+ selectDecimalMoney<DB, TB extends keyof DB, RA extends ReferenceExpression<DB, TB>, C extends string>(eb: ExpressionBuilder<DB, TB>, amount: RA, currency: FixedCurrency<C>): RawBuilder<MoneyFor<ExtractTypeFromReferenceExpression<DB, TB, RA>, C>>;
78
+ /**
79
+ * A condition comparing a stored amount with Money, currency and amount together. With a
80
+ * currency column, `=` and the ordering comparisons also require the same currency, and `<>`
81
+ * holds when either differs. With `fixed()`, Money in another currency throws.
82
+ *
83
+ * .where((eb) => money.compareMoney(eb, 'amount_minor', 'currency', '>=', limit))
84
+ */
85
+ compareMoney<DB, TB extends keyof DB>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: ReferenceExpression<DB, TB> | FixedCurrency<string>, operator: MoneyComparison, money: Money): Expression<SqlBool>;
86
+ /**
87
+ * Like `compareMoney`, for a NUMERIC/DECIMAL amount column of the given size (NUMERIC(19,4) by
88
+ * default). SQLite allows only `=` and `<>`, which compare the text, so they match only values
89
+ * written with `setDecimalMoney`.
90
+ */
91
+ compareDecimalMoney<DB, TB extends keyof DB>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: ReferenceExpression<DB, TB> | FixedCurrency<string>, operator: MoneyComparison, money: Money, size?: DecimalColumnSize): Expression<SqlBool>;
92
+ /**
93
+ * The sum of an amount column as Money, or null over no rows. With a currency column, rows in
94
+ * more than one currency (or an amount without a currency) make the result throw when read, so
95
+ * group by the currency column to sum per currency.
96
+ *
97
+ * .select((eb) => [money.sumMoney(eb, 'amount_minor', 'currency').as('total'), 'currency'])
98
+ * .groupBy('currency')
99
+ */
100
+ sumMoney<DB, TB extends keyof DB>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: ReferenceExpression<DB, TB>): RawBuilder<Money | null>;
101
+ sumMoney<DB, TB extends keyof DB, C extends string>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: FixedCurrency<C>): RawBuilder<Money<C> | null>;
102
+ /** Like `sumMoney`, for a NUMERIC/DECIMAL amount column. Not available on SQLite (TEXT). */
103
+ sumDecimalMoney<DB, TB extends keyof DB>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: ReferenceExpression<DB, TB>): RawBuilder<Money | null>;
104
+ sumDecimalMoney<DB, TB extends keyof DB, C extends string>(eb: ExpressionBuilder<DB, TB>, amount: ReferenceExpression<DB, TB>, currency: FixedCurrency<C>): RawBuilder<Money<C> | null>;
105
+ }
106
+ /** The read, filter and sum helpers for one SQL dialect. */
107
+ export declare function moneyHelpers(dialect: MoneyDialect): MoneyHelpers;
108
+ /**
109
+ * A Kysely plugin that turns the values built by `moneyHelpers` into Money, in every row and in
110
+ * JSON nested inside rows. It keeps no state between queries and doesn't touch the query, so it
111
+ * works with streams, prepared and repeated queries, and other plugins. For nested JSON that
112
+ * SQLite returns as text (`jsonArrayFrom`), put `ParseJSONResultsPlugin` before it.
113
+ */
114
+ export declare class MoneyResultPlugin implements KyselyPlugin {
115
+ /** Leaves the query as it is. */
116
+ transformQuery(args: PluginTransformQueryArgs): RootOperationNode;
117
+ /** Converts the money values in every row. */
118
+ transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>>;
119
+ }
120
+ //# sourceMappingURL=kysely.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kysely.d.ts","sourceRoot":"","sources":["../src/kysely.ts"],"names":[],"mappings":"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"}