@ducatjs/money 0.0.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 (398) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +51 -0
  3. package/README.md +1034 -3
  4. package/assets/CREDITS.md +12 -0
  5. package/data/adyen-fx.json +19 -0
  6. package/data/adyen.json +171 -0
  7. package/data/braintree.json +223 -0
  8. package/data/cash-rounding.json +520 -0
  9. package/data/checkout.json +230 -0
  10. package/data/cldr-cash.json +101 -0
  11. package/data/historic.json +78 -0
  12. package/data/iso4217-list-one.xml +1956 -0
  13. package/data/iso4217-list-three.xml +1185 -0
  14. package/data/klarna.json +95 -0
  15. package/data/paypal.json +65 -0
  16. package/data/stripe-fx.json +17 -0
  17. package/data/stripe.json +285 -0
  18. package/dist/adyen-fx.d.ts +25 -0
  19. package/dist/adyen-fx.d.ts.map +1 -0
  20. package/dist/adyen-fx.js +140 -0
  21. package/dist/adyen-fx.js.map +1 -0
  22. package/dist/adyen.d.ts +25 -0
  23. package/dist/adyen.d.ts.map +1 -0
  24. package/dist/adyen.js +34 -0
  25. package/dist/adyen.js.map +1 -0
  26. package/dist/allocate.d.ts +72 -0
  27. package/dist/allocate.d.ts.map +1 -0
  28. package/dist/allocate.js +314 -0
  29. package/dist/allocate.js.map +1 -0
  30. package/dist/bag.d.ts +58 -0
  31. package/dist/bag.d.ts.map +1 -0
  32. package/dist/bag.js +122 -0
  33. package/dist/bag.js.map +1 -0
  34. package/dist/boc.d.ts +31 -0
  35. package/dist/boc.d.ts.map +1 -0
  36. package/dist/boc.js +114 -0
  37. package/dist/boc.js.map +1 -0
  38. package/dist/boe.d.ts +33 -0
  39. package/dist/boe.d.ts.map +1 -0
  40. package/dist/boe.js +114 -0
  41. package/dist/boe.js.map +1 -0
  42. package/dist/braintree.d.ts +34 -0
  43. package/dist/braintree.d.ts.map +1 -0
  44. package/dist/braintree.js +45 -0
  45. package/dist/braintree.js.map +1 -0
  46. package/dist/cash.d.ts +64 -0
  47. package/dist/cash.d.ts.map +1 -0
  48. package/dist/cash.js +134 -0
  49. package/dist/cash.js.map +1 -0
  50. package/dist/checkout.d.ts +42 -0
  51. package/dist/checkout.d.ts.map +1 -0
  52. package/dist/checkout.js +52 -0
  53. package/dist/checkout.js.map +1 -0
  54. package/dist/convert.d.ts +52 -0
  55. package/dist/convert.d.ts.map +1 -0
  56. package/dist/convert.js +65 -0
  57. package/dist/convert.js.map +1 -0
  58. package/dist/currency.d.ts +22 -0
  59. package/dist/currency.d.ts.map +1 -0
  60. package/dist/currency.js +38 -0
  61. package/dist/currency.js.map +1 -0
  62. package/dist/decimal.d.ts +52 -0
  63. package/dist/decimal.d.ts.map +1 -0
  64. package/dist/decimal.js +251 -0
  65. package/dist/decimal.js.map +1 -0
  66. package/dist/drizzle/mysql.d.ts +105 -0
  67. package/dist/drizzle/mysql.d.ts.map +1 -0
  68. package/dist/drizzle/mysql.js +60 -0
  69. package/dist/drizzle/mysql.js.map +1 -0
  70. package/dist/drizzle/pg.d.ts +103 -0
  71. package/dist/drizzle/pg.d.ts.map +1 -0
  72. package/dist/drizzle/pg.js +60 -0
  73. package/dist/drizzle/pg.js.map +1 -0
  74. package/dist/drizzle/sqlite.d.ts +102 -0
  75. package/dist/drizzle/sqlite.d.ts.map +1 -0
  76. package/dist/drizzle/sqlite.js +59 -0
  77. package/dist/drizzle/sqlite.js.map +1 -0
  78. package/dist/ecb.d.ts +52 -0
  79. package/dist/ecb.d.ts.map +1 -0
  80. package/dist/ecb.js +285 -0
  81. package/dist/ecb.js.map +1 -0
  82. package/dist/exact.d.ts +62 -0
  83. package/dist/exact.d.ts.map +1 -0
  84. package/dist/exact.js +147 -0
  85. package/dist/exact.js.map +1 -0
  86. package/dist/fed.d.ts +35 -0
  87. package/dist/fed.d.ts.map +1 -0
  88. package/dist/fed.js +134 -0
  89. package/dist/fed.js.map +1 -0
  90. package/dist/fetch.d.ts +103 -0
  91. package/dist/fetch.d.ts.map +1 -0
  92. package/dist/fetch.js +222 -0
  93. package/dist/fetch.js.map +1 -0
  94. package/dist/fixed.d.ts +121 -0
  95. package/dist/fixed.d.ts.map +1 -0
  96. package/dist/fixed.js +420 -0
  97. package/dist/fixed.js.map +1 -0
  98. package/dist/fn.d.ts +34 -0
  99. package/dist/fn.d.ts.map +1 -0
  100. package/dist/fn.js +37 -0
  101. package/dist/fn.js.map +1 -0
  102. package/dist/format.d.ts +13 -0
  103. package/dist/format.d.ts.map +1 -0
  104. package/dist/format.js +90 -0
  105. package/dist/format.js.map +1 -0
  106. package/dist/generated/adyen.d.ts +3 -0
  107. package/dist/generated/adyen.d.ts.map +1 -0
  108. package/dist/generated/adyen.js +144 -0
  109. package/dist/generated/adyen.js.map +1 -0
  110. package/dist/generated/braintree.d.ts +3 -0
  111. package/dist/generated/braintree.d.ts.map +1 -0
  112. package/dist/generated/braintree.js +140 -0
  113. package/dist/generated/braintree.js.map +1 -0
  114. package/dist/generated/cash.d.ts +14 -0
  115. package/dist/generated/cash.d.ts.map +1 -0
  116. package/dist/generated/cash.js +465 -0
  117. package/dist/generated/cash.js.map +1 -0
  118. package/dist/generated/checkout.d.ts +3 -0
  119. package/dist/generated/checkout.d.ts.map +1 -0
  120. package/dist/generated/checkout.js +151 -0
  121. package/dist/generated/checkout.js.map +1 -0
  122. package/dist/generated/historic.d.ts +337 -0
  123. package/dist/generated/historic.d.ts.map +1 -0
  124. package/dist/generated/historic.js +66 -0
  125. package/dist/generated/historic.js.map +1 -0
  126. package/dist/generated/iso4217.d.ts +174 -0
  127. package/dist/generated/iso4217.d.ts.map +1 -0
  128. package/dist/generated/iso4217.js +175 -0
  129. package/dist/generated/iso4217.js.map +1 -0
  130. package/dist/generated/kernel.d.ts +17 -0
  131. package/dist/generated/kernel.d.ts.map +1 -0
  132. package/dist/generated/kernel.js +208 -0
  133. package/dist/generated/kernel.js.map +1 -0
  134. package/dist/generated/klarna.d.ts +3 -0
  135. package/dist/generated/klarna.d.ts.map +1 -0
  136. package/dist/generated/klarna.js +21 -0
  137. package/dist/generated/klarna.js.map +1 -0
  138. package/dist/generated/paypal.d.ts +3 -0
  139. package/dist/generated/paypal.d.ts.map +1 -0
  140. package/dist/generated/paypal.js +31 -0
  141. package/dist/generated/paypal.js.map +1 -0
  142. package/dist/generated/stripe.d.ts +8 -0
  143. package/dist/generated/stripe.d.ts.map +1 -0
  144. package/dist/generated/stripe.js +150 -0
  145. package/dist/generated/stripe.js.map +1 -0
  146. package/dist/historic.d.ts +40 -0
  147. package/dist/historic.d.ts.map +1 -0
  148. package/dist/historic.js +43 -0
  149. package/dist/historic.js.map +1 -0
  150. package/dist/history.d.ts +96 -0
  151. package/dist/history.d.ts.map +1 -0
  152. package/dist/history.js +213 -0
  153. package/dist/history.js.map +1 -0
  154. package/dist/hmrc.d.ts +28 -0
  155. package/dist/hmrc.d.ts.map +1 -0
  156. package/dist/hmrc.js +108 -0
  157. package/dist/hmrc.js.map +1 -0
  158. package/dist/index.d.ts +11 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +11 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/klarna.d.ts +31 -0
  163. package/dist/klarna.d.ts.map +1 -0
  164. package/dist/klarna.js +38 -0
  165. package/dist/klarna.js.map +1 -0
  166. package/dist/kysely.d.ts +120 -0
  167. package/dist/kysely.d.ts.map +1 -0
  168. package/dist/kysely.js +309 -0
  169. package/dist/kysely.js.map +1 -0
  170. package/dist/money.d.ts +302 -0
  171. package/dist/money.d.ts.map +1 -0
  172. package/dist/money.js +703 -0
  173. package/dist/money.js.map +1 -0
  174. package/dist/parse.d.ts +55 -0
  175. package/dist/parse.d.ts.map +1 -0
  176. package/dist/parse.js +419 -0
  177. package/dist/parse.js.map +1 -0
  178. package/dist/paypal.d.ts +41 -0
  179. package/dist/paypal.d.ts.map +1 -0
  180. package/dist/paypal.js +58 -0
  181. package/dist/paypal.js.map +1 -0
  182. package/dist/pg.d.ts +100 -0
  183. package/dist/pg.d.ts.map +1 -0
  184. package/dist/pg.js +343 -0
  185. package/dist/pg.js.map +1 -0
  186. package/dist/plugins/adyen.d.ts +15 -0
  187. package/dist/plugins/adyen.d.ts.map +1 -0
  188. package/dist/plugins/adyen.js +10 -0
  189. package/dist/plugins/adyen.js.map +1 -0
  190. package/dist/plugins/all.d.ts +29 -0
  191. package/dist/plugins/all.d.ts.map +1 -0
  192. package/dist/plugins/all.js +30 -0
  193. package/dist/plugins/all.js.map +1 -0
  194. package/dist/plugins/allocate.d.ts +20 -0
  195. package/dist/plugins/allocate.d.ts.map +1 -0
  196. package/dist/plugins/allocate.js +26 -0
  197. package/dist/plugins/allocate.js.map +1 -0
  198. package/dist/plugins/braintree.d.ts +12 -0
  199. package/dist/plugins/braintree.d.ts.map +1 -0
  200. package/dist/plugins/braintree.js +12 -0
  201. package/dist/plugins/braintree.js.map +1 -0
  202. package/dist/plugins/cash.d.ts +19 -0
  203. package/dist/plugins/cash.d.ts.map +1 -0
  204. package/dist/plugins/cash.js +16 -0
  205. package/dist/plugins/cash.js.map +1 -0
  206. package/dist/plugins/checkout.d.ts +21 -0
  207. package/dist/plugins/checkout.d.ts.map +1 -0
  208. package/dist/plugins/checkout.js +16 -0
  209. package/dist/plugins/checkout.js.map +1 -0
  210. package/dist/plugins/convert.d.ts +19 -0
  211. package/dist/plugins/convert.d.ts.map +1 -0
  212. package/dist/plugins/convert.js +13 -0
  213. package/dist/plugins/convert.js.map +1 -0
  214. package/dist/plugins/exact.d.ts +15 -0
  215. package/dist/plugins/exact.d.ts.map +1 -0
  216. package/dist/plugins/exact.js +13 -0
  217. package/dist/plugins/exact.js.map +1 -0
  218. package/dist/plugins/fixed.d.ts +17 -0
  219. package/dist/plugins/fixed.d.ts.map +1 -0
  220. package/dist/plugins/fixed.js +13 -0
  221. package/dist/plugins/fixed.js.map +1 -0
  222. package/dist/plugins/format.d.ts +9 -0
  223. package/dist/plugins/format.d.ts.map +1 -0
  224. package/dist/plugins/format.js +16 -0
  225. package/dist/plugins/format.js.map +1 -0
  226. package/dist/plugins/klarna.d.ts +10 -0
  227. package/dist/plugins/klarna.d.ts.map +1 -0
  228. package/dist/plugins/klarna.js +10 -0
  229. package/dist/plugins/klarna.js.map +1 -0
  230. package/dist/plugins/paypal.d.ts +14 -0
  231. package/dist/plugins/paypal.d.ts.map +1 -0
  232. package/dist/plugins/paypal.js +16 -0
  233. package/dist/plugins/paypal.js.map +1 -0
  234. package/dist/plugins/prisma.d.ts +8 -0
  235. package/dist/plugins/prisma.d.ts.map +1 -0
  236. package/dist/plugins/prisma.js +13 -0
  237. package/dist/plugins/prisma.js.map +1 -0
  238. package/dist/plugins/stripe.d.ts +14 -0
  239. package/dist/plugins/stripe.d.ts.map +1 -0
  240. package/dist/plugins/stripe.js +16 -0
  241. package/dist/plugins/stripe.js.map +1 -0
  242. package/dist/plugins/tax.d.ts +20 -0
  243. package/dist/plugins/tax.d.ts.map +1 -0
  244. package/dist/plugins/tax.js +18 -0
  245. package/dist/plugins/tax.js.map +1 -0
  246. package/dist/policy.d.ts +34 -0
  247. package/dist/policy.d.ts.map +1 -0
  248. package/dist/policy.js +90 -0
  249. package/dist/policy.js.map +1 -0
  250. package/dist/prisma.d.ts +77 -0
  251. package/dist/prisma.d.ts.map +1 -0
  252. package/dist/prisma.js +76 -0
  253. package/dist/prisma.js.map +1 -0
  254. package/dist/processor.d.ts +28 -0
  255. package/dist/processor.d.ts.map +1 -0
  256. package/dist/processor.js +118 -0
  257. package/dist/processor.js.map +1 -0
  258. package/dist/provider.d.ts +103 -0
  259. package/dist/provider.d.ts.map +1 -0
  260. package/dist/provider.js +280 -0
  261. package/dist/provider.js.map +1 -0
  262. package/dist/rate-text.d.ts +38 -0
  263. package/dist/rate-text.d.ts.map +1 -0
  264. package/dist/rate-text.js +143 -0
  265. package/dist/rate-text.js.map +1 -0
  266. package/dist/rate.d.ts +175 -0
  267. package/dist/rate.d.ts.map +1 -0
  268. package/dist/rate.js +371 -0
  269. package/dist/rate.js.map +1 -0
  270. package/dist/rounding-error.d.ts +9 -0
  271. package/dist/rounding-error.d.ts.map +1 -0
  272. package/dist/rounding-error.js +9 -0
  273. package/dist/rounding-error.js.map +1 -0
  274. package/dist/rounding.d.ts +50 -0
  275. package/dist/rounding.d.ts.map +1 -0
  276. package/dist/rounding.js +87 -0
  277. package/dist/rounding.js.map +1 -0
  278. package/dist/schema.d.ts +43 -0
  279. package/dist/schema.d.ts.map +1 -0
  280. package/dist/schema.js +77 -0
  281. package/dist/schema.js.map +1 -0
  282. package/dist/sql.d.ts +54 -0
  283. package/dist/sql.d.ts.map +1 -0
  284. package/dist/sql.js +131 -0
  285. package/dist/sql.js.map +1 -0
  286. package/dist/stripe-fx.d.ts +22 -0
  287. package/dist/stripe-fx.d.ts.map +1 -0
  288. package/dist/stripe-fx.js +30 -0
  289. package/dist/stripe-fx.js.map +1 -0
  290. package/dist/stripe.d.ts +36 -0
  291. package/dist/stripe.d.ts.map +1 -0
  292. package/dist/stripe.js +39 -0
  293. package/dist/stripe.js.map +1 -0
  294. package/dist/tax.d.ts +33 -0
  295. package/dist/tax.d.ts.map +1 -0
  296. package/dist/tax.js +55 -0
  297. package/dist/tax.js.map +1 -0
  298. package/dist/testing/arbitraries.d.ts +43 -0
  299. package/dist/testing/arbitraries.d.ts.map +1 -0
  300. package/dist/testing/arbitraries.js +98 -0
  301. package/dist/testing/arbitraries.js.map +1 -0
  302. package/dist/testing/index.d.ts +67 -0
  303. package/dist/testing/index.d.ts.map +1 -0
  304. package/dist/testing/index.js +159 -0
  305. package/dist/testing/index.js.map +1 -0
  306. package/dist/testing/jest.d.ts +2 -0
  307. package/dist/testing/jest.d.ts.map +1 -0
  308. package/dist/testing/jest.js +15 -0
  309. package/dist/testing/jest.js.map +1 -0
  310. package/dist/testing/vitest.d.ts +7 -0
  311. package/dist/testing/vitest.d.ts.map +1 -0
  312. package/dist/testing/vitest.js +12 -0
  313. package/dist/testing/vitest.js.map +1 -0
  314. package/dist/valibot.d.ts +33 -0
  315. package/dist/valibot.d.ts.map +1 -0
  316. package/dist/valibot.js +61 -0
  317. package/dist/valibot.js.map +1 -0
  318. package/dist/zod.d.ts +36 -0
  319. package/dist/zod.d.ts.map +1 -0
  320. package/dist/zod.js +58 -0
  321. package/dist/zod.js.map +1 -0
  322. package/package.json +280 -5
  323. package/src/adyen-fx.ts +175 -0
  324. package/src/adyen.ts +46 -0
  325. package/src/allocate.ts +393 -0
  326. package/src/bag.ts +170 -0
  327. package/src/boc.ts +136 -0
  328. package/src/boe.ts +131 -0
  329. package/src/braintree.ts +71 -0
  330. package/src/cash.ts +183 -0
  331. package/src/checkout.ts +77 -0
  332. package/src/convert.ts +177 -0
  333. package/src/currency.ts +61 -0
  334. package/src/decimal.ts +283 -0
  335. package/src/drizzle/mysql.ts +78 -0
  336. package/src/drizzle/pg.ts +78 -0
  337. package/src/drizzle/sqlite.ts +70 -0
  338. package/src/ecb.ts +328 -0
  339. package/src/exact.ts +182 -0
  340. package/src/fed.ts +146 -0
  341. package/src/fetch.ts +306 -0
  342. package/src/fixed.ts +558 -0
  343. package/src/fn.ts +94 -0
  344. package/src/format.ts +106 -0
  345. package/src/generated/adyen.ts +144 -0
  346. package/src/generated/braintree.ts +140 -0
  347. package/src/generated/cash.ts +478 -0
  348. package/src/generated/checkout.ts +151 -0
  349. package/src/generated/historic.ts +67 -0
  350. package/src/generated/iso4217.ts +179 -0
  351. package/src/generated/kernel.ts +230 -0
  352. package/src/generated/klarna.ts +21 -0
  353. package/src/generated/paypal.ts +31 -0
  354. package/src/generated/stripe.ts +150 -0
  355. package/src/historic.ts +77 -0
  356. package/src/history.ts +333 -0
  357. package/src/hmrc.ts +125 -0
  358. package/src/index.ts +41 -0
  359. package/src/klarna.ts +54 -0
  360. package/src/kysely.ts +588 -0
  361. package/src/money.ts +979 -0
  362. package/src/parse.ts +511 -0
  363. package/src/paypal.ts +93 -0
  364. package/src/pg.ts +410 -0
  365. package/src/plugins/adyen.ts +25 -0
  366. package/src/plugins/all.ts +57 -0
  367. package/src/plugins/allocate.ts +53 -0
  368. package/src/plugins/braintree.ts +23 -0
  369. package/src/plugins/cash.ts +33 -0
  370. package/src/plugins/checkout.ts +32 -0
  371. package/src/plugins/convert.ts +49 -0
  372. package/src/plugins/exact.ts +23 -0
  373. package/src/plugins/fixed.ts +28 -0
  374. package/src/plugins/format.ts +28 -0
  375. package/src/plugins/klarna.ts +21 -0
  376. package/src/plugins/paypal.ts +29 -0
  377. package/src/plugins/prisma.ts +24 -0
  378. package/src/plugins/stripe.ts +29 -0
  379. package/src/plugins/tax.ts +40 -0
  380. package/src/policy.ts +124 -0
  381. package/src/prisma.ts +199 -0
  382. package/src/processor.ts +181 -0
  383. package/src/provider.ts +389 -0
  384. package/src/rate-text.ts +151 -0
  385. package/src/rate.ts +546 -0
  386. package/src/rounding-error.ts +8 -0
  387. package/src/rounding.ts +122 -0
  388. package/src/schema.ts +119 -0
  389. package/src/sql.ts +178 -0
  390. package/src/stripe-fx.ts +49 -0
  391. package/src/stripe.ts +69 -0
  392. package/src/tax.ts +102 -0
  393. package/src/testing/arbitraries.ts +134 -0
  394. package/src/testing/index.ts +247 -0
  395. package/src/testing/jest.ts +18 -0
  396. package/src/testing/vitest.ts +18 -0
  397. package/src/valibot.ts +87 -0
  398. package/src/zod.ts +78 -0
package/package.json CHANGED
@@ -1,9 +1,284 @@
1
1
  {
2
2
  "name": "@ducatjs/money",
3
- "version": "0.0.0",
4
- "description": "Exact, fast, typed money for TypeScript (in development; not usable yet)",
5
- "repository": { "type": "git", "url": "git+https://github.com/public/ducat.git" },
6
- "homepage": "https://github.com/public/ducat",
3
+ "version": "0.2.0",
4
+ "description": "Exact, fast, typed Money for TypeScript: integer minor units, bigint fallback, Stripe/Adyen views, allocation, cash rounding, Prisma helpers.",
5
+ "homepage": "https://github.com/public/ducat#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/public/ducat/issues"
8
+ },
7
9
  "license": "MIT",
8
- "files": ["README.md"]
10
+ "author": "Alex Stapleton <alexs@prol.etari.at>",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/public/ducat.git"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src",
18
+ "data",
19
+ "assets/CREDITS.md",
20
+ "NOTICE",
21
+ "LICENSE"
22
+ ],
23
+ "type": "module",
24
+ "sideEffects": [
25
+ "./dist/plugins/*.js",
26
+ "./src/plugins/*.ts",
27
+ "./dist/testing/vitest.js",
28
+ "./dist/testing/jest.js",
29
+ "./src/testing/vitest.ts",
30
+ "./src/testing/jest.ts"
31
+ ],
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "./fn": {
38
+ "types": "./dist/fn.d.ts",
39
+ "default": "./dist/fn.js"
40
+ },
41
+ "./allocate": {
42
+ "types": "./dist/plugins/allocate.d.ts",
43
+ "default": "./dist/plugins/allocate.js"
44
+ },
45
+ "./tax": {
46
+ "types": "./dist/plugins/tax.d.ts",
47
+ "default": "./dist/plugins/tax.js"
48
+ },
49
+ "./convert": {
50
+ "types": "./dist/plugins/convert.d.ts",
51
+ "default": "./dist/plugins/convert.js"
52
+ },
53
+ "./convert/ecb": {
54
+ "types": "./dist/ecb.d.ts",
55
+ "default": "./dist/ecb.js"
56
+ },
57
+ "./convert/history": {
58
+ "types": "./dist/history.d.ts",
59
+ "default": "./dist/history.js"
60
+ },
61
+ "./convert/boc": {
62
+ "types": "./dist/boc.d.ts",
63
+ "default": "./dist/boc.js"
64
+ },
65
+ "./convert/fed": {
66
+ "types": "./dist/fed.d.ts",
67
+ "default": "./dist/fed.js"
68
+ },
69
+ "./historic": {
70
+ "types": "./dist/historic.d.ts",
71
+ "default": "./dist/historic.js"
72
+ },
73
+ "./convert/boe": {
74
+ "types": "./dist/boe.d.ts",
75
+ "default": "./dist/boe.js"
76
+ },
77
+ "./convert/hmrc": {
78
+ "types": "./dist/hmrc.d.ts",
79
+ "default": "./dist/hmrc.js"
80
+ },
81
+ "./convert/fetch": {
82
+ "types": "./dist/fetch.d.ts",
83
+ "default": "./dist/fetch.js"
84
+ },
85
+ "./exact": {
86
+ "types": "./dist/plugins/exact.d.ts",
87
+ "default": "./dist/plugins/exact.js"
88
+ },
89
+ "./policy": {
90
+ "types": "./dist/policy.d.ts",
91
+ "default": "./dist/policy.js"
92
+ },
93
+ "./cash": {
94
+ "types": "./dist/plugins/cash.d.ts",
95
+ "default": "./dist/plugins/cash.js"
96
+ },
97
+ "./format": {
98
+ "types": "./dist/plugins/format.d.ts",
99
+ "default": "./dist/plugins/format.js"
100
+ },
101
+ "./fixed": {
102
+ "types": "./dist/plugins/fixed.d.ts",
103
+ "default": "./dist/plugins/fixed.js"
104
+ },
105
+ "./parse": {
106
+ "types": "./dist/parse.d.ts",
107
+ "default": "./dist/parse.js"
108
+ },
109
+ "./stripe": {
110
+ "types": "./dist/plugins/stripe.d.ts",
111
+ "default": "./dist/plugins/stripe.js"
112
+ },
113
+ "./adyen": {
114
+ "types": "./dist/plugins/adyen.d.ts",
115
+ "default": "./dist/plugins/adyen.js"
116
+ },
117
+ "./checkout": {
118
+ "types": "./dist/plugins/checkout.d.ts",
119
+ "default": "./dist/plugins/checkout.js"
120
+ },
121
+ "./paypal": {
122
+ "types": "./dist/plugins/paypal.d.ts",
123
+ "default": "./dist/plugins/paypal.js"
124
+ },
125
+ "./braintree": {
126
+ "types": "./dist/plugins/braintree.d.ts",
127
+ "default": "./dist/plugins/braintree.js"
128
+ },
129
+ "./klarna": {
130
+ "types": "./dist/plugins/klarna.d.ts",
131
+ "default": "./dist/plugins/klarna.js"
132
+ },
133
+ "./stripe-fx": {
134
+ "types": "./dist/stripe-fx.d.ts",
135
+ "default": "./dist/stripe-fx.js"
136
+ },
137
+ "./adyen-fx": {
138
+ "types": "./dist/adyen-fx.d.ts",
139
+ "default": "./dist/adyen-fx.js"
140
+ },
141
+ "./prisma": {
142
+ "types": "./dist/plugins/prisma.d.ts",
143
+ "default": "./dist/plugins/prisma.js"
144
+ },
145
+ "./drizzle/pg": {
146
+ "types": "./dist/drizzle/pg.d.ts",
147
+ "default": "./dist/drizzle/pg.js"
148
+ },
149
+ "./drizzle/mysql": {
150
+ "types": "./dist/drizzle/mysql.d.ts",
151
+ "default": "./dist/drizzle/mysql.js"
152
+ },
153
+ "./drizzle/sqlite": {
154
+ "types": "./dist/drizzle/sqlite.d.ts",
155
+ "default": "./dist/drizzle/sqlite.js"
156
+ },
157
+ "./zod": {
158
+ "types": "./dist/zod.d.ts",
159
+ "default": "./dist/zod.js"
160
+ },
161
+ "./valibot": {
162
+ "types": "./dist/valibot.d.ts",
163
+ "default": "./dist/valibot.js"
164
+ },
165
+ "./pg": {
166
+ "types": "./dist/pg.d.ts",
167
+ "default": "./dist/pg.js"
168
+ },
169
+ "./testing": {
170
+ "types": "./dist/testing/index.d.ts",
171
+ "default": "./dist/testing/index.js"
172
+ },
173
+ "./testing/vitest": {
174
+ "types": "./dist/testing/vitest.d.ts",
175
+ "default": "./dist/testing/vitest.js"
176
+ },
177
+ "./testing/jest": {
178
+ "types": "./dist/testing/jest.d.ts",
179
+ "default": "./dist/testing/jest.js"
180
+ },
181
+ "./testing/arbitraries": {
182
+ "types": "./dist/testing/arbitraries.d.ts",
183
+ "default": "./dist/testing/arbitraries.js"
184
+ },
185
+ "./kysely": {
186
+ "types": "./dist/kysely.d.ts",
187
+ "default": "./dist/kysely.js"
188
+ },
189
+ "./all": {
190
+ "types": "./dist/plugins/all.d.ts",
191
+ "default": "./dist/plugins/all.js"
192
+ },
193
+ "./package.json": "./package.json"
194
+ },
195
+ "scripts": {
196
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.drizzle.json && tsc -p tsconfig.kysely.json && tsc -p tsconfig.peers.json",
197
+ "typecheck": "tsc -p tsconfig.test.json && tsc -p tsconfig.test-drizzle.json && tsc -p test/core-only/tsconfig.json && tsc -p test/browser/tsconfig.json && tsc -p test/jest-types/tsconfig.json",
198
+ "test": "vitest run",
199
+ "test:deep": "DUCAT_DEEP=1 vitest run",
200
+ "compare": "pnpm --dir compare battery && pnpm --dir compare tables",
201
+ "compare:check": "pnpm --dir compare battery:check && pnpm --dir compare tables:check",
202
+ "tables": "pnpm --dir compare tables",
203
+ "test:db": "vitest run --config vitest.db.config.ts",
204
+ "test:browser": "playwright test",
205
+ "test:mutation": "DUCAT_MAX_RUNS=50 stryker run",
206
+ "fetch:dectest": "node scripts/fetch-dectest.mjs",
207
+ "vectors:check": "python3 scripts/gen-pydecimal-vectors.py --check",
208
+ "test:runtimes": "node scripts/smoke-runtimes.mjs",
209
+ "gen": "node scripts/gen-currencies.mjs",
210
+ "gen:check": "node scripts/gen-currencies.mjs --check && node scripts/gen-kernel.mjs --verify",
211
+ "gen:kernel": "node scripts/gen-kernel.mjs",
212
+ "gen:kernel:check": "node scripts/gen-kernel.mjs --check",
213
+ "gen:fetch": "node scripts/gen-currencies.mjs --check --fetch",
214
+ "bench": "node scripts/bench-all.mjs",
215
+ "size": "node scripts/size.mjs",
216
+ "lint": "oxlint",
217
+ "fmt": "oxfmt",
218
+ "fmt:check": "oxfmt --check",
219
+ "check": "pnpm lint && pnpm fmt:check && pnpm typecheck && pnpm size && pnpm test",
220
+ "bench:vitest": "vitest bench --run"
221
+ },
222
+ "devDependencies": {
223
+ "@codspeed/vitest-plugin": "6.1.1",
224
+ "@playwright/test": "1.65.0",
225
+ "@prisma/client": "^6.19.3",
226
+ "@stryker-mutator/core": "10.1.1",
227
+ "@stryker-mutator/vitest-runner": "10.1.1",
228
+ "@types/better-sqlite3": "9.6.0",
229
+ "@types/big.js": "^7.0.0",
230
+ "@types/node": "^26.6.6",
231
+ "@types/pg": "8.23.1",
232
+ "better-sqlite3": "13.0.3",
233
+ "big.js": "^7.0.1",
234
+ "currency.js": "^2.0.4",
235
+ "decimal.js": "^10.6.0",
236
+ "dinero.js": "^2.0.2",
237
+ "drizzle-orm": "0.45.4",
238
+ "esbuild": "^0.28.2",
239
+ "fast-check": "^4.10.2",
240
+ "kysely": "0.29.8",
241
+ "mysql2": "3.24.6",
242
+ "oxfmt": "0.77.0",
243
+ "oxlint": "1.92.0",
244
+ "pg": "8.23.1",
245
+ "pg-cursor": "2.22.1",
246
+ "ts-money": "^0.4.8",
247
+ "typescript": "^5.9.3",
248
+ "valibot": "1.5.0",
249
+ "vitest": "^4.1.12",
250
+ "zod": "4.6.7"
251
+ },
252
+ "peerDependencies": {
253
+ "drizzle-orm": ">=0.45.0 <1",
254
+ "fast-check": "^4.0.0",
255
+ "kysely": ">=0.28.0 <1",
256
+ "valibot": "^1.0.0",
257
+ "vitest": ">=3.2.0 <5",
258
+ "zod": "^4.0.0"
259
+ },
260
+ "peerDependenciesMeta": {
261
+ "drizzle-orm": {
262
+ "optional": true
263
+ },
264
+ "fast-check": {
265
+ "optional": true
266
+ },
267
+ "kysely": {
268
+ "optional": true
269
+ },
270
+ "valibot": {
271
+ "optional": true
272
+ },
273
+ "vitest": {
274
+ "optional": true
275
+ },
276
+ "zod": {
277
+ "optional": true
278
+ }
279
+ },
280
+ "engines": {
281
+ "node": ">=24"
282
+ },
283
+ "packageManager": "pnpm@12.18.0"
9
284
  }
@@ -0,0 +1,175 @@
1
+ // Adyen exchange rates as exact Rates, from settlement details report rows.
2
+ import { exchangeRate, type Rate, type RateInfo } from './rate.js';
3
+
4
+ // UTC offsets, in minutes, of the zone abbreviations that name one offset. Ambiguous ones are left
5
+ // out on purpose: IST is India, Ireland or Israel; CST is US Central or China; BST is British or
6
+ // Bangladesh.
7
+ const ZONE_OFFSET_MINUTES: Readonly<Record<string, number>> = {
8
+ UTC: 0,
9
+ GMT: 0,
10
+ WET: 0,
11
+ WEST: 60,
12
+ CET: 60,
13
+ CEST: 120,
14
+ EET: 120,
15
+ EEST: 180,
16
+ MSK: 180,
17
+ SGT: 480,
18
+ HKT: 480,
19
+ JST: 540,
20
+ KST: 540,
21
+ AEST: 600,
22
+ AEDT: 660,
23
+ NZST: 720,
24
+ NZDT: 780,
25
+ EST: -300,
26
+ EDT: -240,
27
+ MST: -420,
28
+ MDT: -360,
29
+ PST: -480,
30
+ PDT: -420,
31
+ };
32
+
33
+ const LOCAL_TIME = /^(\d{4}-\d\d-\d\d)[ T](\d\d:\d\d(?::\d\d(?:\.\d+)?)?)$/;
34
+ const NUMERIC_OFFSET = /^(?:UTC|GMT)?\s*([+-])(\d{1,2})(?::?(\d\d))?$/;
35
+
36
+ // Real UTC offsets run from -12:00 to +14:00.
37
+ const MAX_OFFSET_MINUTES = 14 * 60;
38
+
39
+ /** The zone's offset in minutes, or undefined when it can't be read unambiguously. */
40
+ function offsetMinutes(zone: string): number | undefined {
41
+ const named = ZONE_OFFSET_MINUTES[zone.toUpperCase()];
42
+ if (named !== undefined) {
43
+ return named;
44
+ }
45
+ const numeric = NUMERIC_OFFSET.exec(zone);
46
+ if (numeric === null) {
47
+ return undefined;
48
+ }
49
+ const hours = Number(numeric[2]);
50
+ const minutes = Number(numeric[3] ?? 0);
51
+ const total = hours * 60 + minutes;
52
+ if (minutes >= 60 || total > MAX_OFFSET_MINUTES) {
53
+ return undefined;
54
+ }
55
+ return numeric[1] === '-' ? -total : total;
56
+ }
57
+
58
+ // Building an Intl.DateTimeFormat is far slower than using one, and a report has thousands of rows
59
+ // in one zone, so keep one formatter per zone. The bound stops a stream of distinct zone names
60
+ // (case variants are accepted by Intl) from growing the cache without limit.
61
+ const MAX_CACHED_FORMATTERS = 32;
62
+ const formatters = new Map<string, Intl.DateTimeFormat>();
63
+
64
+ /** The cached wall-clock formatter for an IANA time zone. */
65
+ function wallClockFormatter(timeZone: string): Intl.DateTimeFormat {
66
+ let formatter = formatters.get(timeZone);
67
+ if (formatter !== undefined) {
68
+ return formatter;
69
+ }
70
+
71
+ formatter = new Intl.DateTimeFormat('en-US', {
72
+ timeZone,
73
+ hourCycle: 'h23',
74
+ year: 'numeric',
75
+ month: 'numeric',
76
+ day: 'numeric',
77
+ hour: 'numeric',
78
+ minute: 'numeric',
79
+ second: 'numeric',
80
+ });
81
+ if (formatters.size >= MAX_CACHED_FORMATTERS) {
82
+ formatters.clear();
83
+ }
84
+ formatters.set(timeZone, formatter);
85
+ return formatter;
86
+ }
87
+
88
+ /** The offset of an IANA time zone at a UTC instant, in minutes. */
89
+ function ianaOffsetMinutes(timeZone: string, utcMs: number): number {
90
+ const parts = wallClockFormatter(timeZone).formatToParts(new Date(utcMs));
91
+ const field = (type: string): number => Number(parts.find((part) => part.type === type)!.value);
92
+ const wallClockAsUtc = Date.UTC(
93
+ field('year'),
94
+ field('month') - 1,
95
+ field('day'),
96
+ field('hour'),
97
+ field('minute'),
98
+ field('second'),
99
+ );
100
+ return Math.round((wallClockAsUtc - Math.floor(utcMs / 1000) * 1000) / 60_000);
101
+ }
102
+
103
+ /** The UTC instant of a wall-clock time in an IANA zone, summer time included. */
104
+ function ianaToUtc(localAsUtcMs: number, timeZone: string): number {
105
+ // The offset at the guess can differ from the offset at the answer across a clock change, so
106
+ // look it up again at the first answer.
107
+ const firstGuess = localAsUtcMs - ianaOffsetMinutes(timeZone, localAsUtcMs) * 60_000;
108
+ return localAsUtcMs - ianaOffsetMinutes(timeZone, firstGuess) * 60_000;
109
+ }
110
+
111
+ /** Creation Date as a UTC instant when its zone is known; otherwise its local day. */
112
+ function creationAsOf(
113
+ created: string,
114
+ label: string | undefined,
115
+ timeZone: string | undefined,
116
+ ): string | undefined {
117
+ const local = LOCAL_TIME.exec(created.trim());
118
+ if (local === null) {
119
+ return /^\d{4}-\d\d-\d\d/.test(created) ? created.slice(0, 10) : undefined;
120
+ }
121
+ const localAsUtcMs = Date.parse(`${local[1]}T${local[2]}Z`);
122
+ if (timeZone !== undefined) {
123
+ return new Date(ianaToUtc(localAsUtcMs, timeZone)).toISOString();
124
+ }
125
+ const offset = label === undefined ? undefined : offsetMinutes(label.trim());
126
+ if (offset === undefined) {
127
+ return local[1];
128
+ }
129
+ return new Date(localAsUtcMs - offset * 60_000).toISOString();
130
+ }
131
+
132
+ /** Options for adyenRate. */
133
+ export interface AdyenRateOptions {
134
+ /**
135
+ * The account's IANA time zone ('Europe/Amsterdam'). When given, Creation Date is read in it,
136
+ * summer time included, and the TimeZone column is not used.
137
+ */
138
+ readonly timeZone?: string;
139
+ }
140
+
141
+ /** A settlement details report row, keyed by column name (as from a CSV parser with headers). */
142
+ export type AdyenSettlementRow = Readonly<Record<string, string | undefined>>;
143
+
144
+ /**
145
+ * The rate in a settlement details report row: "The exchange rate used for converting the gross
146
+ * amount into the net amount", Gross Currency → Net Currency (1 when they are the same). The
147
+ * decimal string is kept exactly. `asOf` comes from Creation Date, which Adyen gives in local time,
148
+ * with the zone in the TimeZone column. Pass `{ timeZone: 'Europe/Amsterdam' }` (the account's IANA
149
+ * zone) to read it correctly all year. Without it, an unambiguous abbreviation (CET, PST, ...) or
150
+ * offset (+01:00) is taken literally: Adyen's documentation doesn't say whether the column switches
151
+ * to CEST in summer, and if it doesn't, a literal CET is an hour off then. Any other label gives
152
+ * the local day, which can be a day off from UTC. `undefined` when the row has no rate. For
153
+ * externally settled payments Adyen lists its reference rate, not the acquirer's, so check those
154
+ * with impliedRate().
155
+ */
156
+ export function adyenRate(row: AdyenSettlementRow, options?: AdyenRateOptions): Rate | undefined {
157
+ const gross = row['Gross Currency'];
158
+ const net = row['Net Currency'];
159
+ const rate = row['Exchange Rate']?.trim();
160
+ if (gross === undefined || gross === '' || net === undefined || net === '') {
161
+ return undefined;
162
+ }
163
+ if (rate === undefined || rate === '') {
164
+ return undefined;
165
+ }
166
+
167
+ const created = row['Creation Date'];
168
+ let info: RateInfo = { source: 'adyen' };
169
+ const asOf =
170
+ created === undefined ? undefined : creationAsOf(created, row['TimeZone'], options?.timeZone);
171
+ if (asOf !== undefined) {
172
+ info = { source: 'adyen', asOf };
173
+ }
174
+ return exchangeRate(gross, net, rate, info);
175
+ }
package/src/adyen.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Adyen's minor-unit view (https://docs.adyen.com/development-resources/currency-codes, encoded in
3
+ * data/adyen.json). Adyen's table is authoritative where it differs from ISO 4217: CLP 2 (ISO 0),
4
+ * ISK 2 (ISO 0), IDR 0 (ISO 2), CVE 0 (ISO 2). The Terminal API uses major units instead.
5
+ */
6
+ import { ADYEN_EXPONENTS } from './generated/adyen.js';
7
+ import { type CurrencyInput, type Money } from './money.js';
8
+ import { fromProcessorAmount, toProcessorAmount } from './processor.js';
9
+ import type { RoundingMode } from './rounding.js';
10
+
11
+ export { ADYEN_EXPONENTS };
12
+
13
+ function exponent(currency: string): number {
14
+ const found = ADYEN_EXPONENTS[currency];
15
+ // typeof, not !== undefined: the table is a plain object, so 'toString' or 'constructor' would
16
+ // otherwise find an inherited method instead of failing.
17
+ if (typeof found !== 'number') {
18
+ throw new RangeError(`${currency} is not in Adyen's currency table`);
19
+ }
20
+ return found;
21
+ }
22
+
23
+ /** Whether Adyen lists the currency (its table, not ISO 4217). */
24
+ export const isAdyenCurrency = (currency: string): boolean =>
25
+ typeof ADYEN_EXPONENTS[currency] === 'number';
26
+ /** The exponent Adyen's API uses for a currency (CLP 2, ISK 2, IDR 0, CVE 0 differ from ISO). */
27
+ export const adyenExponent = exponent;
28
+
29
+ /** Adyen `amount` object: toAdyen(money('15000', 'IDR')) -> { value: 15000, currency: 'IDR' }. */
30
+ export function toAdyen(
31
+ money: Money,
32
+ rounding: RoundingMode = 'unnecessary',
33
+ ): { value: number; currency: string } {
34
+ return {
35
+ value: toProcessorAmount('Adyen', money, exponent(money.currency), 1, rounding),
36
+ currency: money.currency,
37
+ };
38
+ }
39
+
40
+ /** Reads an Adyen `amount` object: fromAdyen({ value: 15000, currency: 'IDR' }) is 15000 IDR. */
41
+ export function fromAdyen<C extends CurrencyInput>(amount: {
42
+ value: number | bigint;
43
+ currency: C;
44
+ }): Money<C> {
45
+ return fromProcessorAmount('Adyen', amount.value, amount.currency, exponent(amount.currency));
46
+ }