@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.
Files changed (253) hide show
  1. package/NOTICE +73 -0
  2. package/README.md +479 -62
  3. package/data/cash-rounding.json +123 -2
  4. package/data/cldr-cash.json +101 -0
  5. package/data/historic.json +78 -0
  6. package/data/iso4217-list-three.xml +1185 -0
  7. package/dist/adyen-fx.d.ts.map +1 -1
  8. package/dist/adyen-fx.js +22 -4
  9. package/dist/adyen-fx.js.map +1 -1
  10. package/dist/boc.d.ts +31 -0
  11. package/dist/boc.d.ts.map +1 -0
  12. package/dist/boc.js +114 -0
  13. package/dist/boc.js.map +1 -0
  14. package/dist/boe.d.ts +33 -0
  15. package/dist/boe.d.ts.map +1 -0
  16. package/dist/boe.js +114 -0
  17. package/dist/boe.js.map +1 -0
  18. package/dist/cash.d.ts +30 -1
  19. package/dist/cash.d.ts.map +1 -1
  20. package/dist/cash.js +50 -2
  21. package/dist/cash.js.map +1 -1
  22. package/dist/convert.d.ts +10 -9
  23. package/dist/convert.d.ts.map +1 -1
  24. package/dist/convert.js +13 -3
  25. package/dist/convert.js.map +1 -1
  26. package/dist/drizzle/mysql.d.ts +105 -0
  27. package/dist/drizzle/mysql.d.ts.map +1 -0
  28. package/dist/drizzle/mysql.js +60 -0
  29. package/dist/drizzle/mysql.js.map +1 -0
  30. package/dist/drizzle/pg.d.ts +103 -0
  31. package/dist/drizzle/pg.d.ts.map +1 -0
  32. package/dist/drizzle/pg.js +60 -0
  33. package/dist/drizzle/pg.js.map +1 -0
  34. package/dist/drizzle/sqlite.d.ts +102 -0
  35. package/dist/drizzle/sqlite.d.ts.map +1 -0
  36. package/dist/drizzle/sqlite.js +59 -0
  37. package/dist/drizzle/sqlite.js.map +1 -0
  38. package/dist/ecb.d.ts +37 -2
  39. package/dist/ecb.d.ts.map +1 -1
  40. package/dist/ecb.js +148 -10
  41. package/dist/ecb.js.map +1 -1
  42. package/dist/fed.d.ts +35 -0
  43. package/dist/fed.d.ts.map +1 -0
  44. package/dist/fed.js +134 -0
  45. package/dist/fed.js.map +1 -0
  46. package/dist/fetch.d.ts +45 -0
  47. package/dist/fetch.d.ts.map +1 -1
  48. package/dist/fetch.js +167 -24
  49. package/dist/fetch.js.map +1 -1
  50. package/dist/fn.d.ts +8 -1
  51. package/dist/fn.d.ts.map +1 -1
  52. package/dist/fn.js +8 -1
  53. package/dist/fn.js.map +1 -1
  54. package/dist/generated/cash.d.ts +2 -0
  55. package/dist/generated/cash.d.ts.map +1 -1
  56. package/dist/generated/cash.js +101 -0
  57. package/dist/generated/cash.js.map +1 -1
  58. package/dist/generated/historic.d.ts +337 -0
  59. package/dist/generated/historic.d.ts.map +1 -0
  60. package/dist/generated/historic.js +66 -0
  61. package/dist/generated/historic.js.map +1 -0
  62. package/dist/historic.d.ts +40 -0
  63. package/dist/historic.d.ts.map +1 -0
  64. package/dist/historic.js +43 -0
  65. package/dist/historic.js.map +1 -0
  66. package/dist/history.d.ts +96 -0
  67. package/dist/history.d.ts.map +1 -0
  68. package/dist/history.js +213 -0
  69. package/dist/history.js.map +1 -0
  70. package/dist/hmrc.d.ts +28 -0
  71. package/dist/hmrc.d.ts.map +1 -0
  72. package/dist/hmrc.js +108 -0
  73. package/dist/hmrc.js.map +1 -0
  74. package/dist/index.d.ts +1 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +1 -1
  77. package/dist/index.js.map +1 -1
  78. package/dist/kysely.d.ts +120 -0
  79. package/dist/kysely.d.ts.map +1 -0
  80. package/dist/kysely.js +309 -0
  81. package/dist/kysely.js.map +1 -0
  82. package/dist/money.d.ts +93 -9
  83. package/dist/money.d.ts.map +1 -1
  84. package/dist/money.js +135 -9
  85. package/dist/money.js.map +1 -1
  86. package/dist/parse.d.ts +45 -1
  87. package/dist/parse.d.ts.map +1 -1
  88. package/dist/parse.js +290 -3
  89. package/dist/parse.js.map +1 -1
  90. package/dist/pg.d.ts +100 -0
  91. package/dist/pg.d.ts.map +1 -0
  92. package/dist/pg.js +343 -0
  93. package/dist/pg.js.map +1 -0
  94. package/dist/plugins/adyen.d.ts +1 -1
  95. package/dist/plugins/adyen.d.ts.map +1 -1
  96. package/dist/plugins/adyen.js.map +1 -1
  97. package/dist/plugins/all.d.ts +8 -1
  98. package/dist/plugins/all.d.ts.map +1 -1
  99. package/dist/plugins/all.js +8 -1
  100. package/dist/plugins/all.js.map +1 -1
  101. package/dist/plugins/allocate.d.ts +1 -1
  102. package/dist/plugins/allocate.d.ts.map +1 -1
  103. package/dist/plugins/allocate.js.map +1 -1
  104. package/dist/plugins/braintree.d.ts +1 -1
  105. package/dist/plugins/braintree.d.ts.map +1 -1
  106. package/dist/plugins/braintree.js.map +1 -1
  107. package/dist/plugins/cash.d.ts +1 -1
  108. package/dist/plugins/cash.d.ts.map +1 -1
  109. package/dist/plugins/cash.js.map +1 -1
  110. package/dist/plugins/checkout.d.ts +1 -1
  111. package/dist/plugins/checkout.d.ts.map +1 -1
  112. package/dist/plugins/checkout.js.map +1 -1
  113. package/dist/plugins/convert.d.ts +5 -5
  114. package/dist/plugins/convert.d.ts.map +1 -1
  115. package/dist/plugins/convert.js.map +1 -1
  116. package/dist/plugins/exact.d.ts +1 -1
  117. package/dist/plugins/exact.d.ts.map +1 -1
  118. package/dist/plugins/exact.js.map +1 -1
  119. package/dist/plugins/fixed.d.ts +1 -1
  120. package/dist/plugins/fixed.d.ts.map +1 -1
  121. package/dist/plugins/fixed.js.map +1 -1
  122. package/dist/plugins/format.d.ts +1 -1
  123. package/dist/plugins/format.d.ts.map +1 -1
  124. package/dist/plugins/format.js.map +1 -1
  125. package/dist/plugins/klarna.d.ts +1 -1
  126. package/dist/plugins/klarna.d.ts.map +1 -1
  127. package/dist/plugins/klarna.js.map +1 -1
  128. package/dist/plugins/paypal.d.ts +1 -1
  129. package/dist/plugins/paypal.d.ts.map +1 -1
  130. package/dist/plugins/paypal.js +0 -4
  131. package/dist/plugins/paypal.js.map +1 -1
  132. package/dist/plugins/prisma.d.ts +1 -1
  133. package/dist/plugins/prisma.d.ts.map +1 -1
  134. package/dist/plugins/prisma.js +0 -4
  135. package/dist/plugins/prisma.js.map +1 -1
  136. package/dist/plugins/stripe.d.ts +1 -1
  137. package/dist/plugins/stripe.d.ts.map +1 -1
  138. package/dist/plugins/stripe.js +0 -4
  139. package/dist/plugins/stripe.js.map +1 -1
  140. package/dist/plugins/tax.d.ts +6 -6
  141. package/dist/plugins/tax.d.ts.map +1 -1
  142. package/dist/plugins/tax.js.map +1 -1
  143. package/dist/policy.d.ts +34 -0
  144. package/dist/policy.d.ts.map +1 -0
  145. package/dist/policy.js +90 -0
  146. package/dist/policy.js.map +1 -0
  147. package/dist/prisma.d.ts +25 -14
  148. package/dist/prisma.d.ts.map +1 -1
  149. package/dist/prisma.js +29 -19
  150. package/dist/prisma.js.map +1 -1
  151. package/dist/provider.d.ts +21 -7
  152. package/dist/provider.d.ts.map +1 -1
  153. package/dist/provider.js +51 -11
  154. package/dist/provider.js.map +1 -1
  155. package/dist/rate-text.d.ts +38 -0
  156. package/dist/rate-text.d.ts.map +1 -0
  157. package/dist/rate-text.js +143 -0
  158. package/dist/rate-text.js.map +1 -0
  159. package/dist/rate.d.ts +61 -5
  160. package/dist/rate.d.ts.map +1 -1
  161. package/dist/rate.js +133 -33
  162. package/dist/rate.js.map +1 -1
  163. package/dist/rounding.js +1 -1
  164. package/dist/rounding.js.map +1 -1
  165. package/dist/schema.d.ts +43 -0
  166. package/dist/schema.d.ts.map +1 -0
  167. package/dist/schema.js +77 -0
  168. package/dist/schema.js.map +1 -0
  169. package/dist/sql.d.ts +54 -0
  170. package/dist/sql.d.ts.map +1 -0
  171. package/dist/sql.js +131 -0
  172. package/dist/sql.js.map +1 -0
  173. package/dist/tax.d.ts +13 -9
  174. package/dist/tax.d.ts.map +1 -1
  175. package/dist/tax.js +20 -4
  176. package/dist/tax.js.map +1 -1
  177. package/dist/testing/arbitraries.d.ts +43 -0
  178. package/dist/testing/arbitraries.d.ts.map +1 -0
  179. package/dist/testing/arbitraries.js +98 -0
  180. package/dist/testing/arbitraries.js.map +1 -0
  181. package/dist/testing/index.d.ts +67 -0
  182. package/dist/testing/index.d.ts.map +1 -0
  183. package/dist/testing/index.js +159 -0
  184. package/dist/testing/index.js.map +1 -0
  185. package/dist/testing/jest.d.ts +2 -0
  186. package/dist/testing/jest.d.ts.map +1 -0
  187. package/dist/testing/jest.js +15 -0
  188. package/dist/testing/jest.js.map +1 -0
  189. package/dist/testing/vitest.d.ts +7 -0
  190. package/dist/testing/vitest.d.ts.map +1 -0
  191. package/dist/testing/vitest.js +12 -0
  192. package/dist/testing/vitest.js.map +1 -0
  193. package/dist/valibot.d.ts +33 -0
  194. package/dist/valibot.d.ts.map +1 -0
  195. package/dist/valibot.js +61 -0
  196. package/dist/valibot.js.map +1 -0
  197. package/dist/zod.d.ts +36 -0
  198. package/dist/zod.d.ts.map +1 -0
  199. package/dist/zod.js +58 -0
  200. package/dist/zod.js.map +1 -0
  201. package/package.json +116 -5
  202. package/src/adyen-fx.ts +25 -4
  203. package/src/boc.ts +136 -0
  204. package/src/boe.ts +131 -0
  205. package/src/cash.ts +70 -2
  206. package/src/convert.ts +33 -15
  207. package/src/drizzle/mysql.ts +78 -0
  208. package/src/drizzle/pg.ts +78 -0
  209. package/src/drizzle/sqlite.ts +70 -0
  210. package/src/ecb.ts +179 -13
  211. package/src/fed.ts +146 -0
  212. package/src/fetch.ts +207 -28
  213. package/src/fn.ts +14 -0
  214. package/src/generated/cash.ts +103 -0
  215. package/src/generated/historic.ts +67 -0
  216. package/src/historic.ts +77 -0
  217. package/src/history.ts +333 -0
  218. package/src/hmrc.ts +125 -0
  219. package/src/index.ts +4 -0
  220. package/src/kysely.ts +588 -0
  221. package/src/money.ts +210 -12
  222. package/src/parse.ts +371 -4
  223. package/src/pg.ts +410 -0
  224. package/src/plugins/adyen.ts +3 -2
  225. package/src/plugins/all.ts +10 -0
  226. package/src/plugins/allocate.ts +3 -2
  227. package/src/plugins/braintree.ts +3 -2
  228. package/src/plugins/cash.ts +3 -2
  229. package/src/plugins/checkout.ts +3 -2
  230. package/src/plugins/convert.ts +6 -6
  231. package/src/plugins/exact.ts +3 -2
  232. package/src/plugins/fixed.ts +3 -2
  233. package/src/plugins/format.ts +3 -2
  234. package/src/plugins/klarna.ts +3 -2
  235. package/src/plugins/paypal.ts +3 -2
  236. package/src/plugins/prisma.ts +3 -2
  237. package/src/plugins/stripe.ts +3 -2
  238. package/src/plugins/tax.ts +11 -11
  239. package/src/policy.ts +124 -0
  240. package/src/prisma.ts +91 -10
  241. package/src/provider.ts +81 -16
  242. package/src/rate-text.ts +151 -0
  243. package/src/rate.ts +205 -36
  244. package/src/rounding.ts +1 -1
  245. package/src/schema.ts +119 -0
  246. package/src/sql.ts +178 -0
  247. package/src/tax.ts +40 -9
  248. package/src/testing/arbitraries.ts +134 -0
  249. package/src/testing/index.ts +247 -0
  250. package/src/testing/jest.ts +18 -0
  251. package/src/testing/vitest.ts +18 -0
  252. package/src/valibot.ts +87 -0
  253. package/src/zod.ts +78 -0
package/dist/rate.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // is converted.
4
4
  import { currencyExponent } from './currency.js';
5
5
  import { formatScaled, POW10, pow10n, ratio, ratioToDecimal, normalizeMinor, } from './decimal.js';
6
- import { CurrencyMismatchError, make } from './money.js';
6
+ import { CurrencyMismatchError, make, roundWithPolicy, } from './money.js';
7
7
  import { DEFAULT_ROUNDING, divideAndRound, divideAndRoundBigint, } from './rounding.js';
8
8
  const MAX_SAFE_MINOR = Number.MAX_SAFE_INTEGER;
9
9
  /** Thrown by a strict-validity conversion with a rate past its `validUntil`. */
@@ -32,18 +32,45 @@ export function toIsoString(time) {
32
32
  }
33
33
  return date.toISOString();
34
34
  }
35
+ /** A date as the first instant of its UTC day; an instant as it is. */
36
+ function asInstant(time) {
37
+ return ISO_DATE.test(time) ? `${time}T00:00:00.000Z` : time;
38
+ }
35
39
  /**
36
- * The earlier of two ISO-8601 strings (one format compares lexicographically); undefined = no
37
- * limit.
40
+ * @internal
41
+ * Whether `time` has come by `at`. A date `at` means the whole of that UTC day, so anything on or
42
+ * before that day counts; a date `time` means the start of its day.
38
43
  */
39
- function earlier(first, second) {
44
+ export function hasStarted(time, at) {
45
+ const instant = toIsoString(at);
46
+ if (ISO_DATE.test(instant)) {
47
+ return time.slice(0, 10) <= instant;
48
+ }
49
+ return asInstant(time) <= instant;
50
+ }
51
+ /** @internal Whether `validUntil` (a date: valid all day, UTC) has passed at `at`. */
52
+ export function hasEnded(validUntil, at) {
53
+ const instant = asInstant(toIsoString(at));
54
+ if (ISO_DATE.test(validUntil)) {
55
+ return instant.slice(0, 10) > validUntil;
56
+ }
57
+ return instant > validUntil;
58
+ }
59
+ /**
60
+ * The earlier of two ISO-8601 strings (one format compares lexicographically), or the later one
61
+ * with `later`; undefined = no limit.
62
+ */
63
+ function earlier(first, second, later) {
40
64
  if (first === undefined) {
41
65
  return second;
42
66
  }
43
- if (second === undefined || first <= second) {
67
+ if (second === undefined) {
44
68
  return first;
45
69
  }
46
- return second;
70
+ if (later === true) {
71
+ return first >= second ? first : second;
72
+ }
73
+ return first <= second ? first : second;
47
74
  }
48
75
  /**
49
76
  * minor × rate × 10^scaleShift, rounded once with `rounding`. This is the kernel of every
@@ -104,17 +131,19 @@ export class Rate {
104
131
  this.ratio = normalized;
105
132
  // Only defined fields are assigned, so rates compare and serialise without undefined keys.
106
133
  const writable = this;
107
- if (info?.source !== undefined) {
108
- writable.source = info.source;
109
- }
110
- if (info?.asOf !== undefined) {
111
- writable.asOf = toIsoString(info.asOf);
112
- }
113
- if (info?.validUntil !== undefined) {
114
- writable.validUntil = toIsoString(info.validUntil);
134
+ const quote = info?.quote;
135
+ if (quote !== undefined) {
136
+ // toString prints a one-for-one quote, so it must be this rate. (rateFromQuote derives a
137
+ // scaled or inverted rate from its quote, so that one can't disagree.)
138
+ const direct = quote.per === undefined && quote.inverted !== true;
139
+ // ratio() caches strings, so for a rate built from the same text this is two lookups.
140
+ const quoted = direct ? ratio(quote.rate) : normalized;
141
+ if (quoted.num !== normalized.num || quoted.den !== normalized.den) {
142
+ throw new RangeError(`Quote ${quote.rate} isn't the rate ${from}→${to}`);
143
+ }
115
144
  }
116
- if (info?.type !== undefined) {
117
- writable.type = info.type;
145
+ if (info !== undefined) {
146
+ Object.assign(this, infoOf(info));
118
147
  }
119
148
  if (derivedFrom !== undefined) {
120
149
  writable.derivedFrom = derivedFrom;
@@ -127,7 +156,15 @@ export class Rate {
127
156
  type = OPPOSITE_SIDE[type] ?? type;
128
157
  }
129
158
  const reciprocal = ratio(this.ratio.den, this.ratio.num);
130
- return new Rate(this.to, this.from, reciprocal, timingOf(this, type), [this]);
159
+ let info = timingOf(this, type);
160
+ // The published number reads the other way round now, so the inverse of a quoted rate keeps
161
+ // its digits too: the inverse of CAD→USD quoted as 1.3650 inverted prints '1.3650'.
162
+ const quote = this.quote;
163
+ if (quote !== undefined) {
164
+ const { inverted, ...rest } = quote;
165
+ info = { ...info, quote: inverted === true ? rest : { ...rest, inverted: true } };
166
+ }
167
+ return new Rate(this.to, this.from, reciprocal, info, [this]);
131
168
  }
132
169
  /**
133
170
  * The exact composite `from` → `next.to`. Nothing is rounded: converting with it rounds once.
@@ -143,9 +180,12 @@ export class Rate {
143
180
  if (this.type === next.type) {
144
181
  type = this.type;
145
182
  }
183
+ // A composite is known only once both legs are, and is valid only while both are.
146
184
  const asOf = earlier(this.asOf, next.asOf);
185
+ const availableAt = earlier(this.availableAt, next.availableAt, true);
147
186
  const validUntil = earlier(this.validUntil, next.validUntil);
148
- return new Rate(this.from, next.to, product, timing(asOf, validUntil, type), [this, next]);
187
+ const info = timing(asOf, availableAt, validUntil, type);
188
+ return new Rate(this.from, next.to, product, info, [this, next]);
149
189
  }
150
190
  /** This rate × (1 + margin), exactly: `withMargin('-0.02')` gives 2% less `to` per `from`. */
151
191
  withMargin(margin) {
@@ -167,13 +207,25 @@ export class Rate {
167
207
  const scaled = divideAndRoundBigint(this.ratio.num * pow10n(places), this.ratio.den, rounding);
168
208
  return formatScaled(scaled, places);
169
209
  }
170
- /** The exact rate: '1.1165', or '2000/2233' when its decimal expansion doesn't terminate. */
210
+ /**
211
+ * The exact rate: '1.1165', or '2000/2233' when its decimal expansion doesn't terminate. A rate
212
+ * published one unit for one unit keeps the published digits ('136.80').
213
+ */
171
214
  toString() {
215
+ const quote = this.quote;
216
+ if (quote !== undefined && quote.per === undefined && quote.inverted !== true) {
217
+ return quote.rate;
218
+ }
172
219
  return ratioToDecimal(this.ratio) ?? `${this.ratio.num}/${this.ratio.den}`;
173
220
  }
174
221
  /** The rate, its metadata and its audit chain as JSON. `rateFromJSON` reverses it. */
175
222
  toJSON() {
176
- const json = { from: this.from, to: this.to, rate: this.toString(), ...infoOf(this) };
223
+ const { quote, ...info } = infoOf(this);
224
+ const json = { from: this.from, to: this.to, rate: this.toString(), ...info };
225
+ // A direct quote is the `rate` string itself, so only a scaled or inverted one is written.
226
+ if (quote !== undefined && (quote.per !== undefined || quote.inverted === true)) {
227
+ json.quote = quote;
228
+ }
177
229
  if (this.derivedFrom !== undefined) {
178
230
  json.derivedFrom = this.derivedFrom.map((input) => input.toJSON());
179
231
  }
@@ -187,16 +239,22 @@ export class Rate {
187
239
  if (this.validUntil === undefined) {
188
240
  return false;
189
241
  }
190
- let instant = toIsoString(now);
191
- if (ISO_DATE.test(instant)) {
192
- instant = `${instant}T00:00:00.000Z`;
193
- }
194
- if (ISO_DATE.test(this.validUntil)) {
195
- return instant.slice(0, 10) > this.validUntil;
242
+ return hasEnded(this.validUntil, now);
243
+ }
244
+ /**
245
+ * Whether the rate had been published by `at`: always, without an `availableAt`. A date `at`
246
+ * means by the end of that UTC day.
247
+ */
248
+ isAvailable(at) {
249
+ if (this.availableAt === undefined) {
250
+ return true;
196
251
  }
197
- return instant > this.validUntil;
252
+ return hasStarted(this.availableAt, at);
198
253
  }
199
- /** Converts `money`, rounding once to the target currency's exponent (or `options.scale`). */
254
+ /**
255
+ * Converts `money`, rounding once: with a mode, to the target currency's exponent (or
256
+ * `options.scale`); with a rounding policy, to the policy's scale and increment.
257
+ */
200
258
  convert(money, rounding = DEFAULT_ROUNDING, options) {
201
259
  if (money.currency !== this.from) {
202
260
  throw new CurrencyMismatchError(this.from, money.currency);
@@ -204,11 +262,27 @@ export class Rate {
204
262
  if (options?.strictValidity === true && this.validUntil !== undefined && this.isExpired()) {
205
263
  throw new RateExpiredError(this.from, this.to, this.validUntil);
206
264
  }
265
+ if (typeof rounding === 'function') {
266
+ return convertWithPolicy(money, this.to, this.ratio, rounding, options);
267
+ }
207
268
  const scale = options?.scale ?? currencyExponent(this.to);
208
269
  const minor = multiplyByRatioAtScale(money.minor, this.ratio, scale - money.scale, rounding);
209
270
  return make(this.to, minor, scale);
210
271
  }
211
272
  }
273
+ /**
274
+ * @internal
275
+ * money × rate in `to`, rounded once by a policy. The amount is relabelled `to` at its own scale,
276
+ * so the policy rounds the product exactly as it would a multiplication in `to`: to its scale
277
+ * (default `to`'s exponent) and increment, checking its currency against `to`.
278
+ */
279
+ export function convertWithPolicy(money, to, rate, policy, options) {
280
+ // Two scales would leave it unclear which one the result has.
281
+ if (options?.scale !== undefined) {
282
+ throw new TypeError('options.scale with a rounding policy');
283
+ }
284
+ return roundWithPolicy(make(to, money.minor, money.scale), rate, policy);
285
+ }
212
286
  /** The metadata fields of `info` that are defined (no undefined keys). */
213
287
  function infoOf(info) {
214
288
  const defined = {};
@@ -218,22 +292,47 @@ function infoOf(info) {
218
292
  if (info.asOf !== undefined) {
219
293
  defined.asOf = toIsoString(info.asOf);
220
294
  }
295
+ if (info.availableAt !== undefined) {
296
+ defined.availableAt = toIsoString(info.availableAt);
297
+ }
221
298
  if (info.validUntil !== undefined) {
222
299
  defined.validUntil = toIsoString(info.validUntil);
223
300
  }
224
301
  if (info.type !== undefined) {
225
302
  defined.type = info.type;
226
303
  }
304
+ if (info.quote !== undefined) {
305
+ defined.quote = info.quote;
306
+ }
227
307
  return defined;
228
308
  }
229
- function timing(asOf, validUntil, type) {
230
- return infoOf({ asOf, validUntil, type });
309
+ function timing(asOf, availableAt, validUntil, type) {
310
+ return infoOf({ asOf, availableAt, validUntil, type });
231
311
  }
232
312
  /**
233
313
  * A derived rate keeps the timing of its input; the input's source stays with it, in derivedFrom.
234
314
  */
235
315
  function timingOf(input, type) {
236
- return timing(input.asOf, input.validUntil, type);
316
+ return timing(input.asOf, input.availableAt, input.validUntil, type);
317
+ }
318
+ // A published decimal whose canonical form drops digits: trailing fraction zeros only. Leading
319
+ // zeros ('01.50') aren't published digits, so those are left to the canonical form.
320
+ const PUBLISHED_DECIMAL = /^(?:0|[1-9]\d*)\.\d*0$/;
321
+ /**
322
+ * Keeps the published digits of `text` on a Rate just built from it, when its canonical form would
323
+ * drop some ('1.1650' prints as '1.165'). Assigned directly: the quote is the rate's own text, so
324
+ * there is nothing to check, and building a rate inline stays cheap.
325
+ */
326
+ function keepDigits(rate, text) {
327
+ // Only a last character of '0' can be dropped, so most rates are settled by one comparison.
328
+ const dropsDigits = typeof text === 'string' &&
329
+ text.charCodeAt(text.length - 1) === 48 &&
330
+ rate.quote === undefined &&
331
+ PUBLISHED_DECIMAL.test(text);
332
+ if (dropsDigits) {
333
+ rate.quote = { rate: text };
334
+ }
335
+ return rate;
237
336
  }
238
337
  /**
239
338
  * An exact rate pinned to a currency pair, so converting the wrong currency is a type error. Give
@@ -245,12 +344,13 @@ function timingOf(input, type) {
245
344
  * eurUsd.inverse().ratio // 2000/2233, exactly
246
345
  */
247
346
  export function exchangeRate(from, to, rate, info) {
248
- return new Rate(from, to, ratio(rate), info);
347
+ return keepDigits(new Rate(from, to, ratio(rate), info), rate);
249
348
  }
250
349
  /** Rebuilds a Rate, with its audit chain, from `rate.toJSON()`. */
251
350
  export function rateFromJSON(json) {
252
351
  const derivedFrom = json.derivedFrom?.map(rateFromJSON);
253
- return new Rate(json.from, json.to, ratio(json.rate), infoOf(json), derivedFrom);
352
+ const rate = new Rate(json.from, json.to, ratio(json.rate), infoOf(json), derivedFrom);
353
+ return keepDigits(rate, json.rate);
254
354
  }
255
355
  /** Whether `value` is a Rate. */
256
356
  export function isRate(value) {
package/dist/rate.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rate.js","sourceRoot":"","sources":["../src/rate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate.js","sourceRoot":"","sources":["../src/rate.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,mGAAmG;AACnG,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,KAAK,EACL,MAAM,EACN,KAAK,EACL,cAAc,EACd,cAAc,GAGf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,EACrB,IAAI,EACJ,eAAe,GAKhB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,oBAAoB,GAErB,MAAM,eAAe,CAAC;AAEvB,MAAM,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAoD/C,gFAAgF;AAChF,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IACrC,UAAU,CAAS;IAE5B,YAAY,IAAY,EAAE,EAAU,EAAE,UAAkB;QACtD,KAAK,CAAC,iBAAiB,IAAI,IAAI,EAAE,eAAe,UAAU,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AA4BD,MAAM,aAAa,GAA6B,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAE3E,MAAM,QAAQ,GAAG,mBAAmB,CAAC;AAErC;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,UAAU,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED,uEAAuE;AACvE,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAiB;IACxD,MAAM,OAAO,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AACpC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,EAAiB;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CACd,KAAyB,EACzB,MAA0B,EAC1B,KAAe;IAEf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAsB,EACtB,IAAW,EACX,UAAkB,EAClB,QAAsB;IAEtB,gGAAgG;IAChG,gGAAgG;IAChG,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,IAAI,UAAU,IAAI,CAAC,EAAE,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QACrF,IAAI,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;QACvB,IAAI,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;QACzB,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,SAAS,IAAI,KAAK,CAAC,UAAU,CAAE,CAAC;QAClC,CAAC;aAAM,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YAC1B,WAAW,IAAI,KAAK,CAAC,CAAC,UAAU,CAAE,CAAC;QACrC,CAAC;QAED,IAAI,SAAS,IAAI,cAAc,IAAI,WAAW,IAAI,cAAc,EAAE,CAAC;YACjE,MAAM,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;YAClC,IAAI,OAAO,IAAI,cAAc,IAAI,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC5D,OAAO,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,IAAI,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IACzC,IAAI,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;IAC3B,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;SAAM,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QAC1B,WAAW,IAAI,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,cAAc,CAAC,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,IAAI;IACN,IAAI,CAAO;IACX,EAAE,CAAK;IACP,KAAK,CAAQ;IAWtB,mCAAmC;IACnC,YAAY,IAAU,EAAE,EAAM,EAAE,IAAW,EAAE,IAAe,EAAE,WAA6B;QACzF,2FAA2F;QAC3F,uEAAuE;QACvE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,UAAU,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,UAAU,CAAC,gCAAgC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;QAExB,2FAA2F;QAC3F,MAAM,QAAQ,GAAG,IAAmD,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,yFAAyF;YACzF,uEAAuE;YACvE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;YAClE,sFAAsF;YACtF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;YACvD,IAAI,MAAM,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,EAAE,CAAC;gBACnE,MAAM,IAAI,UAAU,CAAC,SAAS,KAAK,CAAC,IAAI,mBAAmB,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;QACrC,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,OAAO;QACL,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;QACrC,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzD,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,4FAA4F;QAC5F,oFAAoF;QACpF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;YACpC,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QACpF,CAAC;QACD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACH,OAAO,CAAsB,IAAoB;QAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAExF,kFAAkF;QAClF,IAAI,IAA0B,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;QACD,kFAAkF;QAClF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,8FAA8F;IAC9F,UAAU,CAAC,MAAc;QACvB,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC;QACrD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAc,EAAE,WAAyB,UAAU;QACvD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QACxD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,+FAA+F;IAC/F,SAAS,CAAC,MAAc,EAAE,WAAyB,UAAU;QAC3D,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC/F,OAAO,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC9E,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7E,CAAC;IAED,sFAAsF;IACtF,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,IAAI,GAAa,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;QACxF,2FAA2F;QAC3F,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;YAChF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,MAAqB,IAAI,IAAI,EAAE;QACvC,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,EAAiB;QAC3B,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,OAAO,CACL,KAAkB,EAClB,WAA0B,gBAAgB,EAC1C,OAAwB;QAExB,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,EAAE,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAC1F,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,OAAO,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC7F,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAY,EACZ,EAAM,EACN,IAAW,EACX,MAAsB,EACtB,OAAwB;IAExB,8DAA8D;IAC9D,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,0EAA0E;AAC1E,SAAS,MAAM,CAAC,IAAe;IAC7B,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,CAAC,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IAC3B,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,MAAM,CACb,IAAa,EACb,WAAoB,EACpB,UAAmB,EACnB,IAAe;IAEf,OAAO,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,KAAW,EAAE,IAAe;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,+FAA+F;AAC/F,oFAAoF;AACpF,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AAEnD;;;;GAIG;AACH,SAAS,UAAU,CAAiB,IAAO,EAAE,IAAY;IACvD,4FAA4F;IAC5F,MAAM,WAAW,GACf,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;QACvC,IAAI,CAAC,KAAK,KAAK,SAAS;QACxB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,WAAW,EAAE,CAAC;QACf,IAA8B,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAU,EACV,EAAM,EACN,IAAY,EACZ,IAAe;IAEf,OAAO,UAAU,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;IACvF,OAAO,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,IAAI,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,SAAsB,EACtB,OAAkB,EAClB,IAAe;IAEf,8EAA8E;IAC9E,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;AAC7F,CAAC"}
package/dist/rounding.js CHANGED
@@ -34,7 +34,7 @@ const MAX_SAFE_MINOR = Number.MAX_SAFE_INTEGER;
34
34
  */
35
35
  export function divideAndRound(dividend, divisor, mode) {
36
36
  if (divisor === 1) {
37
- return dividend;
37
+ return dividend + 0; // + 0 normalises -0 (0 * -1 from a caller)
38
38
  }
39
39
  // Beyond MAX_SAFE_MINOR the product quotient * divisor below could round, so take the bigint
40
40
  // path.
@@ -1 +1 @@
1
- {"version":3,"file":"rounding.js","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,IAAI,0BAA0B,EAClD,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAyBpD;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,aAAa;CACqB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAiB,YAAY,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAkB;IAClF,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,6FAA6F;IAC7F,QAAQ;IACR,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC;QACtD,OAAO,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;IAC9C,wEAAwE;IACxE,IAAI,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAE9C,gGAAgG;IAChG,4CAA4C;IAC5C,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS,IAAI,OAAO,CAAC;QACvB,CAAC;aAAM,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;YAChC,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS,IAAI,OAAO,CAAC;QACvB,CAAC;IACH,CAAC;SAAM,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACzB,QAAQ,IAAI,CAAC,CAAC;QACd,SAAS,IAAI,OAAO,CAAC;IACvB,CAAC;SAAM,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,QAAQ,IAAI,CAAC,CAAC;QACd,SAAS,IAAI,OAAO,CAAC;IACvB,CAAC;IAED,kGAAkG;IAClG,QAAQ;IACR,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,QAAQ,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAC3C,CAAC;IACD,8FAA8F;IAC9F,iBAAiB;IACjB,OAAO,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,OAAe,EACf,IAAkB;IAElB,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,0BAA0B,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"rounding.js","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,IAAI,0BAA0B,EAClD,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAyBpD;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,aAAa;CACqB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAiB,YAAY,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAkB;IAClF,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO,QAAQ,GAAG,CAAC,CAAC,CAAC,2CAA2C;IAClE,CAAC;IACD,6FAA6F;IAC7F,QAAQ;IACR,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC;QACtD,OAAO,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;IAC9C,wEAAwE;IACxE,IAAI,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAE9C,gGAAgG;IAChG,4CAA4C;IAC5C,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS,IAAI,OAAO,CAAC;QACvB,CAAC;aAAM,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;YAChC,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS,IAAI,OAAO,CAAC;QACvB,CAAC;IACH,CAAC;SAAM,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACzB,QAAQ,IAAI,CAAC,CAAC;QACd,SAAS,IAAI,OAAO,CAAC;IACvB,CAAC;SAAM,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,QAAQ,IAAI,CAAC,CAAC;QACd,SAAS,IAAI,OAAO,CAAC;IACvB,CAAC;IAED,kGAAkG;IAClG,QAAQ;IACR,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,QAAQ,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAC3C,CAAC;IACD,8FAA8F;IAC9F,iBAAiB;IACjB,OAAO,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,OAAe,EACf,IAAkB;IAElB,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,0BAA0B,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type Money, type MoneyJSON } from './money.js';
2
+ import { type RoundingMode } from './rounding.js';
3
+ /** Options for the Zod and Valibot money schemas. */
4
+ export interface MoneySchemaOptions<C extends string = string> {
5
+ /**
6
+ * The currency, or the currencies, to accept. Without it, any ISO 4217 code or code registered
7
+ * with `defineCurrency` is accepted, and nothing else.
8
+ */
9
+ readonly currency?: C | readonly C[];
10
+ /** Decimal places to keep (default: the currency's exponent), as in `money()`. */
11
+ readonly scale?: number;
12
+ /**
13
+ * How to round an amount with more decimals than the scale. The default, 'unnecessary', rejects
14
+ * such amounts, as `fromJSON` does.
15
+ */
16
+ readonly rounding?: RoundingMode;
17
+ /**
18
+ * The most digits the amount may have, not counting the sign and the decimal point (default
19
+ * 50). It keeps an oversized request body from building a huge bigint.
20
+ */
21
+ readonly maxDigits?: number;
22
+ }
23
+ /** The default `maxDigits`: far beyond any real amount, small enough to be cheap to reject. */
24
+ export declare const DEFAULT_MAX_DIGITS = 50;
25
+ /**
26
+ * @internal Checks the options when the schema is built, so a mistake there throws at once
27
+ * instead of turning every input into a validation error.
28
+ */
29
+ export declare function checkSchemaOptions(options: MoneySchemaOptions | undefined): void;
30
+ /** The Money type a schema produces: one Money per allowed currency, not a mixed-currency Money. */
31
+ export type MoneyFor<C extends string> = C extends string ? Money<C> : never;
32
+ /** @internal A problem with one field of the input, for the schema libraries' issue paths. */
33
+ export interface MoneyIssue {
34
+ readonly field: 'amount' | 'currency';
35
+ readonly message: string;
36
+ }
37
+ /**
38
+ * @internal Reads `{ amount, currency }` (already known to have two string fields) into Money, or
39
+ * says what is wrong with it. Shared by the Zod and Valibot entries, so both accept exactly the
40
+ * same inputs.
41
+ */
42
+ export declare function readMoneyJSON<C extends string>(json: MoneyJSON, options: MoneySchemaOptions<C> | undefined): Money | MoneyIssue;
43
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5D,qDAAqD;AACrD,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC3D;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;IACrC,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,+FAA+F;AAC/F,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAIrC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,SAAS,GAAG,IAAI,CAyBhF;AAED,oGAAoG;AACpG,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;AAE7E,8FAA8F;AAC9F,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC5C,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,SAAS,GACzC,KAAK,GAAG,UAAU,CAmCpB"}
package/dist/schema.js ADDED
@@ -0,0 +1,77 @@
1
+ import { isCurrency } from './currency.js';
2
+ import { MAX_DECIMAL_SCALE } from './decimal.js';
3
+ import { money } from './money.js';
4
+ import { Rounding } from './rounding.js';
5
+ /** The default `maxDigits`: far beyond any real amount, small enough to be cheap to reject. */
6
+ export const DEFAULT_MAX_DIGITS = 50;
7
+ const MODES = new Set(Object.values(Rounding));
8
+ /**
9
+ * @internal Checks the options when the schema is built, so a mistake there throws at once
10
+ * instead of turning every input into a validation error.
11
+ */
12
+ export function checkSchemaOptions(options) {
13
+ if (options === undefined) {
14
+ return;
15
+ }
16
+ const allowed = options.currency;
17
+ const codes = typeof allowed === 'string' || allowed === undefined ? [allowed] : allowed;
18
+ for (const code of codes) {
19
+ if (code !== undefined && !isCurrency(code)) {
20
+ throw new RangeError(`Unknown currency ${String(code)}`);
21
+ }
22
+ }
23
+ const scale = options.scale;
24
+ if (scale !== undefined &&
25
+ !(Number.isInteger(scale) && scale >= 0 && scale <= MAX_DECIMAL_SCALE)) {
26
+ throw new RangeError(`Invalid scale ${scale}`);
27
+ }
28
+ if (options.rounding !== undefined && !MODES.has(options.rounding)) {
29
+ throw new RangeError(`Invalid rounding mode ${String(options.rounding)}`);
30
+ }
31
+ const maxDigits = options.maxDigits;
32
+ if (maxDigits !== undefined && !(Number.isSafeInteger(maxDigits) && maxDigits >= 1)) {
33
+ throw new RangeError(`Invalid maxDigits ${maxDigits}`);
34
+ }
35
+ }
36
+ // The exact decimal strings `toJSON` writes: an optional minus, digits, and an optional fraction.
37
+ // No exponent, no plus sign, no whitespace and no grouping, so the wire format stays unambiguous.
38
+ const DECIMAL = /^-?\d+(?:\.\d+)?$/;
39
+ /**
40
+ * @internal Reads `{ amount, currency }` (already known to have two string fields) into Money, or
41
+ * says what is wrong with it. Shared by the Zod and Valibot entries, so both accept exactly the
42
+ * same inputs.
43
+ */
44
+ export function readMoneyJSON(json, options) {
45
+ const currency = json.currency;
46
+ const allowed = options?.currency;
47
+ if (allowed === undefined) {
48
+ if (!isCurrency(currency)) {
49
+ return { field: 'currency', message: `Unknown currency "${currency}"` };
50
+ }
51
+ }
52
+ else if (typeof allowed === 'string' ? currency !== allowed : !allowed.includes(currency)) {
53
+ const expected = typeof allowed === 'string' ? allowed : allowed.join(', ');
54
+ return { field: 'currency', message: `Expected currency ${expected}, got "${currency}"` };
55
+ }
56
+ const amount = json.amount;
57
+ // Checked before the pattern, so a huge string is rejected without scanning it.
58
+ const maxLength = (options?.maxDigits ?? DEFAULT_MAX_DIGITS) + 2;
59
+ if (amount.length > maxLength || !DECIMAL.test(amount)) {
60
+ return { field: 'amount', message: 'Expected a decimal string such as "12.34"' };
61
+ }
62
+ const digitCount = amount.length - (amount[0] === '-' ? 1 : 0) - (amount.includes('.') ? 1 : 0);
63
+ if (digitCount > (options?.maxDigits ?? DEFAULT_MAX_DIGITS)) {
64
+ return {
65
+ field: 'amount',
66
+ message: `More than ${options?.maxDigits ?? DEFAULT_MAX_DIGITS} digits`,
67
+ };
68
+ }
69
+ try {
70
+ return money(amount, currency, options);
71
+ }
72
+ catch (error) {
73
+ // the options are checked up front, so this is too many decimals for the scale
74
+ return { field: 'amount', message: error.message };
75
+ }
76
+ }
77
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,KAAK,EAA8B,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAuB5D,+FAA+F;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAU,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAuC;IACxE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACzF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,UAAU,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IACE,KAAK,KAAK,SAAS;QACnB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,iBAAiB,CAAC,EACtE,CAAC;QACD,MAAM,IAAI,UAAU,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,UAAU,CAAC,yBAAyB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,UAAU,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAWD,kGAAkG;AAClG,kGAAkG;AAClG,MAAM,OAAO,GAAG,mBAAmB,CAAC;AAEpC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAe,EACf,OAA0C;IAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,EAAE,QAAQ,CAAC;IAElC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,QAAQ,GAAG,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;SAAM,IACL,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAa,CAAC,EACrF,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,QAAQ,UAAU,QAAQ,GAAG,EAAE,CAAC;IAC5F,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,gFAAgF;IAChF,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,SAAS,IAAI,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,GAAG,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2CAA2C,EAAE,CAAC;IACnF,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,IAAI,UAAU,GAAG,CAAC,OAAO,EAAE,SAAS,IAAI,kBAAkB,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,aAAa,OAAO,EAAE,SAAS,IAAI,kBAAkB,SAAS;SACxE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+EAA+E;QAC/E,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAG,KAAe,CAAC,OAAO,EAAE,CAAC;IAChE,CAAC;AACH,CAAC"}
package/dist/sql.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ import { type Money } from './money.js';
2
+ /** The declared size of a NUMERIC/DECIMAL column. */
3
+ export interface DecimalColumnSize {
4
+ /** Total number of significant digits the column holds. */
5
+ readonly precision: number;
6
+ /** Digits after the decimal point. */
7
+ readonly scale: number;
8
+ }
9
+ /** NUMERIC(19,4): 15 integer digits and 4 decimals, enough for every ISO 4217 exponent. */
10
+ export declare const DEFAULT_DECIMAL_SIZE: DecimalColumnSize;
11
+ /** Throws unless the money is in the column's currency (when the column has a fixed currency). */
12
+ export declare function checkCurrency(money: Money, currency: string | undefined): void;
13
+ /**
14
+ * Throws unless the money is at its currency's exponent. Columns store amounts at the currency's
15
+ * scale, so a value with sub-minor digits would have to be rounded, and the caller should choose how.
16
+ */
17
+ export declare function checkIsoScale(money: Money): void;
18
+ /**
19
+ * Minor units for a BIGINT column, as a bigint. Throws beyond the column's range, ±9.2·10^18:
20
+ * MySQL outside strict mode would store the nearest limit instead.
21
+ */
22
+ export declare function minorToDriver(money: Money, currency: string | undefined): bigint;
23
+ /**
24
+ * Money from a BIGINT driver value. Accepts a bigint, a safe-integer number, or an integer string
25
+ * (node-postgres returns int8 as a string). A number beyond 2^53 has already lost digits, so it
26
+ * throws.
27
+ */
28
+ export declare function minorFromDriver<C extends string>(value: unknown, currency: C): Money<C>;
29
+ /** Throws if a decimal column of this size would round amounts in this currency. */
30
+ export declare function checkDecimalSize(currency: string, size: DecimalColumnSize): void;
31
+ /**
32
+ * The exact decimal string for a NUMERIC/DECIMAL column. Throws if the column could not hold it
33
+ * unchanged: MySQL outside strict mode clamps an out-of-range value instead of failing.
34
+ */
35
+ export declare function decimalToDriver(money: Money, currency: string | undefined, size: DecimalColumnSize | undefined): string;
36
+ /**
37
+ * Throws if the decimal (the money's `toDecimal`) has more integer digits than a column of this
38
+ * size holds: Postgres rejects it, and MySQL outside strict mode clamps it.
39
+ */
40
+ export declare function checkIntegerDigits(money: Money, decimal: string, size: DecimalColumnSize): void;
41
+ /**
42
+ * Money from a NUMERIC/DECIMAL driver value, which must be a string: a number has been through a
43
+ * float. Trailing zeros (`12.3400` from NUMERIC(19,4)) are fine; more decimals than the currency
44
+ * has, `NaN` and `Infinity` throw.
45
+ */
46
+ export declare function decimalFromDriver<C extends string>(value: unknown, currency: C): Money<C>;
47
+ /** `{"amount":"12.34","currency":"EUR"}` for a JSON, JSONB or TEXT column. */
48
+ export declare function jsonToDriver(money: Money, currency: string | undefined): string;
49
+ /**
50
+ * Money from a JSON column: the parsed object (JSONB in node-postgres, JSON in mysql2) or the
51
+ * text (SQLite).
52
+ */
53
+ export declare function jsonFromDriver<C extends string>(value: unknown, currency: C | undefined): Money<C>;
54
+ //# sourceMappingURL=sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAKA,OAAO,EAOL,KAAK,KAAK,EAEX,MAAM,YAAY,CAAC;AAOpB,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,iBAA+C,CAAC;AAEnF,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAI9E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAOhD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAShF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAWvF;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAkBhF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,iBAAiB,GAAG,SAAS,GAClC,MAAM,CASR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAU/F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAQzF;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAI/E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,GAAG,SAAS,GACtB,KAAK,CAAC,CAAC,CAAC,CAOV"}