@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
package/dist/convert.js CHANGED
@@ -4,7 +4,7 @@ import { exact } from './exact.js';
4
4
  import { ratio } from './decimal.js';
5
5
  import { make } from './money.js';
6
6
  import { rateOf } from './provider.js';
7
- import { isRate, multiplyByRatioAtScale } from './rate.js';
7
+ import { convertWithPolicy, isRate, multiplyByRatioAtScale, } from './rate.js';
8
8
  import { DEFAULT_ROUNDING } from './rounding.js';
9
9
  export { exchangeRate, impliedRate, isRate, multiplyByRatioAtScale, Rate, RateExpiredError, rateFromJSON, } from './rate.js';
10
10
  export { bag, comparator, MoneyBag, sortByValue, sumByCurrency, } from './bag.js';
@@ -37,19 +37,29 @@ export function convert(money, rateOrTarget, roundingOrRate, optionsOrRounding,
37
37
  throw new RangeError('Exchange rate must be positive');
38
38
  }
39
39
  const rounding = optionsOrRounding ?? DEFAULT_ROUNDING;
40
+ if (typeof rounding === 'function') {
41
+ return convertWithPolicy(money, to, rate, rounding, maybeOptions);
42
+ }
40
43
  const scale = maybeOptions?.scale ?? currencyExponent(to);
41
44
  const minor = multiplyByRatioAtScale(money.minor, rate, scale - money.scale, rounding);
42
45
  return make(to, minor, scale);
43
46
  }
44
47
  /**
45
48
  * Converts at `rate` like convert(), and also reports the residual: `value + residual` is exactly
46
- * money × rate, so a ledger can book the rounding difference.
49
+ * money × rate, so a ledger can book the rounding difference. With a rounding policy, the value
50
+ * is on the policy's scale and increment, and the residual is still the exact difference.
47
51
  *
48
52
  * const { value, residual } = convertDetailed(money('0.07', 'EUR'), eurUsd, 'halfEven');
49
53
  * // value 0.08 USD, residual -0.001845 USD (as an exact ExactMoney)
50
54
  */
51
55
  export function convertDetailed(money, rate, rounding = DEFAULT_ROUNDING, options) {
52
- const rounded = exact(money).convert(rate).roundWithResidual(rounding, options?.scale);
56
+ const converted = exact(money).convert(rate);
57
+ if (typeof rounding === 'function') {
58
+ // The policy rounds; the residual is still exactly what it left out.
59
+ const value = rate.convert(money, rounding, options);
60
+ return { value, residual: converted.subtract(exact(value)), rate };
61
+ }
62
+ const rounded = converted.roundWithResidual(rounding, options?.scale);
53
63
  return { value: rounded.value, residual: rounded.residual, rate };
54
64
  }
55
65
  //# sourceMappingURL=convert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,KAAK,EAAe,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,IAAI,EAAkC,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,MAAM,EAAqB,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAkC,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAqB,MAAM,eAAe,CAAC;AAEpE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,sBAAsB,EACtB,IAAI,EACJ,gBAAgB,EAChB,YAAY,GAKb,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,GAAG,EACH,UAAU,EACV,QAAQ,EACR,WAAW,EACX,aAAa,GAGd,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EACT,oBAAoB,EACpB,QAAQ,EACR,SAAS,EACT,aAAa,EACb,GAAG,GAOJ,MAAM,eAAe,CAAC;AAQvB,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAQ,KAAkC,EAAE,IAAI,KAAK,UAAU,CAAC;AACzE,CAAC;AAyCD,MAAM,UAAU,OAAO,CACrB,KAAY,EACZ,YAA2B,EAC3B,cAAqD,EACrD,iBAAiD,EACjD,YAAqC;IAErC,IAAI,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,cAA0C,CAAC;QAC5D,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,iBAA+C,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,EAAE,GAAG,YAAY,CAAC;IACxB,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,IAAI,KAA0C,CAAC;QAC/C,IAAI,YAAY,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YACrC,KAAK,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC;QACtC,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,iBAA6C,EAAE,YAAY,CAAC,CAAC;IAC1F,CAAC;IAED,8FAA8F;IAC9F,IAAI,IAAI,GAAG,KAAK,CAAC,cAAwB,CAAC,CAAC;IAC3C,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;QACvC,6FAA6F;QAC7F,4FAA4F;QAC5F,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,UAAU,CAAC,gCAAgC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,QAAQ,GAAI,iBAA8C,IAAI,gBAAgB,CAAC;IACrF,MAAM,KAAK,GAAG,YAAY,EAAE,KAAK,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACvF,OAAO,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AASD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAkB,EAClB,IAA6B,EAC7B,WAAyB,gBAAgB,EACzC,OAAwB;IAExB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACvF,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import type { CurrencyInput, Money, MoneyJSON } from '../money.js';
2
+ import { type DecimalColumnSize } from '../sql.js';
3
+ export { DEFAULT_DECIMAL_SIZE, type DecimalColumnSize } from '../sql.js';
4
+ /**
5
+ * A BIGINT column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
6
+ * `Money<C>`. Exact up to the column's limit of ±9.2·10^18 minor units. mysql2 returns BIGINT as a
7
+ * number by default, which is exact only below 2^53; beyond that it throws, so set
8
+ * `supportBigNumbers: true` (with `bigNumberStrings: true`) on the connection for larger amounts.
9
+ * Writing another currency, or a value at a scale other than the currency's, throws.
10
+ *
11
+ * total: moneyMinor('EUR')('total_minor').notNull()
12
+ */
13
+ export declare function moneyMinor<const C extends CurrencyInput>(currency: C): {
14
+ (): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
15
+ name: "";
16
+ dataType: "custom";
17
+ columnType: "MySqlCustomColumn";
18
+ data: Money<C>;
19
+ driverParam: string | number | bigint;
20
+ enumValues: undefined;
21
+ }>;
22
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
23
+ name: "";
24
+ dataType: "custom";
25
+ columnType: "MySqlCustomColumn";
26
+ data: Money<C>;
27
+ driverParam: string | number | bigint;
28
+ enumValues: undefined;
29
+ }>;
30
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
31
+ name: TName;
32
+ dataType: "custom";
33
+ columnType: "MySqlCustomColumn";
34
+ data: Money<C>;
35
+ driverParam: string | number | bigint;
36
+ enumValues: undefined;
37
+ }>;
38
+ };
39
+ /**
40
+ * A DECIMAL(precision, scale) column, DECIMAL(19,4) by default, read back as `Money<C>`. The driver
41
+ * must return DECIMAL as a string (mysql2's default; don't set `decimalNumbers`): a number has been
42
+ * through a float and throws. Writing a value the column could not hold unchanged throws (outside
43
+ * strict mode MySQL would clamp it), and so does a column scale below the currency's exponent.
44
+ *
45
+ * price: moneyDecimal('EUR', { precision: 19, scale: 4 })('price').notNull()
46
+ */
47
+ export declare function moneyDecimal<const C extends CurrencyInput>(currency: C, size?: DecimalColumnSize): {
48
+ (): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
49
+ name: "";
50
+ dataType: "custom";
51
+ columnType: "MySqlCustomColumn";
52
+ data: Money<C>;
53
+ driverParam: string;
54
+ enumValues: undefined;
55
+ }>;
56
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
57
+ name: "";
58
+ dataType: "custom";
59
+ columnType: "MySqlCustomColumn";
60
+ data: Money<C>;
61
+ driverParam: string;
62
+ enumValues: undefined;
63
+ }>;
64
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
65
+ name: TName;
66
+ dataType: "custom";
67
+ columnType: "MySqlCustomColumn";
68
+ data: Money<C>;
69
+ driverParam: string;
70
+ enumValues: undefined;
71
+ }>;
72
+ };
73
+ /**
74
+ * A JSON column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
75
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
76
+ *
77
+ * refund: moneyJson()('refund')
78
+ */
79
+ export declare function moneyJson<const C extends CurrencyInput = CurrencyInput>(currency?: C): {
80
+ (): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
81
+ name: "";
82
+ dataType: "custom";
83
+ columnType: "MySqlCustomColumn";
84
+ data: Money<C>;
85
+ driverParam: string | MoneyJSON<string>;
86
+ enumValues: undefined;
87
+ }>;
88
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
89
+ name: "";
90
+ dataType: "custom";
91
+ columnType: "MySqlCustomColumn";
92
+ data: Money<C>;
93
+ driverParam: string | MoneyJSON<string>;
94
+ enumValues: undefined;
95
+ }>;
96
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/mysql-core").MySqlCustomColumnBuilder<{
97
+ name: TName;
98
+ dataType: "custom";
99
+ columnType: "MySqlCustomColumn";
100
+ data: Money<C>;
101
+ driverParam: string | MoneyJSON<string>;
102
+ enumValues: undefined;
103
+ }>;
104
+ };
105
+ //# sourceMappingURL=mysql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/drizzle/mysql.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EASL,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEzE;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,QAAQ,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EACxD,QAAQ,EAAE,CAAC,EACX,IAAI,GAAE,iBAAwC;;;;;;;;;;;;;;;;;;;;;;;;;EAS/C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAOpF"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `@ducatjs/money/drizzle/mysql`: Drizzle ORM column types for MySQL and MariaDB (mysql2,
3
+ * PlanetScale). Selects return `Money`, inserts and updates accept it, and the currency is part of
4
+ * the column's type.
5
+ *
6
+ * import { mysqlTable } from 'drizzle-orm/mysql-core';
7
+ * import { moneyMinor } from '@ducatjs/money/drizzle/mysql';
8
+ *
9
+ * const orders = mysqlTable('orders', { total: moneyMinor('EUR')('total_minor').notNull() });
10
+ */
11
+ import { customType } from 'drizzle-orm/mysql-core';
12
+ import { checkDecimalSize, decimalFromDriver, decimalToDriver, DEFAULT_DECIMAL_SIZE, jsonFromDriver, jsonToDriver, minorFromDriver, minorToDriver, } from '../sql.js';
13
+ export { DEFAULT_DECIMAL_SIZE } from '../sql.js';
14
+ /**
15
+ * A BIGINT column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
16
+ * `Money<C>`. Exact up to the column's limit of ±9.2·10^18 minor units. mysql2 returns BIGINT as a
17
+ * number by default, which is exact only below 2^53; beyond that it throws, so set
18
+ * `supportBigNumbers: true` (with `bigNumberStrings: true`) on the connection for larger amounts.
19
+ * Writing another currency, or a value at a scale other than the currency's, throws.
20
+ *
21
+ * total: moneyMinor('EUR')('total_minor').notNull()
22
+ */
23
+ export function moneyMinor(currency) {
24
+ return customType({
25
+ dataType: () => 'bigint',
26
+ toDriver: (money) => minorToDriver(money, currency).toString(),
27
+ fromDriver: (value) => minorFromDriver(value, currency),
28
+ });
29
+ }
30
+ /**
31
+ * A DECIMAL(precision, scale) column, DECIMAL(19,4) by default, read back as `Money<C>`. The driver
32
+ * must return DECIMAL as a string (mysql2's default; don't set `decimalNumbers`): a number has been
33
+ * through a float and throws. Writing a value the column could not hold unchanged throws (outside
34
+ * strict mode MySQL would clamp it), and so does a column scale below the currency's exponent.
35
+ *
36
+ * price: moneyDecimal('EUR', { precision: 19, scale: 4 })('price').notNull()
37
+ */
38
+ export function moneyDecimal(currency, size = DEFAULT_DECIMAL_SIZE) {
39
+ checkDecimalSize(currency, size);
40
+ return customType({
41
+ dataType: () => `decimal(${size.precision}, ${size.scale})`,
42
+ toDriver: (money) => decimalToDriver(money, currency, size),
43
+ fromDriver: (value) => decimalFromDriver(value, currency),
44
+ });
45
+ }
46
+ /**
47
+ * A JSON column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
48
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
49
+ *
50
+ * refund: moneyJson()('refund')
51
+ */
52
+ export function moneyJson(currency) {
53
+ return customType({
54
+ dataType: () => 'json',
55
+ toDriver: (money) => jsonToDriver(money, currency),
56
+ // mysql2 parses JSON columns itself; other drivers may return the text
57
+ fromDriver: (value) => jsonFromDriver(value, currency),
58
+ });
59
+ }
60
+ //# sourceMappingURL=mysql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/drizzle/mysql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,oBAAoB,EAA0B,MAAM,WAAW,CAAC;AAEzE;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAgC,QAAW;IACnE,OAAO,UAAU,CAA2D;QAC1E,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ;QACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE;QAC9D,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC;KACxD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAW,EACX,OAA0B,oBAAoB;IAE9C,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAEjC,OAAO,UAAU,CAAyC;QACxD,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,KAAK,GAAG;QAC3D,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC;QAC3D,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAgD,QAAY;IACnF,OAAO,UAAU,CAAqD;QACpE,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;QACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC;QAClD,uEAAuE;QACvE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC;KACvD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,103 @@
1
+ import type { CurrencyInput, Money, MoneyJSON } from '../money.js';
2
+ import { type DecimalColumnSize } from '../sql.js';
3
+ export { DEFAULT_DECIMAL_SIZE, type DecimalColumnSize } from '../sql.js';
4
+ /**
5
+ * A BIGINT column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
6
+ * `Money<C>`. Exact up to the column's limit of ±9.2·10^18 minor units. Writing another currency, or
7
+ * a value at a scale other than the currency's, throws.
8
+ *
9
+ * total: moneyMinor('EUR')('total_minor').notNull()
10
+ */
11
+ export declare function moneyMinor<const C extends CurrencyInput>(currency: C): {
12
+ (): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
13
+ name: "";
14
+ dataType: "custom";
15
+ columnType: "PgCustomColumn";
16
+ data: Money<C>;
17
+ driverParam: string | number | bigint;
18
+ enumValues: undefined;
19
+ }>;
20
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
21
+ name: "";
22
+ dataType: "custom";
23
+ columnType: "PgCustomColumn";
24
+ data: Money<C>;
25
+ driverParam: string | number | bigint;
26
+ enumValues: undefined;
27
+ }>;
28
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
29
+ name: TName;
30
+ dataType: "custom";
31
+ columnType: "PgCustomColumn";
32
+ data: Money<C>;
33
+ driverParam: string | number | bigint;
34
+ enumValues: undefined;
35
+ }>;
36
+ };
37
+ /**
38
+ * A NUMERIC(precision, scale) column, NUMERIC(19,4) by default, read back as `Money<C>`. The
39
+ * driver must return NUMERIC as a string (node-postgres and postgres.js do); a number has been
40
+ * through a float and throws, as do `NaN` and `Infinity`. Writing a value the column could not hold
41
+ * unchanged throws, and so does a column scale below the currency's exponent.
42
+ *
43
+ * price: moneyDecimal('EUR', { precision: 19, scale: 4 })('price').notNull()
44
+ */
45
+ export declare function moneyDecimal<const C extends CurrencyInput>(currency: C, size?: DecimalColumnSize): {
46
+ (): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
47
+ name: "";
48
+ dataType: "custom";
49
+ columnType: "PgCustomColumn";
50
+ data: Money<C>;
51
+ driverParam: string;
52
+ enumValues: undefined;
53
+ }>;
54
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
55
+ name: "";
56
+ dataType: "custom";
57
+ columnType: "PgCustomColumn";
58
+ data: Money<C>;
59
+ driverParam: string;
60
+ enumValues: undefined;
61
+ }>;
62
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
63
+ name: TName;
64
+ dataType: "custom";
65
+ columnType: "PgCustomColumn";
66
+ data: Money<C>;
67
+ driverParam: string;
68
+ enumValues: undefined;
69
+ }>;
70
+ };
71
+ /**
72
+ * A JSONB column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
73
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
74
+ *
75
+ * refund: moneyJson()('refund')
76
+ */
77
+ export declare function moneyJson<const C extends CurrencyInput = CurrencyInput>(currency?: C): {
78
+ (): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
79
+ name: "";
80
+ dataType: "custom";
81
+ columnType: "PgCustomColumn";
82
+ data: Money<C>;
83
+ driverParam: string | MoneyJSON<string>;
84
+ enumValues: undefined;
85
+ }>;
86
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
87
+ name: "";
88
+ dataType: "custom";
89
+ columnType: "PgCustomColumn";
90
+ data: Money<C>;
91
+ driverParam: string | MoneyJSON<string>;
92
+ enumValues: undefined;
93
+ }>;
94
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/pg-core").PgCustomColumnBuilder<{
95
+ name: TName;
96
+ dataType: "custom";
97
+ columnType: "PgCustomColumn";
98
+ data: Money<C>;
99
+ driverParam: string | MoneyJSON<string>;
100
+ enumValues: undefined;
101
+ }>;
102
+ };
103
+ //# sourceMappingURL=pg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../src/drizzle/pg.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EASL,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEzE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,QAAQ,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAQpE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EACxD,QAAQ,EAAE,CAAC,EACX,IAAI,GAAE,iBAAwC;;;;;;;;;;;;;;;;;;;;;;;;;EAS/C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAOpF"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `@ducatjs/money/drizzle/pg`: Drizzle ORM column types for Postgres (node-postgres, postgres.js,
3
+ * PGlite, Neon). Selects return `Money`, inserts and updates accept it, and the currency is part of
4
+ * the column's type.
5
+ *
6
+ * import { pgTable } from 'drizzle-orm/pg-core';
7
+ * import { moneyMinor } from '@ducatjs/money/drizzle/pg';
8
+ *
9
+ * const orders = pgTable('orders', { total: moneyMinor('EUR')('total_minor').notNull() });
10
+ */
11
+ import { customType } from 'drizzle-orm/pg-core';
12
+ import { checkDecimalSize, decimalFromDriver, decimalToDriver, DEFAULT_DECIMAL_SIZE, jsonFromDriver, jsonToDriver, minorFromDriver, minorToDriver, } from '../sql.js';
13
+ export { DEFAULT_DECIMAL_SIZE } from '../sql.js';
14
+ /**
15
+ * A BIGINT column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
16
+ * `Money<C>`. Exact up to the column's limit of ±9.2·10^18 minor units. Writing another currency, or
17
+ * a value at a scale other than the currency's, throws.
18
+ *
19
+ * total: moneyMinor('EUR')('total_minor').notNull()
20
+ */
21
+ export function moneyMinor(currency) {
22
+ return customType({
23
+ dataType: () => 'bigint',
24
+ // a string, not a bigint: node-postgres cannot bind a bigint parameter
25
+ toDriver: (money) => minorToDriver(money, currency).toString(),
26
+ // node-postgres returns int8 as a string, postgres.js as a string or a bigint
27
+ fromDriver: (value) => minorFromDriver(value, currency),
28
+ });
29
+ }
30
+ /**
31
+ * A NUMERIC(precision, scale) column, NUMERIC(19,4) by default, read back as `Money<C>`. The
32
+ * driver must return NUMERIC as a string (node-postgres and postgres.js do); a number has been
33
+ * through a float and throws, as do `NaN` and `Infinity`. Writing a value the column could not hold
34
+ * unchanged throws, and so does a column scale below the currency's exponent.
35
+ *
36
+ * price: moneyDecimal('EUR', { precision: 19, scale: 4 })('price').notNull()
37
+ */
38
+ export function moneyDecimal(currency, size = DEFAULT_DECIMAL_SIZE) {
39
+ checkDecimalSize(currency, size);
40
+ return customType({
41
+ dataType: () => `numeric(${size.precision}, ${size.scale})`,
42
+ toDriver: (money) => decimalToDriver(money, currency, size),
43
+ fromDriver: (value) => decimalFromDriver(value, currency),
44
+ });
45
+ }
46
+ /**
47
+ * A JSONB column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
48
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
49
+ *
50
+ * refund: moneyJson()('refund')
51
+ */
52
+ export function moneyJson(currency) {
53
+ return customType({
54
+ dataType: () => 'jsonb',
55
+ toDriver: (money) => jsonToDriver(money, currency),
56
+ // node-postgres parses JSONB itself; other drivers may return the text
57
+ fromDriver: (value) => jsonFromDriver(value, currency),
58
+ });
59
+ }
60
+ //# sourceMappingURL=pg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.js","sourceRoot":"","sources":["../../src/drizzle/pg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,oBAAoB,EAA0B,MAAM,WAAW,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAgC,QAAW;IACnE,OAAO,UAAU,CAA2D;QAC1E,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ;QACxB,uEAAuE;QACvE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE;QAC9D,8EAA8E;QAC9E,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC;KACxD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAW,EACX,OAA0B,oBAAoB;IAE9C,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAEjC,OAAO,UAAU,CAAyC;QACxD,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,KAAK,GAAG;QAC3D,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC;QAC3D,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAgD,QAAY;IACnF,OAAO,UAAU,CAAqD;QACpE,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO;QACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC;QAClD,uEAAuE;QACvE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC;KACvD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,102 @@
1
+ import type { CurrencyInput, Money } from '../money.js';
2
+ /**
3
+ * An INTEGER column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
4
+ * `Money<C>`. Exact up to SQLite's limit of ±9.2·10^18 minor units. better-sqlite3 returns integers
5
+ * as numbers by default, which are exact only below 2^53; beyond that reading throws, so call
6
+ * `defaultSafeIntegers(true)` on the database for larger amounts. Writing another currency, or a
7
+ * value at a scale other than the currency's, throws.
8
+ *
9
+ * total: moneyMinor('EUR')('total_minor').notNull()
10
+ */
11
+ export declare function moneyMinor<const C extends CurrencyInput>(currency: C): {
12
+ (): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
13
+ name: "";
14
+ dataType: "custom";
15
+ columnType: "SQLiteCustomColumn";
16
+ data: Money<C>;
17
+ driverParam: number | bigint;
18
+ enumValues: undefined;
19
+ }>;
20
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
21
+ name: "";
22
+ dataType: "custom";
23
+ columnType: "SQLiteCustomColumn";
24
+ data: Money<C>;
25
+ driverParam: number | bigint;
26
+ enumValues: undefined;
27
+ }>;
28
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
29
+ name: TName;
30
+ dataType: "custom";
31
+ columnType: "SQLiteCustomColumn";
32
+ data: Money<C>;
33
+ driverParam: number | bigint;
34
+ enumValues: undefined;
35
+ }>;
36
+ };
37
+ /**
38
+ * A TEXT column holding the exact decimal string (`12.34`), read back as `Money<C>`. SQLite's
39
+ * NUMERIC affinity would store some decimals as REAL and lose digits, so they are kept as text.
40
+ * Writing another currency, or a value at a scale other than the currency's, throws.
41
+ *
42
+ * price: moneyDecimal('EUR')('price').notNull()
43
+ */
44
+ export declare function moneyDecimal<const C extends CurrencyInput>(currency: C): {
45
+ (): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
46
+ name: "";
47
+ dataType: "custom";
48
+ columnType: "SQLiteCustomColumn";
49
+ data: Money<C>;
50
+ driverParam: string;
51
+ enumValues: undefined;
52
+ }>;
53
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
54
+ name: "";
55
+ dataType: "custom";
56
+ columnType: "SQLiteCustomColumn";
57
+ data: Money<C>;
58
+ driverParam: string;
59
+ enumValues: undefined;
60
+ }>;
61
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
62
+ name: TName;
63
+ dataType: "custom";
64
+ columnType: "SQLiteCustomColumn";
65
+ data: Money<C>;
66
+ driverParam: string;
67
+ enumValues: undefined;
68
+ }>;
69
+ };
70
+ /**
71
+ * A TEXT column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
72
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
73
+ *
74
+ * refund: moneyJson()('refund')
75
+ */
76
+ export declare function moneyJson<const C extends CurrencyInput = CurrencyInput>(currency?: C): {
77
+ (): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
78
+ name: "";
79
+ dataType: "custom";
80
+ columnType: "SQLiteCustomColumn";
81
+ data: Money<C>;
82
+ driverParam: string;
83
+ enumValues: undefined;
84
+ }>;
85
+ <TConfig extends Record<string, any>>(fieldConfig?: TConfig | undefined): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
86
+ name: "";
87
+ dataType: "custom";
88
+ columnType: "SQLiteCustomColumn";
89
+ data: Money<C>;
90
+ driverParam: string;
91
+ enumValues: undefined;
92
+ }>;
93
+ <TName extends string>(dbName: TName, fieldConfig?: unknown): import("drizzle-orm/sqlite-core").SQLiteCustomColumnBuilder<{
94
+ name: TName;
95
+ dataType: "custom";
96
+ columnType: "SQLiteCustomColumn";
97
+ data: Money<C>;
98
+ driverParam: string;
99
+ enumValues: undefined;
100
+ }>;
101
+ };
102
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/drizzle/sqlite.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAUxD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,QAAQ,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAMpE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,QAAQ,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAStE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAMpF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `@ducatjs/money/drizzle/sqlite`: Drizzle ORM column types for SQLite (better-sqlite3, libSQL,
3
+ * Bun). Selects return `Money`, inserts and updates accept it, and the currency is part of the
4
+ * column's type.
5
+ *
6
+ * import { sqliteTable } from 'drizzle-orm/sqlite-core';
7
+ * import { moneyMinor } from '@ducatjs/money/drizzle/sqlite';
8
+ *
9
+ * const orders = sqliteTable('orders', { total: moneyMinor('EUR')('total_minor').notNull() });
10
+ */
11
+ import { customType } from 'drizzle-orm/sqlite-core';
12
+ import { currencyExponent } from '../currency.js';
13
+ import { decimalFromDriver, decimalToDriver, jsonFromDriver, jsonToDriver, minorFromDriver, minorToDriver, } from '../sql.js';
14
+ /**
15
+ * An INTEGER column of minor units in a fixed currency (`1234` is 12.34 EUR), read back as
16
+ * `Money<C>`. Exact up to SQLite's limit of ±9.2·10^18 minor units. better-sqlite3 returns integers
17
+ * as numbers by default, which are exact only below 2^53; beyond that reading throws, so call
18
+ * `defaultSafeIntegers(true)` on the database for larger amounts. Writing another currency, or a
19
+ * value at a scale other than the currency's, throws.
20
+ *
21
+ * total: moneyMinor('EUR')('total_minor').notNull()
22
+ */
23
+ export function moneyMinor(currency) {
24
+ return customType({
25
+ dataType: () => 'integer',
26
+ toDriver: (money) => minorToDriver(money, currency),
27
+ fromDriver: (value) => minorFromDriver(value, currency),
28
+ });
29
+ }
30
+ /**
31
+ * A TEXT column holding the exact decimal string (`12.34`), read back as `Money<C>`. SQLite's
32
+ * NUMERIC affinity would store some decimals as REAL and lose digits, so they are kept as text.
33
+ * Writing another currency, or a value at a scale other than the currency's, throws.
34
+ *
35
+ * price: moneyDecimal('EUR')('price').notNull()
36
+ */
37
+ export function moneyDecimal(currency) {
38
+ // fail at the schema definition, not on the first query, for an unknown currency
39
+ currencyExponent(currency);
40
+ return customType({
41
+ dataType: () => 'text',
42
+ toDriver: (money) => decimalToDriver(money, currency, undefined),
43
+ fromDriver: (value) => decimalFromDriver(value, currency),
44
+ });
45
+ }
46
+ /**
47
+ * A TEXT column holding `{"amount":"12.34","currency":"EUR"}`, with the currency in each value.
48
+ * Pass a currency to fix it: then a value in another currency throws, on write and on read.
49
+ *
50
+ * refund: moneyJson()('refund')
51
+ */
52
+ export function moneyJson(currency) {
53
+ return customType({
54
+ dataType: () => 'text',
55
+ toDriver: (money) => jsonToDriver(money, currency),
56
+ fromDriver: (value) => jsonFromDriver(value, currency),
57
+ });
58
+ }
59
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/drizzle/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,WAAW,CAAC;AAEnB;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAgC,QAAW;IACnE,OAAO,UAAU,CAAkD;QACjE,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;QACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC;QACnD,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC;KACxD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAgC,QAAW;IACrE,iFAAiF;IACjF,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE3B,OAAO,UAAU,CAAyC;QACxD,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;QACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;QAChE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAgD,QAAY;IACnF,OAAO,UAAU,CAAyC;QACxD,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;QACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC;QAClD,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC;KACvD,CAAC,CAAC;AACL,CAAC"}
package/dist/ecb.d.ts CHANGED
@@ -10,8 +10,43 @@ import { type RateTable } from './provider.js';
10
10
  export declare function parseEcbXml(xml: string): RateTable[];
11
11
  /**
12
12
  * Parses eurofxref.csv or eurofxref-hist.csv (from the ECB's zips) the way parseEcbXml does.
13
- * 'N/A' and blank cells (currencies not quoted that day) are skipped, and a day with no rates at
14
- * all is left out, so a lookback goes on to the day before.
13
+ * 'N/A' and blank cells (currencies not quoted that day) are listed in the table's `missing`, and a
14
+ * day with no rates at all is left out, so a lookback goes on to the day before.
15
15
  */
16
16
  export declare function parseEcbCsv(csv: string): RateTable[];
17
+ /** Options for parseEcbSdmxCsv. */
18
+ export interface EcbSdmxOptions {
19
+ /**
20
+ * The decimals each currency is published with, for a file without the DECIMALS column (as
21
+ * fetched with `detail=dataonly`). A DECIMALS column in the file takes precedence.
22
+ */
23
+ readonly decimals?: Readonly<Record<string, number>>;
24
+ }
25
+ /**
26
+ * The DECIMALS of each series in an ECB SDMX-CSV file: the data file itself with full detail, or
27
+ * the series file the API returns with `detail=nodata`.
28
+ */
29
+ export declare function parseEcbSdmxDecimals(csv: string): Record<string, number>;
30
+ /**
31
+ * Parses the ECB Data Portal's SDMX-CSV (`format=csvdata`) for the daily euro reference rates
32
+ * (dataflow EXR, key `D.<currencies>.EUR.SP00.A`) into one EUR-based table per day, newest first,
33
+ * like parseEcbXml. Any date range back to 1999 comes in one file.
34
+ *
35
+ * The API strips trailing zeros ('136.8' for the published 136.80), so the published digits are
36
+ * rebuilt from each series' DECIMALS attribute: in the file with full detail, or from `decimals`
37
+ * (see parseEcbSdmxDecimals) for a `detail=dataonly` file. Two series overstate it (THB and LTL),
38
+ * and are padded only to the decimals the ECB actually published. Without DECIMALS, the digits
39
+ * stay as the file gives them; the values are exact either way. An empty or `NaN` value is a missing value.
40
+ * A row for another frequency, rate type or base currency, or with a UNIT_MULT other than 0,
41
+ * throws SyntaxError rather than being read as a daily rate. Discontinued series simply end, so
42
+ * the tables of their last days include them.
43
+ *
44
+ * No `availableAt` is set, as with parseEcbXml: the API gives no publication time, and the ECB
45
+ * publishes at about 16:00 CET. So a backtest that asks for 10:00 CET on a day still gets that
46
+ * day's rate; ask for the day before if that matters.
47
+ *
48
+ * const tables = parseEcbSdmxCsv(await (await fetch(url)).text());
49
+ * const history = rateHistory(tables); // from @ducatjs/money/convert/history
50
+ */
51
+ export declare function parseEcbSdmxCsv(csv: string, options?: EcbSdmxOptions): RateTable[];
17
52
  //# sourceMappingURL=ecb.d.ts.map
package/dist/ecb.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ecb.d.ts","sourceRoot":"","sources":["../src/ecb.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAuE1D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBpD;AAiCD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CA0BpD"}
1
+ {"version":3,"file":"ecb.d.ts","sourceRoot":"","sources":["../src/ecb.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAoE1D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBpD;AAiCD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CA+BpD;AASD,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD;AA+CD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxE;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,EAAE,CAwDlF"}