@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
@@ -0,0 +1,25 @@
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 type { RoundingMode } from './rounding.js';
9
+ export { ADYEN_EXPONENTS };
10
+ declare function exponent(currency: string): number;
11
+ /** Whether Adyen lists the currency (its table, not ISO 4217). */
12
+ export declare const isAdyenCurrency: (currency: string) => boolean;
13
+ /** The exponent Adyen's API uses for a currency (CLP 2, ISK 2, IDR 0, CVE 0 differ from ISO). */
14
+ export declare const adyenExponent: typeof exponent;
15
+ /** Adyen `amount` object: toAdyen(money('15000', 'IDR')) -> { value: 15000, currency: 'IDR' }. */
16
+ export declare function toAdyen(money: Money, rounding?: RoundingMode): {
17
+ value: number;
18
+ currency: string;
19
+ };
20
+ /** Reads an Adyen `amount` object: fromAdyen({ value: 15000, currency: 'IDR' }) is 15000 IDR. */
21
+ export declare function fromAdyen<C extends CurrencyInput>(amount: {
22
+ value: number | bigint;
23
+ currency: C;
24
+ }): Money<C>;
25
+ //# sourceMappingURL=adyen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adyen.d.ts","sourceRoot":"","sources":["../src/adyen.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,iBAAS,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ1C;AAED,kEAAkE;AAClE,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KAAG,OACJ,CAAC;AAChD,iGAAiG;AACjG,eAAO,MAAM,aAAa,iBAAW,CAAC;AAEtC,kGAAkG;AAClG,wBAAgB,OAAO,CACrB,KAAK,EAAE,KAAK,EACZ,QAAQ,GAAE,YAA4B,GACrC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKrC;AAED,iGAAiG;AACjG,wBAAgB,SAAS,CAAC,CAAC,SAAS,aAAa,EAAE,MAAM,EAAE;IACzD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC;CACb,GAAG,KAAK,CAAC,CAAC,CAAC,CAEX"}
package/dist/adyen.js ADDED
@@ -0,0 +1,34 @@
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 {} from './money.js';
8
+ import { fromProcessorAmount, toProcessorAmount } from './processor.js';
9
+ export { ADYEN_EXPONENTS };
10
+ function exponent(currency) {
11
+ const found = ADYEN_EXPONENTS[currency];
12
+ // typeof, not !== undefined: the table is a plain object, so 'toString' or 'constructor' would
13
+ // otherwise find an inherited method instead of failing.
14
+ if (typeof found !== 'number') {
15
+ throw new RangeError(`${currency} is not in Adyen's currency table`);
16
+ }
17
+ return found;
18
+ }
19
+ /** Whether Adyen lists the currency (its table, not ISO 4217). */
20
+ export const isAdyenCurrency = (currency) => typeof ADYEN_EXPONENTS[currency] === 'number';
21
+ /** The exponent Adyen's API uses for a currency (CLP 2, ISK 2, IDR 0, CVE 0 differ from ISO). */
22
+ export const adyenExponent = exponent;
23
+ /** Adyen `amount` object: toAdyen(money('15000', 'IDR')) -> { value: 15000, currency: 'IDR' }. */
24
+ export function toAdyen(money, rounding = 'unnecessary') {
25
+ return {
26
+ value: toProcessorAmount('Adyen', money, exponent(money.currency), 1, rounding),
27
+ currency: money.currency,
28
+ };
29
+ }
30
+ /** Reads an Adyen `amount` object: fromAdyen({ value: 15000, currency: 'IDR' }) is 15000 IDR. */
31
+ export function fromAdyen(amount) {
32
+ return fromProcessorAmount('Adyen', amount.value, amount.currency, exponent(amount.currency));
33
+ }
34
+ //# sourceMappingURL=adyen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adyen.js","sourceRoot":"","sources":["../src/adyen.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAkC,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxE,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,SAAS,QAAQ,CAAC,QAAgB;IAChC,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACxC,+FAA+F;IAC/F,yDAAyD;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAAC,GAAG,QAAQ,mCAAmC,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAW,EAAE,CAC3D,OAAO,eAAe,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;AAChD,iGAAiG;AACjG,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,kGAAkG;AAClG,MAAM,UAAU,OAAO,CACrB,KAAY,EACZ,WAAyB,aAAa;IAEtC,OAAO;QACL,KAAK,EAAE,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;QAC/E,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;AACJ,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,SAAS,CAA0B,MAGlD;IACC,OAAO,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChG,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { type Money } from './money.js';
2
+ /**
3
+ * Where the indivisible remainder (always fewer minor units than there are non-zero buckets for
4
+ * the spreading strategies) goes:
5
+ * - 'largest' largest-remainder (Hamilton) method: units go to the buckets with the biggest
6
+ * fractional part, ties to the earlier bucket. The default; minimises error per bucket.
7
+ * - 'first' one unit each to the first buckets (with non-zero weight)
8
+ * - 'last' one unit each to the last buckets
9
+ * - 'toFirst' the whole remainder to the first bucket
10
+ * - 'toLast' the whole remainder to the last bucket
11
+ */
12
+ export type Remainder = 'largest' | 'first' | 'last' | 'toFirst' | 'toLast';
13
+ /** Options for `allocate` and `split`: where the indivisible remainder goes. */
14
+ export interface AllocateOptions {
15
+ readonly remainder?: Remainder;
16
+ }
17
+ /** A ratio weight: a non-negative integer, bigint or decimal string ('33.3'). */
18
+ export type Weight = number | bigint | string;
19
+ /**
20
+ * Splits `m` into parts proportional to `weights`. Exact: the parts always sum to `m`, and zero
21
+ * weights get zero. With 'largest' each part is less than one minor unit from its exact share; with
22
+ * 'first' and 'last', at most one unit. Negative amounts are allocated as the negation of the
23
+ * positive allocation. These properties are proved for a Lean model of this function
24
+ * (proofs/Ducat/Allocate.lean), and test/allocate.oracle.test.ts checks this code against that
25
+ * model.
26
+ *
27
+ * allocate(money('100', 'EUR'), [1, 1, 1]) // 33.34, 33.33, 33.33
28
+ * allocate(money('0.05', 'EUR'), ['70', '30']) // 0.04, 0.01
29
+ */
30
+ export declare function allocate<C extends string>(money: Money<C>, weights: readonly Weight[], options?: AllocateOptions): Money<C>[];
31
+ /** Splits into `count` equal parts; the remainder goes per `remainder` (default 'first'). */
32
+ export declare function split<C extends string>(money: Money<C>, count: number, options?: AllocateOptions): Money<C>[];
33
+ /**
34
+ * Options for `instalments`: where the remainder goes, and an optional unit every regular
35
+ * instalment is a multiple of.
36
+ */
37
+ export interface InstalmentOptions<C extends string> {
38
+ /** Where the remainder goes: default 'toFirst' (first instalment absorbs it). */
39
+ readonly remainder?: Exclude<Remainder, 'largest'>;
40
+ /** Make every regular instalment a multiple of this (e.g. money('1', 'EUR') for whole euros). */
41
+ readonly unit?: Money<C>;
42
+ }
43
+ /**
44
+ * Instalment plan: `count` equal payments, one of which absorbs the remainder.
45
+ *
46
+ * instalments(money('100', 'EUR'), 3) // 33.34, 33.33, 33.33
47
+ * instalments(money('100', 'EUR'), 3, { remainder: 'toLast' }) // 33.33, 33.33, 33.34
48
+ * instalments(money('100', 'EUR'), 3, { unit: money('1', 'EUR') }) // 34.00, 33.00, 33.00
49
+ */
50
+ export declare function instalments<C extends string>(total: Money<C>, count: number, options?: InstalmentOptions<NoInfer<C>>): Money<C>[];
51
+ /** One tranche of a `schedule`: a fixed amount, a (capped) percentage, or the rest. */
52
+ export type Tranche<C extends string> = {
53
+ readonly amount: Money<C>;
54
+ } | {
55
+ readonly percent: Weight;
56
+ readonly cap?: Money<C>;
57
+ } | {
58
+ readonly rest: true;
59
+ };
60
+ /**
61
+ * A payment schedule mixing fixed amounts, percentages of the total (optionally capped) and one
62
+ * `rest` tranche that receives whatever is left. Percent tranches are computed together with
63
+ * largest-remainder allocation, so no rounding mode is needed and the schedule is exact.
64
+ * Throws if the tranches cannot add up to exactly `total`.
65
+ *
66
+ * schedule(money('1000', 'EUR'), [{ percent: 30 }, { amount: money('200', 'EUR') }, { rest: true }])
67
+ * // 300.00, 200.00, 500.00
68
+ */
69
+ export declare function schedule<C extends string>(total: Money<C>, tranches: readonly Tranche<NoInfer<C>>[]): Money<C>[];
70
+ /** Splits into tranches of at most `max` each: chunk(EUR 1000, EUR 300) -> 300, 300, 300, 100. */
71
+ export declare function chunk<C extends string>(total: Money<C>, max: Money<NoInfer<C>>): Money<C>[];
72
+ //# sourceMappingURL=allocate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allocate.d.ts","sourceRoot":"","sources":["../src/allocate.ts"],"names":[],"mappings":"AACA,OAAO,EAQL,KAAK,KAAK,EACX,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE5E,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAChC;AAED,iFAAiF;AACjF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAyF9C;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,CAAC,EAAE,eAAe,GACxB,KAAK,CAAC,CAAC,CAAC,EAAE,CA4FZ;AAED,6FAA6F;AAC7F,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EACpC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,eAAe,GACxB,KAAK,CAAC,CAAC,CAAC,EAAE,CAMZ;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,MAAM;IACjD,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACnD,iGAAiG;IACjG,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC1C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GACtC,KAAK,CAAC,CAAC,CAAC,EAAE,CA+BZ;AAED,uFAAuF;AACvF,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,IAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5B;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,QAAQ,EAAE,SAAS,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,GACvC,KAAK,CAAC,CAAC,CAAC,EAAE,CAwDZ;AAED,kGAAkG;AAClG,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAiB3F"}
@@ -0,0 +1,314 @@
1
+ import { parseDecimal, pow10n, normalizeMinor } from './decimal.js';
2
+ import { CurrencyMismatchError, compare, make, negate, scaleUp, subtract, toScale, } from './money.js';
3
+ const MAX_SAFE_MINOR = Number.MAX_SAFE_INTEGER;
4
+ function weightsToBig(ws) {
5
+ return weightsScaled(ws).ws;
6
+ }
7
+ function weightsScaled(ws) {
8
+ let scale = 0;
9
+ const parsed = ws.map((weight) => {
10
+ if (typeof weight === 'bigint') {
11
+ return { digits: weight, scale: 0 };
12
+ }
13
+ if (typeof weight === 'number' && Number.isSafeInteger(weight)) {
14
+ return { digits: BigInt(weight), scale: 0 };
15
+ }
16
+ const item = parseDecimal(String(weight));
17
+ return item;
18
+ });
19
+ for (const item of parsed) {
20
+ if (item.digits < 0n) {
21
+ throw new RangeError('Allocation weights must not be negative');
22
+ }
23
+ if (item.scale > scale) {
24
+ scale = item.scale;
25
+ }
26
+ }
27
+ return { ws: parsed.map((item) => item.digits * pow10n(scale - item.scale)), scale };
28
+ }
29
+ /**
30
+ * Distributes `rem` extra units among the buckets; `frac` are the per-bucket remainders (for
31
+ * 'largest').
32
+ */
33
+ function distribute(shares, rem, weights, frac, mode, one) {
34
+ if (rem === 0) {
35
+ return;
36
+ }
37
+ const count = shares.length;
38
+ const eligible = [];
39
+ for (let i = 0; i < count; i++) {
40
+ if (weights[i] > 0) {
41
+ eligible.push(i);
42
+ }
43
+ }
44
+ const plus = (i, k) => {
45
+ shares[i] = (typeof one === 'number' ? shares[i] + k : shares[i] + BigInt(k));
46
+ };
47
+ switch (mode) {
48
+ case 'toFirst':
49
+ return plus(eligible[0], rem);
50
+ case 'toLast':
51
+ return plus(eligible[eligible.length - 1], rem);
52
+ case 'first':
53
+ for (let k = 0; k < rem; k++) {
54
+ plus(eligible[k], 1);
55
+ }
56
+ return;
57
+ case 'last':
58
+ for (let k = 0; k < rem; k++) {
59
+ plus(eligible[eligible.length - 1 - k], 1);
60
+ }
61
+ return;
62
+ case 'largest': {
63
+ const remainders = frac;
64
+ // Largest remainder first; equal remainders keep bucket order.
65
+ eligible.sort((left, right) => {
66
+ if (remainders[left] !== remainders[right]) {
67
+ return remainders[left] > remainders[right] ? -1 : 1;
68
+ }
69
+ return left - right;
70
+ });
71
+ for (let k = 0; k < rem; k++) {
72
+ plus(eligible[k], 1);
73
+ }
74
+ return;
75
+ }
76
+ }
77
+ throw new RangeError(`Unknown remainder strategy "${String(mode)}"`);
78
+ }
79
+ /**
80
+ * Splits `m` into parts proportional to `weights`. Exact: the parts always sum to `m`, and zero
81
+ * weights get zero. With 'largest' each part is less than one minor unit from its exact share; with
82
+ * 'first' and 'last', at most one unit. Negative amounts are allocated as the negation of the
83
+ * positive allocation. These properties are proved for a Lean model of this function
84
+ * (proofs/Ducat/Allocate.lean), and test/allocate.oracle.test.ts checks this code against that
85
+ * model.
86
+ *
87
+ * allocate(money('100', 'EUR'), [1, 1, 1]) // 33.34, 33.33, 33.33
88
+ * allocate(money('0.05', 'EUR'), ['70', '30']) // 0.04, 0.01
89
+ */
90
+ export function allocate(money, weights, options) {
91
+ const count = weights.length;
92
+ if (count === 0) {
93
+ throw new RangeError('allocate() needs at least one weight');
94
+ }
95
+ const mode = options?.remainder ?? 'largest';
96
+ if (money.minor < 0) {
97
+ return allocate(negate(money), weights, options).map(negate);
98
+ }
99
+ const minor = money.minor;
100
+ // fast path: integer weights whose products with the amount fit exactly in a double
101
+ if (typeof minor === 'number') {
102
+ let total = 0;
103
+ let maxWeight = 0;
104
+ let ok = true;
105
+ for (let i = 0; i < count; i++) {
106
+ const weight = weights[i];
107
+ if (typeof weight !== 'number' || !(weight >= 0) || !Number.isSafeInteger(weight)) {
108
+ ok = false;
109
+ break;
110
+ }
111
+ total += weight;
112
+ if (weight > maxWeight) {
113
+ maxWeight = weight;
114
+ }
115
+ }
116
+ if (ok && total > 0 && total <= MAX_SAFE_MINOR && minor * maxWeight <= MAX_SAFE_MINOR - total) {
117
+ const ws = weights;
118
+ const shares = new Array(count);
119
+ const frac = new Array(count);
120
+ let rem = minor;
121
+ for (let i = 0; i < count; i++) {
122
+ const product = minor * ws[i];
123
+ let quotient = Math.floor(product / total);
124
+ let remainder = product - quotient * total;
125
+ if (remainder < 0) {
126
+ quotient -= 1;
127
+ remainder += total;
128
+ }
129
+ else if (remainder >= total) {
130
+ quotient += 1;
131
+ remainder -= total;
132
+ } // float-quotient fix-up
133
+ shares[i] = quotient;
134
+ frac[i] = remainder;
135
+ rem -= quotient;
136
+ }
137
+ if (rem > 0) {
138
+ if (mode === 'largest' && count <= 32) {
139
+ // selection instead of sort: rem < number of non-zero weights, n small
140
+ for (; rem > 0; rem--) {
141
+ let best = -1;
142
+ for (let i = 0; i < count; i++) {
143
+ if (ws[i] > 0 && frac[i] >= 0 && (best < 0 || frac[i] > frac[best])) {
144
+ best = i;
145
+ }
146
+ }
147
+ shares[best] += 1;
148
+ frac[best] = -1;
149
+ }
150
+ }
151
+ else {
152
+ distribute(shares, rem, ws, frac, mode, 1);
153
+ }
154
+ }
155
+ const out = new Array(count);
156
+ for (let i = 0; i < count; i++) {
157
+ out[i] = make(money.currency, shares[i], money.scale);
158
+ }
159
+ return out;
160
+ }
161
+ }
162
+ const ws = weightsToBig(weights);
163
+ let total = 0n;
164
+ for (const weight of ws) {
165
+ total += weight;
166
+ }
167
+ if (total === 0n) {
168
+ throw new RangeError('Allocation weights must not all be zero');
169
+ }
170
+ const xb = BigInt(minor);
171
+ const shares = new Array(count);
172
+ const frac = new Array(count);
173
+ let assigned = 0n;
174
+ for (let i = 0; i < count; i++) {
175
+ const product = xb * ws[i];
176
+ shares[i] = product / total;
177
+ frac[i] = product % total;
178
+ assigned += shares[i];
179
+ }
180
+ distribute(shares, Number(xb - assigned), ws, frac, mode, 1n);
181
+ return shares.map((share) => make(money.currency, share, money.scale));
182
+ }
183
+ /** Splits into `count` equal parts; the remainder goes per `remainder` (default 'first'). */
184
+ export function split(money, count, options) {
185
+ if (!Number.isSafeInteger(count) || count < 1) {
186
+ throw new RangeError(`Invalid count ${count}`);
187
+ }
188
+ const weights = new Array(count).fill(1);
189
+ return allocate(money, weights, { remainder: options?.remainder ?? 'first' });
190
+ }
191
+ /**
192
+ * Instalment plan: `count` equal payments, one of which absorbs the remainder.
193
+ *
194
+ * instalments(money('100', 'EUR'), 3) // 33.34, 33.33, 33.33
195
+ * instalments(money('100', 'EUR'), 3, { remainder: 'toLast' }) // 33.33, 33.33, 33.34
196
+ * instalments(money('100', 'EUR'), 3, { unit: money('1', 'EUR') }) // 34.00, 33.00, 33.00
197
+ */
198
+ export function instalments(total, count, options) {
199
+ if (!Number.isSafeInteger(count) || count < 1) {
200
+ throw new RangeError(`Invalid count ${count}`);
201
+ }
202
+ const mode = options?.remainder ?? 'toFirst';
203
+ const unit = options?.unit;
204
+ if (!unit) {
205
+ return allocate(total, new Array(count).fill(1), { remainder: mode });
206
+ }
207
+ if (unit.currency !== total.currency) {
208
+ throw new CurrencyMismatchError(total.currency, unit.currency);
209
+ }
210
+ if (!(unit.minor > 0)) {
211
+ throw new RangeError('unit must be positive');
212
+ }
213
+ const scale = Math.max(total.scale, unit.scale);
214
+ const scaledTotal = toScale(total, scale);
215
+ const unitMinor = BigInt(scaleUp(unit.minor, scale - unit.scale));
216
+ const neg = scaledTotal.minor < 0;
217
+ const tv = BigInt(scaledTotal.minor) * (neg ? -1n : 1n);
218
+ const per = (tv / (unitMinor * BigInt(count))) * unitMinor;
219
+ const parts = new Array(count).fill(per);
220
+ let left = tv - per * BigInt(count);
221
+ // spread whole units first (for 'first'/'last'), then the sub-unit leftover
222
+ if (mode === 'first' || mode === 'last') {
223
+ for (let k = 0; left >= unitMinor; k++, left -= unitMinor) {
224
+ parts[mode === 'first' ? k : count - 1 - k] += unitMinor;
225
+ }
226
+ }
227
+ parts[mode === 'toLast' || mode === 'last' ? count - 1 : 0] += left;
228
+ return parts.map((part) => make(total.currency, neg ? -part : part, scale));
229
+ }
230
+ /**
231
+ * A payment schedule mixing fixed amounts, percentages of the total (optionally capped) and one
232
+ * `rest` tranche that receives whatever is left. Percent tranches are computed together with
233
+ * largest-remainder allocation, so no rounding mode is needed and the schedule is exact.
234
+ * Throws if the tranches cannot add up to exactly `total`.
235
+ *
236
+ * schedule(money('1000', 'EUR'), [{ percent: 30 }, { amount: money('200', 'EUR') }, { rest: true }])
237
+ * // 300.00, 200.00, 500.00
238
+ */
239
+ export function schedule(total, tranches) {
240
+ const pctIdx = [];
241
+ const pcts = [];
242
+ let restIdx = -1;
243
+ tranches.forEach((tranche, i) => {
244
+ if ('percent' in tranche) {
245
+ pctIdx.push(i);
246
+ pcts.push(tranche.percent);
247
+ }
248
+ else if ('rest' in tranche) {
249
+ if (restIdx >= 0) {
250
+ throw new RangeError('schedule() allows only one rest tranche');
251
+ }
252
+ restIdx = i;
253
+ }
254
+ });
255
+ const out = new Array(tranches.length);
256
+ let left = total;
257
+ if (pcts.length) {
258
+ const { ws, scale } = weightsScaled(pcts);
259
+ let sum = 0n;
260
+ for (const weight of ws) {
261
+ sum += weight;
262
+ }
263
+ const hundred = 100n * pow10n(scale);
264
+ if (sum > hundred) {
265
+ throw new RangeError('schedule() percentages exceed 100');
266
+ }
267
+ const parts = allocate(total, [...ws, hundred - sum].map((weight) => normalizeMinor(weight)));
268
+ pctIdx.forEach((trancheIndex, k) => {
269
+ let part = parts[k];
270
+ const cap = tranches[trancheIndex].cap;
271
+ if (cap && compare(part, cap) > 0) {
272
+ part = cap;
273
+ }
274
+ out[trancheIndex] = part;
275
+ left = subtract(left, part);
276
+ });
277
+ }
278
+ tranches.forEach((tranche, i) => {
279
+ if ('amount' in tranche) {
280
+ out[i] = tranche.amount;
281
+ left = subtract(left, tranche.amount);
282
+ }
283
+ });
284
+ if (left.minor < 0) {
285
+ throw new RangeError(`schedule() tranches exceed the total by ${negate(left)}`);
286
+ }
287
+ if (restIdx >= 0) {
288
+ out[restIdx] = left;
289
+ }
290
+ else if (left.minor != 0) {
291
+ throw new RangeError(`schedule() leaves ${left} unassigned; add { rest: true }`);
292
+ }
293
+ return out;
294
+ }
295
+ /** Splits into tranches of at most `max` each: chunk(EUR 1000, EUR 300) -> 300, 300, 300, 100. */
296
+ export function chunk(total, max) {
297
+ if (!(max.minor > 0)) {
298
+ throw new RangeError('chunk() max must be positive');
299
+ }
300
+ if (total.minor < 0) {
301
+ throw new RangeError('chunk() total must not be negative');
302
+ }
303
+ const out = [];
304
+ let left = total;
305
+ while (compare(left, max) > 0) {
306
+ out.push(max);
307
+ left = subtract(left, max);
308
+ }
309
+ if (left.minor > 0 || out.length === 0) {
310
+ out.push(left);
311
+ }
312
+ return out;
313
+ }
314
+ //# sourceMappingURL=allocate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allocate.js","sourceRoot":"","sources":["../src/allocate.ts"],"names":[],"mappings":"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"}
package/dist/bag.d.ts ADDED
@@ -0,0 +1,58 @@
1
+ import { type ExactMoney } from './exact.js';
2
+ import { type Money } from './money.js';
3
+ import { type RateProvider } from './provider.js';
4
+ import type { RoundingMode } from './rounding.js';
5
+ /** Options for MoneyBag#total. */
6
+ export interface TotalOptions {
7
+ readonly asOf?: string | Date;
8
+ /** Result scale (default: the target currency's exponent). */
9
+ readonly scale?: number;
10
+ }
11
+ /** Per-currency totals of `items`, in first-seen order. */
12
+ export declare function sumByCurrency(items: Iterable<Money>): Map<string, Money>;
13
+ /** An immutable set of per-currency totals: `bag(eur10, usd5, eur2).get('EUR')` is EUR 12. */
14
+ export declare class MoneyBag {
15
+ #private;
16
+ /** @internal use bag() */
17
+ constructor(totals: ReadonlyMap<string, Money>);
18
+ /** A new bag with `items` added. */
19
+ add(...items: Money[]): MoneyBag;
20
+ /** The total in `currency`, or undefined when the bag has none. */
21
+ get<C extends string>(currency: C): Money<C> | undefined;
22
+ /** The currencies held, in first-seen order. */
23
+ currencies(): string[];
24
+ /** The per-currency totals, in first-seen order. */
25
+ values(): Money[];
26
+ /** Every entry converted exactly into `to` and summed. Nothing is rounded. */
27
+ exactTotal<To extends string>(to: To, provider: RateProvider, options?: Pick<TotalOptions, 'asOf'>): ExactMoney<To>;
28
+ /** The total in `to`, rounded once: `bag.total('EUR', fx, 'halfEven')`. */
29
+ total<To extends string>(to: To, provider: RateProvider, rounding: RoundingMode, options?: TotalOptions): Money<To>;
30
+ /** The totals as a list of Money JSON values. */
31
+ toJSON(): unknown[];
32
+ }
33
+ /** A bag of the per-currency totals of `items`. */
34
+ export declare function bag(...items: Money[]): MoneyBag;
35
+ /** Options for comparator(). */
36
+ export interface ComparatorOptions {
37
+ /** Every amount is compared as its exact value in this currency. */
38
+ readonly base: string;
39
+ readonly asOf?: string | Date;
40
+ }
41
+ /**
42
+ * Compares amounts in any currencies through one base currency, exactly (no rounding, so rounding
43
+ * makes no ties). One rate per currency makes it a total preorder, so `list.sort(comparator(fx, {
44
+ * base: 'USD' }))` is consistent. Pairwise conversion with bid/ask or slightly inconsistent mids is
45
+ * not, and Array#sort's result then differs between engines. Rates are looked up once per currency,
46
+ * lazily: a missing rate throws from inside `sort`, after the list may already be partly reordered.
47
+ * `sortByValue` looks every rate up first.
48
+ */
49
+ export declare function comparator(provider: RateProvider, options: ComparatorOptions): (money: Money, other: Money) => -1 | 0 | 1;
50
+ /**
51
+ * A new array of `items` in ascending order of their value in `options.base`, as `comparator`
52
+ * orders them. Every amount is converted before sorting, so a missing rate throws
53
+ * RateUnavailableError before anything is reordered, and each amount is converted only once.
54
+ *
55
+ * sortByValue([jpy100, gbp1, usd1], fx, { base: 'EUR' }) // [jpy100, usd1, gbp1]
56
+ */
57
+ export declare function sortByValue<Item extends Money>(items: Iterable<Item>, provider: RateProvider, options: ComparatorOptions): Item[];
58
+ //# sourceMappingURL=bag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bag.d.ts","sourceRoot":"","sources":["../src/bag.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAU,KAAK,YAAY,EAAkB,MAAM,eAAe,CAAC;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AASD,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAWxE;AAED,8FAA8F;AAC9F,qBAAa,QAAQ;;IAGnB,0BAA0B;gBACd,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC;IAK9C,oCAAoC;IACpC,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ;IAIhC,mEAAmE;IACnE,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS;IAIxD,gDAAgD;IAChD,UAAU,IAAI,MAAM,EAAE;IAItB,oDAAoD;IACpD,MAAM,IAAI,KAAK,EAAE;IAIjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,SAAS,MAAM,EAC1B,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,YAAY,EACtB,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GACnC,UAAU,CAAC,EAAE,CAAC;IAcjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,MAAM,EACrB,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,EACtB,OAAO,CAAC,EAAE,YAAY,GACrB,KAAK,CAAC,EAAE,CAAC;IAIZ,iDAAiD;IACjD,MAAM,IAAI,OAAO,EAAE;CAGpB;AAED,mDAAmD;AACnD,wBAAgB,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,CAE/C;AAED,gCAAgC;AAChC,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAwBD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,iBAAiB,GACzB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAG5C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,SAAS,KAAK,EAC5C,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EACrB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,iBAAiB,GACzB,IAAI,EAAE,CAMR"}