solve-engine 2.25.0 → 2.27.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 (240) hide show
  1. package/dist/CalendarBackend-MdS3Bb4P.d.cts +181 -0
  2. package/dist/CalendarBackend-MdS3Bb4P.d.ts +181 -0
  3. package/dist/{Configuration-DnzYPmoK.d.cts → Configuration-BxriK9Kw.d.cts} +63 -4
  4. package/dist/{Configuration-DnzYPmoK.d.ts → Configuration-BxriK9Kw.d.ts} +63 -4
  5. package/dist/DateCalendar-B85t6Vk6.d.ts +90 -0
  6. package/dist/DateCalendar-CUGI1fT4.d.cts +90 -0
  7. package/dist/{EngineError-fR1K1rvx.d.cts → EngineError-C-kBwYlN.d.cts} +31 -4
  8. package/dist/{EngineError-fR1K1rvx.d.ts → EngineError-C-kBwYlN.d.ts} +31 -4
  9. package/dist/{FormattingSettings-bRKjU7wI.d.ts → FormattingSettings-ByO-4wiM.d.cts} +14 -0
  10. package/dist/{FormattingSettings-bRKjU7wI.d.cts → FormattingSettings-CvCzAfsz.d.ts} +14 -0
  11. package/dist/{Lexer-aB95pjoX.d.cts → Lexer-DhGhoAa2.d.cts} +13 -3
  12. package/dist/{Lexer-Bmctxl0n.d.ts → Lexer-DqtnZMC5.d.ts} +13 -3
  13. package/dist/{PackageCompatibility-CUVg8tmt.d.cts → PackageCompatibility-CNiTtC6S.d.cts} +1 -1
  14. package/dist/{PackageCompatibility-BludTs7v.d.ts → PackageCompatibility-fj_f7uqC.d.ts} +1 -1
  15. package/dist/{PackageRegistry-Dvn4i2QK.d.cts → PackageRegistry-BHBCFswo.d.cts} +328 -14
  16. package/dist/{PackageRegistry-DT-x32OM.d.ts → PackageRegistry-CNZUwWHJ.d.ts} +328 -14
  17. package/dist/{Parselet-BawfGuTF.d.cts → Parselet-DF3864la.d.cts} +19 -3
  18. package/dist/{Parselet-DqTbbtWA.d.ts → Parselet-Dgymjxzd.d.ts} +19 -3
  19. package/dist/{Token-CbP_OutD.d.cts → Token-D8f7yaz1.d.cts} +17 -0
  20. package/dist/{Token-CbP_OutD.d.ts → Token-D8f7yaz1.d.ts} +17 -0
  21. package/dist/{TokenNormalizer-CLBtiE8M.d.ts → TokenNormalizer-IF7nPRMp.d.ts} +1 -1
  22. package/dist/{TokenNormalizer-CjTDmHgB.d.cts → TokenNormalizer-Pe3_390t.d.cts} +1 -1
  23. package/dist/{ScopeManager-B636am7Y.d.ts → VMBuiltins-CZiZRKn-.d.ts} +91 -9
  24. package/dist/{ScopeManager-CdwX0VTw.d.cts → VMBuiltins-kv4rr0y5.d.cts} +91 -9
  25. package/dist/{VMCheckpoints-DDlxNssY.d.ts → VMCheckpoints-DXze6ypg.d.ts} +2 -2
  26. package/dist/{VMCheckpoints-CYqeq8IV.d.cts → VMCheckpoints-yun4ocSv.d.cts} +2 -2
  27. package/dist/{Value-Ds3Gy07C.d.cts → Value-BYHw-x7q.d.cts} +57 -1
  28. package/dist/{Value-Ds3Gy07C.d.ts → Value-BYHw-x7q.d.ts} +57 -1
  29. package/dist/{WorkerError-B1dF3VYT.d.cts → WorkerError-BLZyNq6M.d.cts} +1 -1
  30. package/dist/{WorkerError-dneODN-u.d.ts → WorkerError-CfBJYueR.d.ts} +1 -1
  31. package/dist/chunk-2SYYKQ4Q.cjs +2 -0
  32. package/dist/chunk-2SYYKQ4Q.cjs.map +1 -0
  33. package/dist/chunk-6EYKVQT3.cjs +2 -0
  34. package/dist/chunk-6EYKVQT3.cjs.map +1 -0
  35. package/dist/chunk-7RC6RBS6.cjs +2 -0
  36. package/dist/chunk-7RC6RBS6.cjs.map +1 -0
  37. package/dist/chunk-AZX4NTYN.cjs +3 -0
  38. package/dist/chunk-AZX4NTYN.cjs.map +1 -0
  39. package/dist/{chunk-JFZ5SLF7.js → chunk-BCR53EIL.js} +2 -2
  40. package/dist/{chunk-JFZ5SLF7.js.map → chunk-BCR53EIL.js.map} +1 -1
  41. package/dist/chunk-BCY2WY5P.js +5 -0
  42. package/dist/chunk-BCY2WY5P.js.map +1 -0
  43. package/dist/chunk-BLJ6E577.js +2 -0
  44. package/dist/chunk-BLJ6E577.js.map +1 -0
  45. package/dist/chunk-CL7DM2FX.js +2 -0
  46. package/dist/chunk-CL7DM2FX.js.map +1 -0
  47. package/dist/{chunk-BMXYR5LI.cjs → chunk-CQLCTKMX.cjs} +2 -2
  48. package/dist/{chunk-BMXYR5LI.cjs.map → chunk-CQLCTKMX.cjs.map} +1 -1
  49. package/dist/chunk-D4VBWPWN.js +2 -0
  50. package/dist/chunk-D4VBWPWN.js.map +1 -0
  51. package/dist/chunk-DFMAZ6XM.cjs +3 -0
  52. package/dist/chunk-DFMAZ6XM.cjs.map +1 -0
  53. package/dist/chunk-E4HAKNBQ.cjs +2 -0
  54. package/dist/chunk-E4HAKNBQ.cjs.map +1 -0
  55. package/dist/{chunk-XHQYHXRE.js → chunk-ESZNJQ2C.js} +3 -3
  56. package/dist/{chunk-XHQYHXRE.js.map → chunk-ESZNJQ2C.js.map} +1 -1
  57. package/dist/{chunk-IJMNVBIS.js → chunk-FAO6DQ74.js} +2 -2
  58. package/dist/chunk-FAO6DQ74.js.map +1 -0
  59. package/dist/{chunk-WGP4UUO5.cjs → chunk-FDKTESBC.cjs} +2 -2
  60. package/dist/{chunk-WGP4UUO5.cjs.map → chunk-FDKTESBC.cjs.map} +1 -1
  61. package/dist/{chunk-NEGZZB7F.cjs → chunk-G2V33LFM.cjs} +2 -2
  62. package/dist/{chunk-NEGZZB7F.cjs.map → chunk-G2V33LFM.cjs.map} +1 -1
  63. package/dist/chunk-GJZIJK2Q.cjs +2 -0
  64. package/dist/chunk-GJZIJK2Q.cjs.map +1 -0
  65. package/dist/chunk-GVL3ZMS7.cjs +2 -0
  66. package/dist/chunk-GVL3ZMS7.cjs.map +1 -0
  67. package/dist/{chunk-YBQPEWT7.cjs → chunk-GXO7TSXQ.cjs} +3 -3
  68. package/dist/chunk-GXO7TSXQ.cjs.map +1 -0
  69. package/dist/{chunk-OONQ3V3I.js → chunk-HANGBVEE.js} +2 -2
  70. package/dist/{chunk-OONQ3V3I.js.map → chunk-HANGBVEE.js.map} +1 -1
  71. package/dist/chunk-J4K72CQN.js +2 -0
  72. package/dist/chunk-J4K72CQN.js.map +1 -0
  73. package/dist/{chunk-72PYPENZ.js → chunk-LE6WZLJ4.js} +2 -2
  74. package/dist/{chunk-72PYPENZ.js.map → chunk-LE6WZLJ4.js.map} +1 -1
  75. package/dist/chunk-LQIRBP4Q.js +2 -0
  76. package/dist/chunk-LQIRBP4Q.js.map +1 -0
  77. package/dist/{chunk-RDYXH7ML.js → chunk-LTUYWJGO.js} +2 -2
  78. package/dist/{chunk-RDYXH7ML.js.map → chunk-LTUYWJGO.js.map} +1 -1
  79. package/dist/chunk-O5PO4D2A.cjs +2 -0
  80. package/dist/chunk-O5PO4D2A.cjs.map +1 -0
  81. package/dist/chunk-PQFI55AC.js +3 -0
  82. package/dist/chunk-PQFI55AC.js.map +1 -0
  83. package/dist/chunk-QQHHZPEW.cjs +2 -0
  84. package/dist/chunk-QQHHZPEW.cjs.map +1 -0
  85. package/dist/chunk-REZQFPVX.js +2 -0
  86. package/dist/chunk-REZQFPVX.js.map +1 -0
  87. package/dist/chunk-RRUGQ6DM.js +2 -0
  88. package/dist/chunk-RRUGQ6DM.js.map +1 -0
  89. package/dist/chunk-S3ODNMJS.js +2 -0
  90. package/dist/chunk-S3ODNMJS.js.map +1 -0
  91. package/dist/{chunk-SAF3B3AX.cjs → chunk-SE6ZCGZ5.cjs} +2 -2
  92. package/dist/{chunk-SAF3B3AX.cjs.map → chunk-SE6ZCGZ5.cjs.map} +1 -1
  93. package/dist/chunk-TC23XEAV.js +2 -0
  94. package/dist/chunk-TC23XEAV.js.map +1 -0
  95. package/dist/{chunk-FYAMQFZZ.cjs → chunk-TMQ37JQY.cjs} +3 -3
  96. package/dist/{chunk-FYAMQFZZ.cjs.map → chunk-TMQ37JQY.cjs.map} +1 -1
  97. package/dist/chunk-TPPM4QSS.cjs +2 -0
  98. package/dist/chunk-TPPM4QSS.cjs.map +1 -0
  99. package/dist/chunk-UVHD7BBC.js +3 -0
  100. package/dist/{chunk-ZDCZ5IDD.js.map → chunk-UVHD7BBC.js.map} +1 -1
  101. package/dist/{chunk-57PSJQQW.js → chunk-VB6QMU2W.js} +3 -3
  102. package/dist/chunk-VB6QMU2W.js.map +1 -0
  103. package/dist/chunk-VQO54ZMA.js +2 -0
  104. package/dist/chunk-VQO54ZMA.js.map +1 -0
  105. package/dist/{chunk-7DP57BA7.js → chunk-Y7XRA2EV.js} +2 -2
  106. package/dist/{chunk-7DP57BA7.js.map → chunk-Y7XRA2EV.js.map} +1 -1
  107. package/dist/{chunk-5IJD5L3O.cjs → chunk-YBQOQTVL.cjs} +2 -2
  108. package/dist/chunk-YBQOQTVL.cjs.map +1 -0
  109. package/dist/{chunk-EL2XUOWX.js → chunk-YG7UWQFV.js} +2 -2
  110. package/dist/{chunk-EL2XUOWX.js.map → chunk-YG7UWQFV.js.map} +1 -1
  111. package/dist/chunk-YSHWNCDH.cjs +5 -0
  112. package/dist/chunk-YSHWNCDH.cjs.map +1 -0
  113. package/dist/chunk-ZC2NPRLO.js +3 -0
  114. package/dist/chunk-ZC2NPRLO.js.map +1 -0
  115. package/dist/{chunk-FYTB7SDP.cjs → chunk-ZDJTDFTR.cjs} +2 -2
  116. package/dist/{chunk-FYTB7SDP.cjs.map → chunk-ZDJTDFTR.cjs.map} +1 -1
  117. package/dist/chunk-ZE5KKMBV.cjs +2 -0
  118. package/dist/chunk-ZE5KKMBV.cjs.map +1 -0
  119. package/dist/{chunk-4BAUQE6A.cjs → chunk-ZPHUTCJ5.cjs} +3 -3
  120. package/dist/{chunk-4BAUQE6A.cjs.map → chunk-ZPHUTCJ5.cjs.map} +1 -1
  121. package/dist/{chunk-GBCN7FNV.cjs → chunk-ZSLVLMO5.cjs} +2 -2
  122. package/dist/{chunk-GBCN7FNV.cjs.map → chunk-ZSLVLMO5.cjs.map} +1 -1
  123. package/dist/constants.cjs +1 -1
  124. package/dist/constants.d.cts +1 -1
  125. package/dist/constants.d.ts +1 -1
  126. package/dist/constants.js +1 -1
  127. package/dist/engine.cjs +1 -1
  128. package/dist/engine.d.cts +14 -12
  129. package/dist/engine.d.ts +14 -12
  130. package/dist/engine.js +1 -1
  131. package/dist/errors.cjs +1 -1
  132. package/dist/errors.d.cts +3 -3
  133. package/dist/errors.d.ts +3 -3
  134. package/dist/errors.js +1 -1
  135. package/dist/format.cjs +1 -1
  136. package/dist/format.d.cts +4 -3
  137. package/dist/format.d.ts +4 -3
  138. package/dist/format.js +1 -1
  139. package/dist/index.cjs +1 -1
  140. package/dist/index.cjs.map +1 -1
  141. package/dist/index.d.cts +15 -13
  142. package/dist/index.d.ts +15 -13
  143. package/dist/index.js +1 -1
  144. package/dist/index.js.map +1 -1
  145. package/dist/language.d.cts +12 -11
  146. package/dist/language.d.ts +12 -11
  147. package/dist/lexer.cjs +1 -1
  148. package/dist/lexer.d.cts +4 -4
  149. package/dist/lexer.d.ts +4 -4
  150. package/dist/lexer.js +1 -1
  151. package/dist/normalizer.cjs +1 -1
  152. package/dist/normalizer.d.cts +3 -3
  153. package/dist/normalizer.d.ts +3 -3
  154. package/dist/normalizer.js +1 -1
  155. package/dist/packages.cjs +1 -1
  156. package/dist/packages.d.cts +11 -10
  157. package/dist/packages.d.ts +11 -10
  158. package/dist/packages.js +1 -1
  159. package/dist/parser.cjs +1 -1
  160. package/dist/parser.d.cts +5 -4
  161. package/dist/parser.d.ts +5 -4
  162. package/dist/parser.js +1 -1
  163. package/dist/{pipeline-69q2tsLE.d.cts → pipeline-BYkKNpql.d.cts} +1 -1
  164. package/dist/{pipeline-DTqGLPsV.d.ts → pipeline-Cl7KW8CB.d.ts} +1 -1
  165. package/dist/resolvers.d.cts +2 -2
  166. package/dist/resolvers.d.ts +2 -2
  167. package/dist/temporal.cjs +2 -0
  168. package/dist/temporal.cjs.map +1 -0
  169. package/dist/temporal.d.cts +201 -0
  170. package/dist/temporal.d.ts +201 -0
  171. package/dist/temporal.js +2 -0
  172. package/dist/temporal.js.map +1 -0
  173. package/dist/testing.cjs +2 -2
  174. package/dist/testing.cjs.map +1 -1
  175. package/dist/testing.d.cts +12 -11
  176. package/dist/testing.d.ts +12 -11
  177. package/dist/testing.js +1 -1
  178. package/dist/testing.js.map +1 -1
  179. package/dist/uom.cjs +1 -1
  180. package/dist/uom.d.cts +2 -2
  181. package/dist/uom.d.ts +2 -2
  182. package/dist/uom.js +1 -1
  183. package/dist/vm.cjs +1 -1
  184. package/dist/vm.cjs.map +1 -1
  185. package/dist/vm.d.cts +8 -56
  186. package/dist/vm.d.ts +8 -56
  187. package/dist/vm.js +1 -1
  188. package/dist/vm.js.map +1 -1
  189. package/dist/worker.cjs +2 -2
  190. package/dist/worker.cjs.map +1 -1
  191. package/dist/worker.d.cts +35 -13
  192. package/dist/worker.d.ts +35 -13
  193. package/dist/worker.js +2 -2
  194. package/dist/worker.js.map +1 -1
  195. package/package.json +12 -1
  196. package/dist/chunk-4BRTUFTH.js +0 -2
  197. package/dist/chunk-4BRTUFTH.js.map +0 -1
  198. package/dist/chunk-4NZXCHQL.cjs +0 -2
  199. package/dist/chunk-4NZXCHQL.cjs.map +0 -1
  200. package/dist/chunk-57PSJQQW.js.map +0 -1
  201. package/dist/chunk-5IJD5L3O.cjs.map +0 -1
  202. package/dist/chunk-634ILVMP.cjs +0 -2
  203. package/dist/chunk-634ILVMP.cjs.map +0 -1
  204. package/dist/chunk-63ZOOUOL.js +0 -2
  205. package/dist/chunk-63ZOOUOL.js.map +0 -1
  206. package/dist/chunk-77KI7AKJ.cjs +0 -2
  207. package/dist/chunk-77KI7AKJ.cjs.map +0 -1
  208. package/dist/chunk-7N3IJSWF.js +0 -5
  209. package/dist/chunk-7N3IJSWF.js.map +0 -1
  210. package/dist/chunk-DUYTXLO2.js +0 -2
  211. package/dist/chunk-DUYTXLO2.js.map +0 -1
  212. package/dist/chunk-IJMNVBIS.js.map +0 -1
  213. package/dist/chunk-JSM3O7EM.cjs +0 -2
  214. package/dist/chunk-JSM3O7EM.cjs.map +0 -1
  215. package/dist/chunk-MZMA32NE.js +0 -3
  216. package/dist/chunk-MZMA32NE.js.map +0 -1
  217. package/dist/chunk-N4SSR7Q6.js +0 -2
  218. package/dist/chunk-N4SSR7Q6.js.map +0 -1
  219. package/dist/chunk-NMU5E7W7.js +0 -2
  220. package/dist/chunk-NMU5E7W7.js.map +0 -1
  221. package/dist/chunk-OB2VX4IL.js +0 -2
  222. package/dist/chunk-OB2VX4IL.js.map +0 -1
  223. package/dist/chunk-RAPEZR5L.cjs +0 -2
  224. package/dist/chunk-RAPEZR5L.cjs.map +0 -1
  225. package/dist/chunk-SPOVFRZO.cjs +0 -5
  226. package/dist/chunk-SPOVFRZO.cjs.map +0 -1
  227. package/dist/chunk-SQHBOWES.cjs +0 -2
  228. package/dist/chunk-SQHBOWES.cjs.map +0 -1
  229. package/dist/chunk-UF5XMZTT.js +0 -2
  230. package/dist/chunk-UF5XMZTT.js.map +0 -1
  231. package/dist/chunk-UV3EUIBT.cjs +0 -3
  232. package/dist/chunk-UV3EUIBT.cjs.map +0 -1
  233. package/dist/chunk-VMSCRVNX.cjs +0 -2
  234. package/dist/chunk-VMSCRVNX.cjs.map +0 -1
  235. package/dist/chunk-XBGK3TTU.cjs +0 -3
  236. package/dist/chunk-XBGK3TTU.cjs.map +0 -1
  237. package/dist/chunk-XX55RR4Q.js +0 -3
  238. package/dist/chunk-XX55RR4Q.js.map +0 -1
  239. package/dist/chunk-YBQPEWT7.cjs.map +0 -1
  240. package/dist/chunk-ZDCZ5IDD.js +0 -3
@@ -1,3 +1,3 @@
1
- 'use strict';var chunkTLG7VZRX_cjs=require('./chunk-TLG7VZRX.cjs'),chunkYBQPEWT7_cjs=require('./chunk-YBQPEWT7.cjs');var b=new Set(["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLE","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UYW","UZS","VED","VES","VND","VUV","WST","XAF","XCD","XCG","XOF","XPF","YER","ZAR","ZMW","ZWG"]);function O(N){return b.has(N.toUpperCase())}var D={API_ERROR:"CURRENCY_API_ERROR",UNKNOWN_CODE:"UNKNOWN_CURRENCY_CODE",CRYPTO_API_ERROR:"CRYPTO_PRICE_API_ERROR"},a=class a{constructor(){this.baseTables=new Map;}isCryptoCode(t){return Object.prototype.hasOwnProperty.call(a.CRYPTO_IDS,t.toUpperCase())}async getRate(t,e,r){let n=t.toUpperCase(),s=e.toUpperCase();if(this.isCryptoCode(n)||this.isCryptoCode(s))return this.getCryptoRate(n,s,r);let{signal:R,cleanup:l}=chunkTLG7VZRX_cjs.a(r,a.FETCH_TIMEOUT_MS,"Currency API fetch");try{let u=new URLSearchParams({base:n}),i=await fetch(`https://api.frankfurter.dev/v2/rates?${u.toString()}`,{signal:R});if(!i.ok)throw chunkYBQPEWT7_cjs.c.external(D.API_ERROR,`Currency API returned ${i.status}`,{status:i.status});let c=await i.json(),C=Array.isArray(c)?Object.fromEntries(c.filter(o=>{if(typeof o!="object"||o===null)return !1;let d=o;return typeof d.quote=="string"&&typeof d.rate=="number"}).map(o=>[o.quote.toUpperCase(),o.rate])):c.rates??{};if(C[s]===void 0)throw chunkYBQPEWT7_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${s}`,{code:s});return this.baseTables.set(n,{fetchedAt:Date.now(),rates:{...C,[n]:1}}),C[s]}finally{l();}}async getCryptoRate(t,e,r){let{signal:n,cleanup:s}=chunkTLG7VZRX_cjs.a(r,a.FETCH_TIMEOUT_MS,"Crypto price API fetch");try{let R=this.isCryptoCode(t),l=this.isCryptoCode(e),u;if(R&&l){let i=a.CRYPTO_IDS[t],c=a.CRYPTO_IDS[e],C=await this.fetchCoinGeckoPrices([i,c],"usd",n),o=C[i]?.usd,d=C[c]?.usd;if(typeof o!="number")throw chunkYBQPEWT7_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${t}`,{code:t});if(typeof d!="number")throw chunkYBQPEWT7_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${e}`,{code:e});u=o/d;}else if(R){let i=a.CRYPTO_IDS[t],c=e.toLowerCase(),o=(await this.fetchCoinGeckoPrices([i],c,n))[i]?.[c];if(typeof o!="number")throw chunkYBQPEWT7_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${e}`,{code:e});u=o;}else {let i=a.CRYPTO_IDS[e],c=t.toLowerCase(),o=(await this.fetchCoinGeckoPrices([i],c,n))[i]?.[c];if(typeof o!="number")throw chunkYBQPEWT7_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${t}`,{code:t});u=1/o;}return this.baseTables.set(t,{fetchedAt:Date.now(),rates:{[t]:1,[e]:u}}),u}finally{s();}}async fetchCoinGeckoPrices(t,e,r){let n=new URLSearchParams({ids:t.join(","),vs_currencies:e}),s=await fetch(`https://api.coingecko.com/api/v3/simple/price?${n.toString()}`,{signal:r});if(!s.ok)throw chunkYBQPEWT7_cjs.c.external(D.CRYPTO_API_ERROR,`Crypto price API returned ${s.status}`,{status:s.status});return s.json()}primeRates(t,e){let r=t.toUpperCase();this.baseTables.set(r,{fetchedAt:Date.now(),rates:{...e,[r]:1}});}clearRates(){this.baseTables.clear();}getRateSync(t,e){let r=t.toUpperCase(),n=e.toUpperCase();if(r===n)return 1;let s=Date.now();for(let R of this.baseTables.values()){if(s-R.fetchedAt>a.RATE_FRESHNESS_MS)continue;let l=R.rates[r],u=R.rates[n];if(l&&u)return u/l}return null}async convert(t,e,r){let n=await this.getRate(e,r);return t*n}getAllRates(){let t=Date.now(),e={},r=false;for(let[n,s]of this.baseTables)if(!(t-s.fetchedAt>a.RATE_FRESHNESS_MS))for(let[R,l]of Object.entries(s.rates))e[`${n}:${R}`]=l,r=true;return r?e:null}hasRates(){return this.getAllRates()!==null}convertSync(t,e,r){let n=this.getRateSync(e,r);return n===null?null:t*n}isCurrency(t){return O(t)||this.isCryptoCode(t)}};a.RATE_FRESHNESS_MS=900*1e3,a.CRYPTO_IDS={BTC:"bitcoin",ETH:"ethereum",SOL:"solana",XRP:"ripple",ADA:"cardano",DOGE:"dogecoin",DOT:"polkadot"},a.FETCH_TIMEOUT_MS=1e4;var f=a,p=new f,g=p;
2
- exports.a=f;exports.b=p;exports.c=g;//# sourceMappingURL=chunk-FYAMQFZZ.cjs.map
3
- //# sourceMappingURL=chunk-FYAMQFZZ.cjs.map
1
+ 'use strict';var chunkTLG7VZRX_cjs=require('./chunk-TLG7VZRX.cjs'),chunkGXO7TSXQ_cjs=require('./chunk-GXO7TSXQ.cjs');var b=new Set(["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLE","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UYW","UZS","VED","VES","VND","VUV","WST","XAF","XCD","XCG","XOF","XPF","YER","ZAR","ZMW","ZWG"]);function O(N){return b.has(N.toUpperCase())}var D={API_ERROR:"CURRENCY_API_ERROR",UNKNOWN_CODE:"UNKNOWN_CURRENCY_CODE",CRYPTO_API_ERROR:"CRYPTO_PRICE_API_ERROR"},a=class a{constructor(){this.baseTables=new Map;}isCryptoCode(t){return Object.prototype.hasOwnProperty.call(a.CRYPTO_IDS,t.toUpperCase())}async getRate(t,e,r){let n=t.toUpperCase(),s=e.toUpperCase();if(this.isCryptoCode(n)||this.isCryptoCode(s))return this.getCryptoRate(n,s,r);let{signal:R,cleanup:l}=chunkTLG7VZRX_cjs.a(r,a.FETCH_TIMEOUT_MS,"Currency API fetch");try{let u=new URLSearchParams({base:n}),i=await fetch(`https://api.frankfurter.dev/v2/rates?${u.toString()}`,{signal:R});if(!i.ok)throw chunkGXO7TSXQ_cjs.c.external(D.API_ERROR,`Currency API returned ${i.status}`,{status:i.status});let c=await i.json(),C=Array.isArray(c)?Object.fromEntries(c.filter(o=>{if(typeof o!="object"||o===null)return !1;let d=o;return typeof d.quote=="string"&&typeof d.rate=="number"}).map(o=>[o.quote.toUpperCase(),o.rate])):c.rates??{};if(C[s]===void 0)throw chunkGXO7TSXQ_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${s}`,{code:s});return this.baseTables.set(n,{fetchedAt:Date.now(),rates:{...C,[n]:1}}),C[s]}finally{l();}}async getCryptoRate(t,e,r){let{signal:n,cleanup:s}=chunkTLG7VZRX_cjs.a(r,a.FETCH_TIMEOUT_MS,"Crypto price API fetch");try{let R=this.isCryptoCode(t),l=this.isCryptoCode(e),u;if(R&&l){let i=a.CRYPTO_IDS[t],c=a.CRYPTO_IDS[e],C=await this.fetchCoinGeckoPrices([i,c],"usd",n),o=C[i]?.usd,d=C[c]?.usd;if(typeof o!="number")throw chunkGXO7TSXQ_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${t}`,{code:t});if(typeof d!="number")throw chunkGXO7TSXQ_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${e}`,{code:e});u=o/d;}else if(R){let i=a.CRYPTO_IDS[t],c=e.toLowerCase(),o=(await this.fetchCoinGeckoPrices([i],c,n))[i]?.[c];if(typeof o!="number")throw chunkGXO7TSXQ_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${e}`,{code:e});u=o;}else {let i=a.CRYPTO_IDS[e],c=t.toLowerCase(),o=(await this.fetchCoinGeckoPrices([i],c,n))[i]?.[c];if(typeof o!="number")throw chunkGXO7TSXQ_cjs.c.validation(D.UNKNOWN_CODE,`Unknown currency: ${t}`,{code:t});u=1/o;}return this.baseTables.set(t,{fetchedAt:Date.now(),rates:{[t]:1,[e]:u}}),u}finally{s();}}async fetchCoinGeckoPrices(t,e,r){let n=new URLSearchParams({ids:t.join(","),vs_currencies:e}),s=await fetch(`https://api.coingecko.com/api/v3/simple/price?${n.toString()}`,{signal:r});if(!s.ok)throw chunkGXO7TSXQ_cjs.c.external(D.CRYPTO_API_ERROR,`Crypto price API returned ${s.status}`,{status:s.status});return s.json()}primeRates(t,e){let r=t.toUpperCase();this.baseTables.set(r,{fetchedAt:Date.now(),rates:{...e,[r]:1}});}clearRates(){this.baseTables.clear();}getRateSync(t,e){let r=t.toUpperCase(),n=e.toUpperCase();if(r===n)return 1;let s=Date.now();for(let R of this.baseTables.values()){if(s-R.fetchedAt>a.RATE_FRESHNESS_MS)continue;let l=R.rates[r],u=R.rates[n];if(l&&u)return u/l}return null}async convert(t,e,r){let n=await this.getRate(e,r);return t*n}getAllRates(){let t=Date.now(),e={},r=false;for(let[n,s]of this.baseTables)if(!(t-s.fetchedAt>a.RATE_FRESHNESS_MS))for(let[R,l]of Object.entries(s.rates))e[`${n}:${R}`]=l,r=true;return r?e:null}hasRates(){return this.getAllRates()!==null}convertSync(t,e,r){let n=this.getRateSync(e,r);return n===null?null:t*n}isCurrency(t){return O(t)||this.isCryptoCode(t)}};a.RATE_FRESHNESS_MS=900*1e3,a.CRYPTO_IDS={BTC:"bitcoin",ETH:"ethereum",SOL:"solana",XRP:"ripple",ADA:"cardano",DOGE:"dogecoin",DOT:"polkadot"},a.FETCH_TIMEOUT_MS=1e4;var f=a,p=new f,g=p;
2
+ exports.a=f;exports.b=p;exports.c=g;//# sourceMappingURL=chunk-TMQ37JQY.cjs.map
3
+ //# sourceMappingURL=chunk-TMQ37JQY.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/uom/Iso4217.ts","../src/uom/CurrencyExchange.ts"],"names":["ISO_4217_CODES","isIso4217","code","CurrencyErrorCodes","_CurrencyExchangeService","from","to","signal","fromUpper","toUpper","fetchSignal","cleanup","createTimeoutSignal","query","response","ErrorFactory","data","rates","entry","candidate","fromIsCrypto","toIsCrypto","rate","fromId","toId","fromUsd","toUsd","vs","value","priceOfToInFrom","ids","vsCurrency","base","baseUpper","now","table","fromRate","toRate","snapshot","any","CurrencyExchangeService","currencyExchangeService","sharedCurrencyExchange"],"mappings":"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","file":"chunk-FYAMQFZZ.cjs","sourcesContent":["/**\n * Every active ISO 4217 currency code.\n *\n * This exists because `CurrencyExchange.isCurrency()` used to hold a\n * hand-written list of forty-six codes, and a code missing from it did not\n * error: `$100 in UAH` returned the original hundred dollars, unconverted, as\n * though the rate were 1. A wrong answer, not a missing feature.\n *\n * The list is the ISO 4217 active set, so \"is this a currency\" is answered by\n * the standard rather than by whichever codes happened to get added. Whether a\n * *rate* is available for one is a separate question, answered at resolution\n * time by whatever the exchange provider supports; conflating the two is what\n * produced the silent failure.\n *\n * Deliberately excluded:\n * - The historical/withdrawn codes (DEM, FRF, and the rest). They are not\n * active, no provider quotes them, and recognising them would only move the\n * failure later.\n * - The X-series non-currencies: XAU/XAG/XPT/XPD (metals), XDR (IMF special\n * drawing rights), XTS (reserved for testing) and XXX (explicitly \"no\n * currency\"). XXX in particular must never resolve.\n *\n * Cryptocurrencies are not here either. They are not ISO 4217 and are tracked\n * separately in `CurrencyExchangeService.CRYPTO_IDS`.\n */\nexport const ISO_4217_CODES: ReadonlySet<string> = new Set([\n\t\"AED\", \"AFN\", \"ALL\", \"AMD\", \"ANG\", \"AOA\", \"ARS\", \"AUD\", \"AWG\", \"AZN\",\n\t\"BAM\", \"BBD\", \"BDT\", \"BGN\", \"BHD\", \"BIF\", \"BMD\", \"BND\", \"BOB\", \"BOV\",\n\t\"BRL\", \"BSD\", \"BTN\", \"BWP\", \"BYN\", \"BZD\",\n\t\"CAD\", \"CDF\", \"CHE\", \"CHF\", \"CHW\", \"CLF\", \"CLP\", \"CNY\", \"COP\", \"COU\",\n\t\"CRC\", \"CUP\", \"CVE\", \"CZK\",\n\t\"DJF\", \"DKK\", \"DOP\", \"DZD\",\n\t\"EGP\", \"ERN\", \"ETB\", \"EUR\",\n\t\"FJD\", \"FKP\",\n\t\"GBP\", \"GEL\", \"GHS\", \"GIP\", \"GMD\", \"GNF\", \"GTQ\", \"GYD\",\n\t\"HKD\", \"HNL\", \"HTG\", \"HUF\",\n\t\"IDR\", \"ILS\", \"INR\", \"IQD\", \"IRR\", \"ISK\",\n\t\"JMD\", \"JOD\", \"JPY\",\n\t\"KES\", \"KGS\", \"KHR\", \"KMF\", \"KPW\", \"KRW\", \"KWD\", \"KYD\", \"KZT\",\n\t\"LAK\", \"LBP\", \"LKR\", \"LRD\", \"LSL\", \"LYD\",\n\t\"MAD\", \"MDL\", \"MGA\", \"MKD\", \"MMK\", \"MNT\", \"MOP\", \"MRU\", \"MUR\", \"MVR\",\n\t\"MWK\", \"MXN\", \"MXV\", \"MYR\", \"MZN\",\n\t\"NAD\", \"NGN\", \"NIO\", \"NOK\", \"NPR\", \"NZD\",\n\t\"OMR\",\n\t\"PAB\", \"PEN\", \"PGK\", \"PHP\", \"PKR\", \"PLN\", \"PYG\",\n\t\"QAR\",\n\t\"RON\", \"RSD\", \"RUB\", \"RWF\",\n\t\"SAR\", \"SBD\", \"SCR\", \"SDG\", \"SEK\", \"SGD\", \"SHP\", \"SLE\", \"SOS\", \"SRD\",\n\t\"SSP\", \"STN\", \"SVC\", \"SYP\", \"SZL\",\n\t\"THB\", \"TJS\", \"TMT\", \"TND\", \"TOP\", \"TRY\", \"TTD\", \"TWD\", \"TZS\",\n\t\"UAH\", \"UGX\", \"USD\", \"USN\", \"UYI\", \"UYU\", \"UYW\", \"UZS\",\n\t\"VED\", \"VES\", \"VND\", \"VUV\",\n\t\"WST\",\n\t\"XAF\", \"XCD\", \"XCG\", \"XOF\", \"XPF\",\n\t\"YER\",\n\t\"ZAR\", \"ZMW\", \"ZWG\",\n]);\n\n/**\n * Whether `code` is an active ISO 4217 currency code.\n *\n * @param code - A three-letter code, in any case.\n */\nexport function isIso4217(code: string): boolean {\n\treturn ISO_4217_CODES.has(code.toUpperCase());\n}\n","/**\n * Production-grade currency exchange service with scalable architecture\n * Integrates with DataQueryService for worker-based execution\n */\n\nimport { isIso4217 } from \"@solve-js/uom/Iso4217\";\nimport { createTimeoutSignal } from \"@solve-js/utilities/TimeoutSignal\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * Error codes for this service. Co-located rather than unioned into\n * `errors/ErrorCode.ts`'s core catalog (that catalog is scoped to the\n * parser/VM/engine/errors/config/lexer layers, not yet the ~17 domain\n * packages. See that file's module doc for the intended per-package\n * pattern this follows).\n */\nexport const CurrencyErrorCodes = {\n /** Frankfurter's rates endpoint returned a non-OK HTTP status. */\n API_ERROR: \"CURRENCY_API_ERROR\",\n /** A requested currency/crypto code isn't in the fetched rate table, an unrecognized code, not an API failure. */\n UNKNOWN_CODE: \"UNKNOWN_CURRENCY_CODE\",\n /** CoinGecko's simple-price endpoint returned a non-OK HTTP status. */\n CRYPTO_API_ERROR: \"CRYPTO_PRICE_API_ERROR\",\n} as const;\n\n// ============================================================================\n// CURRENCY EXCHANGE SERVICE\n// ============================================================================\n\n/**\n * Caches exchange rates fetched from an external source.\n *\n * Rates are global market data rather than per-engine configuration, which is\n * why one instance is shared. Two engines with private copies would fetch the\n * same endpoint twice and could disagree about one pair at one moment. See\n * `engine/EngineContext.ts`.\n */\nexport class CurrencyExchangeService {\n /**\n * Live rate tables cached from successful getRate() fetches, keyed by\n * uppercase base currency. Each table holds every rate the API returned\n * for that base (plus the base itself at 1), so any pair whose two codes\n * appear in one fresh table can be served synchronously, including\n * cross pairs via triangulation (EUR→GBP through a USD-base table).\n * Stale tables are ignored, not evicted; the next successful fetch for\n * the same base overwrites them.\n */\n private baseTables: Map<string, { fetchedAt: number; rates: Record<string, number> }> = new Map();\n\n /**\n * How long a fetched rate may be served synchronously by getRateSync().\n * Beyond this window callers fall through to the async path (expression\n * shows Pending until the fetch lands).\n */\n private static readonly RATE_FRESHNESS_MS = 15 * 60 * 1000;\n\n /**\n * Ticker → CoinGecko coin id, for the cryptocurrencies `isCurrency()`\n * recognizes. Frankfurter (the fiat rate source below) is ECB reference\n * rates only and has no concept of BTC/ETH/etc, routing a crypto code\n * through it as `base=BTC` fails outright, which is why crypto pairs\n * previously never resolved (see CurrencyAsyncResolver/VM.ts's ADD\n * handling for the two bugs that let that failure pass silently instead\n * of surfacing as a real fetch).\n */\n private static readonly CRYPTO_IDS: Record<string, string> = {\n BTC: \"bitcoin\", ETH: \"ethereum\", SOL: \"solana\", XRP: \"ripple\",\n ADA: \"cardano\", DOGE: \"dogecoin\", DOT: \"polkadot\",\n };\n\n private isCryptoCode(code: string): boolean {\n // An own-property check, not `in`: `in` also answers for everything on\n // Object.prototype, so a code spelt like an inherited name would pass.\n return Object.prototype.hasOwnProperty.call(CurrencyExchangeService.CRYPTO_IDS, code.toUpperCase());\n }\n\n constructor() {}\n\n // ------------------------------------------------------------------------\n // RATE FETCHING\n // ------------------------------------------------------------------------\n\n /**\n * Timeout (ms) for currency exchange rate fetches.\n *\n * If the frankfurter API doesn't respond within this window, the fetch\n * is aborted, preventing indefinite \"Pending\" states in the playground\n * and Obsidian plugin when the exchange rate API is unreachable.\n */\n private static readonly FETCH_TIMEOUT_MS = 10_000;\n\n /**\n * Fetch the live exchange rate for converting 1 unit of `from` into `to`.\n *\n * Routes cryptocurrency codes (see {@link CRYPTO_IDS}) to CoinGecko and\n * everything else to Frankfurter (ECB reference rates, fiat-only). On\n * success, caches the whole returned rate table for `from` so subsequent\n * lookups, including cross-pairs via triangulation, can be served\n * synchronously by {@link getRateSync} within the freshness window.\n *\n * @throws If the currency code is unrecognized or the fetch fails/times out.\n */\n async getRate(from: string, to: string, signal?: AbortSignal): Promise<number> {\n const fromUpper = from.toUpperCase();\n const toUpper = to.toUpperCase();\n\n if (this.isCryptoCode(fromUpper) || this.isCryptoCode(toUpper)) {\n return this.getCryptoRate(fromUpper, toUpper, signal);\n }\n\n // Combine the caller's optional abort signal with a hard timeout so a\n // hanging currency API never blocks re-evaluation indefinitely.\n const { signal: fetchSignal, cleanup } = createTimeoutSignal(\n signal,\n CurrencyExchangeService.FETCH_TIMEOUT_MS,\n \"Currency API fetch\",\n );\n\n try {\n // Built with URLSearchParams rather than interpolated. The code is\n // ISO-4217 by the time it gets here, but the query should be safe on\n // its own terms rather than by relying on a check that lives elsewhere.\n const query = new URLSearchParams({ base: fromUpper });\n const response = await fetch(`https://api.frankfurter.dev/v2/rates?${query.toString()}`, { signal: fetchSignal });\n if (!response.ok) throw ErrorFactory.external(CurrencyErrorCodes.API_ERROR, `Currency API returned ${response.status}`, { status: response.status });\n const data = await response.json();\n // The v2 endpoint returns a flat array of { date, base, quote, rate }\n // entries (one per target currency) rather than the classic v1 shape\n // { base, date, rates: { CODE: rate } }. Reading data.rates against\n // the real response is always undefined, so every conversion used to\n // throw \"Unknown currency\" no matter which currencies were requested.\n // Accept both shapes so a future API revision back to the object form\n // doesn't silently break this again.\n const rates: Record<string, number> = Array.isArray(data)\n ? Object.fromEntries(\n data\n .filter((entry: unknown): entry is { quote: string; rate: number } => {\n if (typeof entry !== \"object\" || entry === null) return false;\n const candidate = entry as { quote?: unknown; rate?: unknown };\n return typeof candidate.quote === \"string\" && typeof candidate.rate === \"number\";\n })\n .map((entry: { quote: string; rate: number }) => [entry.quote.toUpperCase(), entry.rate])\n )\n : (data.rates ?? {});\n if (rates[toUpper] === undefined) throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n\n // The API returns ALL rates for the base currency, cache the whole\n // table so subsequent conversions (including cross pairs via\n // triangulation) resolve synchronously within the freshness window\n // instead of going Pending again.\n this.baseTables.set(fromUpper, {\n fetchedAt: Date.now(),\n rates: { ...rates, [fromUpper]: 1 },\n });\n\n return rates[toUpper];\n } finally {\n cleanup();\n }\n }\n\n /**\n * Crypto rate fetch, routed through CoinGecko's no-auth simple-price\n * endpoint instead of Frankfurter (fiat-only, has no BTC/ETH concept).\n * Handles all three combinations, crypto→crypto, crypto→fiat\n * fiat→crypto, via prices denominated in USD (or the target fiat\n * directly, which CoinGecko's `vs_currencies` also accepts), then\n * caches the result as a same-shaped base table so getRateSync /\n * convertSync keep working unchanged for crypto pairs too.\n */\n private async getCryptoRate(fromUpper: string, toUpper: string, signal?: AbortSignal): Promise<number> {\n const { signal: fetchSignal, cleanup } = createTimeoutSignal(\n signal,\n CurrencyExchangeService.FETCH_TIMEOUT_MS,\n \"Crypto price API fetch\",\n );\n\n try {\n const fromIsCrypto = this.isCryptoCode(fromUpper);\n const toIsCrypto = this.isCryptoCode(toUpper);\n let rate: number;\n\n if (fromIsCrypto && toIsCrypto) {\n const fromId = CurrencyExchangeService.CRYPTO_IDS[fromUpper];\n const toId = CurrencyExchangeService.CRYPTO_IDS[toUpper];\n const data = await this.fetchCoinGeckoPrices([fromId, toId], \"usd\", fetchSignal);\n const fromUsd = data[fromId]?.usd;\n const toUsd = data[toId]?.usd;\n if (typeof fromUsd !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${fromUpper}`, { code: fromUpper });\n if (typeof toUsd !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n rate = fromUsd / toUsd;\n } else if (fromIsCrypto) {\n const fromId = CurrencyExchangeService.CRYPTO_IDS[fromUpper];\n const vs = toUpper.toLowerCase();\n const data = await this.fetchCoinGeckoPrices([fromId], vs, fetchSignal);\n const value = data[fromId]?.[vs];\n if (typeof value !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n rate = value;\n } else {\n const toId = CurrencyExchangeService.CRYPTO_IDS[toUpper];\n const vs = fromUpper.toLowerCase();\n const data = await this.fetchCoinGeckoPrices([toId], vs, fetchSignal);\n const priceOfToInFrom = data[toId]?.[vs];\n if (typeof priceOfToInFrom !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${fromUpper}`, { code: fromUpper });\n rate = 1 / priceOfToInFrom;\n }\n\n // Cache as a single-pair base table, same shape Frankfurter fetches\n // produce, so getRateSync/convertSync's triangulation logic doesn't\n // need to know or care which source a rate came from.\n this.baseTables.set(fromUpper, {\n fetchedAt: Date.now(),\n rates: { [fromUpper]: 1, [toUpper]: rate },\n });\n\n return rate;\n } finally {\n cleanup();\n }\n }\n\n private async fetchCoinGeckoPrices(ids: string[], vsCurrency: string, signal: AbortSignal): Promise<Record<string, Record<string, number>>> {\n const query = new URLSearchParams({ ids: ids.join(\",\"), vs_currencies: vsCurrency });\n const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?${query.toString()}`, { signal });\n if (!response.ok) throw ErrorFactory.external(CurrencyErrorCodes.CRYPTO_API_ERROR, `Crypto price API returned ${response.status}`, { status: response.status });\n return response.json();\n }\n\n /**\n * Seed a base rate table without a network fetch.\n *\n * Intended for tests and for future user-provided offline rates\n * production live data always comes from {@link getRate}. Seeded rates\n * obey the same freshness window as fetched ones.\n *\n * @param base - Base currency code (e.g. \"USD\").\n * @param rates - Map of currency code → rate relative to the base.\n */\n primeRates(base: string, rates: Record<string, number>): void {\n const baseUpper = base.toUpperCase();\n this.baseTables.set(baseUpper, {\n fetchedAt: Date.now(),\n rates: { ...rates, [baseUpper]: 1 },\n });\n }\n\n /**\n * Drop every cached/primed rate table.\n *\n * Mainly for test isolation: {@link sharedCurrencyExchange} is a\n * module-level singleton, so a rate primed or fetched by one test can\n * silently leak into a later test in the same file. Also usable in\n * production if a caller ever wants to force a full re-fetch.\n */\n clearRates(): void {\n this.baseTables.clear();\n }\n\n /**\n * Synchronous rate lookup: `1` for same-currency pairs, a cached LIVE\n * rate if one was fetched within {@link RATE_FRESHNESS_MS}, otherwise\n * `null`, callers fall through to the async fetch path and the\n * expression shows Pending until real data arrives.\n *\n * There is deliberately no hardcoded fallback table: a stale made-up\n * rate presented as a real conversion is worse than a Pending state.\n */\n getRateSync(from: string, to: string): number | null {\n const fromUpper = from.toUpperCase();\n const toUpper = to.toUpperCase();\n if (fromUpper === toUpper) {\n return 1;\n }\n const now = Date.now();\n for (const table of this.baseTables.values()) {\n if (now - table.fetchedAt > CurrencyExchangeService.RATE_FRESHNESS_MS) continue;\n const fromRate = table.rates[fromUpper];\n const toRate = table.rates[toUpper];\n if (fromRate && toRate) {\n return toRate / fromRate;\n }\n }\n return null;\n }\n\n /** Convert `value` from `from` to `to` using a freshly-fetched live rate (see {@link getRate}). */\n async convert(value: number, from: string, to: string): Promise<number> {\n const rate = await this.getRate(from, to);\n return value * rate;\n }\n\n /**\n * Get all currently cached fresh rates, keyed \"FROM:TO\".\n * @returns Snapshot of fresh live rates, or null when none are cached.\n */\n getAllRates(): Record<string, number> | null {\n const now = Date.now();\n const snapshot: Record<string, number> = {};\n let any = false;\n for (const [base, table] of this.baseTables) {\n if (now - table.fetchedAt > CurrencyExchangeService.RATE_FRESHNESS_MS) continue;\n for (const [code, rate] of Object.entries(table.rates)) {\n snapshot[`${base}:${code}`] = rate;\n any = true;\n }\n }\n return any ? snapshot : null;\n }\n\n /**\n * Check whether any fresh live rates are currently cached.\n */\n hasRates(): boolean {\n return this.getAllRates() !== null;\n }\n\n /**\n * Synchronous conversion using cached rates only\n * Returns null if rate not in cache\n */\n convertSync(value: number, from: string, to: string): number | null {\n const rate = this.getRateSync(from, to);\n if (rate === null) return null;\n return value * rate;\n }\n\n // ------------------------------------------------------------------------\n // CURRENCY VALIDATION\n // ------------------------------------------------------------------------\n\n /**\n * Check whether `code` is a recognized currency code: any active ISO 4217\n * code, or one of the cryptocurrencies in {@link CRYPTO_IDS}.\n *\n * This used to be a hand-written list of forty-six codes, which meant\n * `$100 in UAH` returned an unconverted hundred dollars rather than saying\n * it could not convert. Answering from the standard rather than from\n * whichever codes happened to get added is what stops that class of bug.\n *\n * Recognising a code is not the same as having a rate for it. That is\n * answered later, by the exchange provider; conflating the two is what\n * produced the silent failure.\n */\n isCurrency(code: string): boolean {\n return isIso4217(code) || this.isCryptoCode(code);\n }\n}\n\n// ============================================================================\n// SINGLETON INSTANCE\n// ============================================================================\n\n/** The shared rate cache. See {@link CurrencyExchangeService} for why it is shared. */\nexport const currencyExchangeService = new CurrencyExchangeService();\n\n// Export for backward compatibility\n/** Alias for {@link currencyExchangeService}, kept for older imports. */\nexport const sharedCurrencyExchange = currencyExchangeService;\n\n// Default export\nexport default currencyExchangeService;\n"]}
1
+ {"version":3,"sources":["../src/uom/Iso4217.ts","../src/uom/CurrencyExchange.ts"],"names":["ISO_4217_CODES","isIso4217","code","CurrencyErrorCodes","_CurrencyExchangeService","from","to","signal","fromUpper","toUpper","fetchSignal","cleanup","createTimeoutSignal","query","response","ErrorFactory","data","rates","entry","candidate","fromIsCrypto","toIsCrypto","rate","fromId","toId","fromUsd","toUsd","vs","value","priceOfToInFrom","ids","vsCurrency","base","baseUpper","now","table","fromRate","toRate","snapshot","any","CurrencyExchangeService","currencyExchangeService","sharedCurrencyExchange"],"mappings":"qHAyBO,IAAMA,CAAAA,CAAsC,IAAI,GAAA,CAAI,CAC1D,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAC/D,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC/D,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CACnC,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC/D,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CAAO,KAAA,CACP,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACjD,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CACnC,KAAA,CAAO,KAAA,CAAO,KAAA,CACd,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACxD,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACnC,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAC/D,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC5B,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACnC,KAAA,CACA,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC1C,KAAA,CACA,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC/D,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC5B,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACxD,KAAA,CAAO,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CACjD,KAAA,CAAO,MAAO,KAAA,CAAO,KAAA,CACrB,KAAA,CACA,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAAO,KAAA,CAC5B,KAAA,CACA,KAAA,CAAO,KAAA,CAAO,KACf,CAAC,CAAA,CAOM,SAASC,CAAAA,CAAUC,CAAAA,CAAuB,CAChD,OAAOF,CAAAA,CAAe,GAAA,CAAIE,EAAK,WAAA,EAAa,CAC7C,CCjDO,IAAMC,CAAAA,CAAqB,CAEhC,SAAA,CAAW,oBAAA,CAEX,YAAA,CAAc,uBAAA,CAEd,gBAAA,CAAkB,wBACpB,CAAA,CAcaC,CAAAA,CAAN,MAAMA,CAAwB,CAuCnC,WAAA,EAAc,CA7Bd,IAAA,CAAQ,WAAgF,IAAI,IA6B7E,CANP,YAAA,CAAaF,CAAAA,CAAuB,CAG1C,OAAO,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAKE,CAAAA,CAAwB,UAAA,CAAYF,CAAAA,CAAK,aAAa,CACpG,CA4BA,MAAM,OAAA,CAAQG,CAAAA,CAAcC,CAAAA,CAAYC,CAAAA,CAAuC,CAC7E,IAAMC,CAAAA,CAAYH,CAAAA,CAAK,WAAA,EAAY,CAC7BI,EAAUH,CAAAA,CAAG,WAAA,EAAY,CAE/B,GAAI,IAAA,CAAK,YAAA,CAAaE,CAAS,CAAA,EAAK,IAAA,CAAK,YAAA,CAAaC,CAAO,CAAA,CAC3D,OAAO,KAAK,aAAA,CAAcD,CAAAA,CAAWC,CAAAA,CAASF,CAAM,CAAA,CAKtD,GAAM,CAAE,MAAA,CAAQG,CAAAA,CAAa,OAAA,CAAAC,CAAQ,CAAA,CAAIC,mBAAAA,CACvCL,CAAAA,CACAH,EAAwB,gBAAA,CACxB,oBACF,CAAA,CAEA,GAAI,CAIF,IAAMS,EAAQ,IAAI,eAAA,CAAgB,CAAE,IAAA,CAAML,CAAU,CAAC,EAC/CM,CAAAA,CAAW,MAAM,KAAA,CAAM,CAAA,qCAAA,EAAwCD,CAAAA,CAAM,QAAA,EAAU,CAAA,CAAA,CAAI,CAAE,MAAA,CAAQH,CAAY,CAAC,CAAA,CAChH,GAAI,CAACI,CAAAA,CAAS,EAAA,CAAI,MAAMC,mBAAAA,CAAa,QAAA,CAASZ,CAAAA,CAAmB,UAAW,CAAA,sBAAA,EAAyBW,CAAAA,CAAS,MAAM,CAAA,CAAA,CAAI,CAAE,MAAA,CAAQA,EAAS,MAAO,CAAC,CAAA,CACnJ,IAAME,CAAAA,CAAO,MAAMF,CAAAA,CAAS,IAAA,EAAK,CAQ3BG,CAAAA,CAAgC,KAAA,CAAM,OAAA,CAAQD,CAAI,CAAA,CACpD,OAAO,WAAA,CACLA,CAAAA,CACG,MAAA,CAAQE,CAAAA,EAA6D,CACpE,GAAI,OAAOA,CAAAA,EAAU,QAAA,EAAYA,CAAAA,GAAU,IAAA,CAAM,OAAO,CAAA,CAAA,CACxD,IAAMC,CAAAA,CAAYD,CAAAA,CAClB,OAAO,OAAOC,CAAAA,CAAU,KAAA,EAAU,QAAA,EAAY,OAAOA,CAAAA,CAAU,IAAA,EAAS,QAC1E,CAAC,CAAA,CACA,GAAA,CAAKD,GAA2C,CAACA,CAAAA,CAAM,KAAA,CAAM,WAAA,EAAY,CAAGA,CAAAA,CAAM,IAAI,CAAC,CAC5F,CAAA,CACCF,CAAAA,CAAK,KAAA,EAAS,GACnB,GAAIC,CAAAA,CAAMR,CAAO,CAAA,GAAM,KAAA,CAAA,CAAW,MAAMM,mBAAAA,CAAa,UAAA,CAAWZ,CAAAA,CAAmB,YAAA,CAAc,CAAA,kBAAA,EAAqBM,CAAO,CAAA,CAAA,CAAI,CAAE,KAAMA,CAAQ,CAAC,CAAA,CAMlJ,OAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAID,EAAW,CAC7B,SAAA,CAAW,IAAA,CAAK,GAAA,EAAI,CACpB,KAAA,CAAO,CAAE,GAAGS,CAAAA,CAAO,CAACT,CAAS,EAAG,CAAE,CACpC,CAAC,CAAA,CAEMS,CAAAA,CAAMR,CAAO,CACtB,CAAA,OAAE,CACAE,IACF,CACF,CAWA,MAAc,aAAA,CAAcH,CAAAA,CAAmBC,EAAiBF,CAAAA,CAAuC,CACrG,GAAM,CAAE,MAAA,CAAQG,CAAAA,CAAa,QAAAC,CAAQ,CAAA,CAAIC,mBAAAA,CACvCL,CAAAA,CACAH,CAAAA,CAAwB,gBAAA,CACxB,wBACF,CAAA,CAEA,GAAI,CACF,IAAMgB,CAAAA,CAAe,IAAA,CAAK,YAAA,CAAaZ,CAAS,CAAA,CAC1Ca,CAAAA,CAAa,IAAA,CAAK,YAAA,CAAaZ,CAAO,CAAA,CACxCa,CAAAA,CAEJ,GAAIF,CAAAA,EAAgBC,CAAAA,CAAY,CAC9B,IAAME,CAAAA,CAASnB,CAAAA,CAAwB,WAAWI,CAAS,CAAA,CACrDgB,CAAAA,CAAOpB,CAAAA,CAAwB,UAAA,CAAWK,CAAO,CAAA,CACjDO,CAAAA,CAAO,MAAM,IAAA,CAAK,oBAAA,CAAqB,CAACO,CAAAA,CAAQC,CAAI,EAAG,KAAA,CAAOd,CAAW,CAAA,CACzEe,CAAAA,CAAUT,CAAAA,CAAKO,CAAM,GAAG,GAAA,CACxBG,CAAAA,CAAQV,CAAAA,CAAKQ,CAAI,CAAA,EAAG,GAAA,CAC1B,GAAI,OAAOC,CAAAA,EAAY,QAAA,CAAU,MAAMV,mBAAAA,CAAa,UAAA,CAAWZ,CAAAA,CAAmB,YAAA,CAAc,CAAA,kBAAA,EAAqBK,CAAS,CAAA,CAAA,CAAI,CAAE,IAAA,CAAMA,CAAU,CAAC,CAAA,CACrJ,GAAI,OAAOkB,CAAAA,EAAU,QAAA,CAAU,MAAMX,oBAAa,UAAA,CAAWZ,CAAAA,CAAmB,YAAA,CAAc,CAAA,kBAAA,EAAqBM,CAAO,CAAA,CAAA,CAAI,CAAE,IAAA,CAAMA,CAAQ,CAAC,CAAA,CAC/Ia,CAAAA,CAAOG,CAAAA,CAAUC,EACnB,CAAA,KAAA,GAAWN,CAAAA,CAAc,CACvB,IAAMG,CAAAA,CAASnB,CAAAA,CAAwB,UAAA,CAAWI,CAAS,CAAA,CACrDmB,CAAAA,CAAKlB,CAAAA,CAAQ,WAAA,EAAY,CAEzBmB,CAAAA,CAAAA,CADO,MAAM,IAAA,CAAK,oBAAA,CAAqB,CAACL,CAAM,CAAA,CAAGI,CAAAA,CAAIjB,CAAW,CAAA,EACnDa,CAAM,CAAA,GAAII,CAAE,CAAA,CAC/B,GAAI,OAAOC,CAAAA,EAAU,QAAA,CAAU,MAAMb,mBAAAA,CAAa,UAAA,CAAWZ,CAAAA,CAAmB,YAAA,CAAc,qBAAqBM,CAAO,CAAA,CAAA,CAAI,CAAE,IAAA,CAAMA,CAAQ,CAAC,EAC/Ia,CAAAA,CAAOM,EACT,CAAA,KAAO,CACL,IAAMJ,CAAAA,CAAOpB,EAAwB,UAAA,CAAWK,CAAO,CAAA,CACjDkB,CAAAA,CAAKnB,CAAAA,CAAU,WAAA,EAAY,CAE3BqB,CAAAA,CAAAA,CADO,MAAM,IAAA,CAAK,oBAAA,CAAqB,CAACL,CAAI,CAAA,CAAGG,EAAIjB,CAAW,CAAA,EACvCc,CAAI,CAAA,GAAIG,CAAE,CAAA,CACvC,GAAI,OAAOE,CAAAA,EAAoB,QAAA,CAAU,MAAMd,mBAAAA,CAAa,UAAA,CAAWZ,EAAmB,YAAA,CAAc,CAAA,kBAAA,EAAqBK,CAAS,CAAA,CAAA,CAAI,CAAE,IAAA,CAAMA,CAAU,CAAC,CAAA,CAC7Jc,CAAAA,CAAO,CAAA,CAAIO,EACb,CAKA,OAAA,IAAA,CAAK,WAAW,GAAA,CAAIrB,CAAAA,CAAW,CAC7B,SAAA,CAAW,IAAA,CAAK,GAAA,GAChB,KAAA,CAAO,CAAE,CAACA,CAAS,EAAG,CAAA,CAAG,CAACC,CAAO,EAAGa,CAAK,CAC3C,CAAC,CAAA,CAEMA,CACT,CAAA,OAAE,CACAX,CAAAA,GACF,CACF,CAEA,MAAc,qBAAqBmB,CAAAA,CAAeC,CAAAA,CAAoBxB,CAAAA,CAAsE,CAC1I,IAAMM,CAAAA,CAAQ,IAAI,eAAA,CAAgB,CAAE,GAAA,CAAKiB,CAAAA,CAAI,IAAA,CAAK,GAAG,EAAG,aAAA,CAAeC,CAAW,CAAC,CAAA,CAC7EjB,CAAAA,CAAW,MAAM,KAAA,CAAM,CAAA,8CAAA,EAAiDD,CAAAA,CAAM,QAAA,EAAU,CAAA,CAAA,CAAI,CAAE,MAAA,CAAAN,CAAO,CAAC,CAAA,CAC5G,GAAI,CAACO,CAAAA,CAAS,EAAA,CAAI,MAAMC,mBAAAA,CAAa,QAAA,CAASZ,CAAAA,CAAmB,gBAAA,CAAkB,CAAA,0BAAA,EAA6BW,CAAAA,CAAS,MAAM,GAAI,CAAE,MAAA,CAAQA,CAAAA,CAAS,MAAO,CAAC,CAAA,CAC9J,OAAOA,CAAAA,CAAS,IAAA,EAClB,CAYA,UAAA,CAAWkB,CAAAA,CAAcf,CAAAA,CAAqC,CAC5D,IAAMgB,CAAAA,CAAYD,CAAAA,CAAK,WAAA,EAAY,CACnC,IAAA,CAAK,WAAW,GAAA,CAAIC,CAAAA,CAAW,CAC7B,SAAA,CAAW,IAAA,CAAK,GAAA,GAChB,KAAA,CAAO,CAAE,GAAGhB,CAAAA,CAAO,CAACgB,CAAS,EAAG,CAAE,CACpC,CAAC,EACH,CAUA,UAAA,EAAmB,CACjB,KAAK,UAAA,CAAW,KAAA,GAClB,CAWA,WAAA,CAAY5B,CAAAA,CAAcC,EAA2B,CACnD,IAAME,CAAAA,CAAYH,CAAAA,CAAK,WAAA,EAAY,CAC7BI,EAAUH,CAAAA,CAAG,WAAA,EAAY,CAC/B,GAAIE,CAAAA,GAAcC,CAAAA,CAChB,OAAO,CAAA,CAET,IAAMyB,CAAAA,CAAM,IAAA,CAAK,GAAA,EAAI,CACrB,IAAA,IAAWC,KAAS,IAAA,CAAK,UAAA,CAAW,MAAA,EAAO,CAAG,CAC5C,GAAID,EAAMC,CAAAA,CAAM,SAAA,CAAY/B,CAAAA,CAAwB,iBAAA,CAAmB,SACvE,IAAMgC,EAAWD,CAAAA,CAAM,KAAA,CAAM3B,CAAS,CAAA,CAChC6B,CAAAA,CAASF,CAAAA,CAAM,KAAA,CAAM1B,CAAO,CAAA,CAClC,GAAI2B,CAAAA,EAAYC,CAAAA,CACd,OAAOA,CAAAA,CAASD,CAEpB,CACA,OAAO,IACT,CAGA,MAAM,OAAA,CAAQR,CAAAA,CAAevB,CAAAA,CAAcC,CAAAA,CAA6B,CACtE,IAAMgB,CAAAA,CAAO,MAAM,IAAA,CAAK,QAAQjB,CAAAA,CAAMC,CAAE,CAAA,CACxC,OAAOsB,CAAAA,CAAQN,CACjB,CAMA,WAAA,EAA6C,CAC3C,IAAMY,CAAAA,CAAM,IAAA,CAAK,GAAA,EAAI,CACfI,EAAmC,EAAC,CACtCC,CAAAA,CAAM,KAAA,CACV,IAAA,GAAW,CAACP,EAAMG,CAAK,CAAA,GAAK,IAAA,CAAK,UAAA,CAC/B,GAAI,EAAAD,EAAMC,CAAAA,CAAM,SAAA,CAAY/B,CAAAA,CAAwB,iBAAA,CAAA,CACpD,IAAA,GAAW,CAACF,CAAAA,CAAMoB,CAAI,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQa,CAAAA,CAAM,KAAK,CAAA,CACnDG,EAAS,CAAA,EAAGN,CAAI,CAAA,CAAA,EAAI9B,CAAI,CAAA,CAAE,CAAA,CAAIoB,EAC9BiB,CAAAA,CAAM,IAAA,CAGV,OAAOA,CAAAA,CAAMD,CAAAA,CAAW,IAC1B,CAKA,QAAA,EAAoB,CAClB,OAAO,IAAA,CAAK,WAAA,EAAY,GAAM,IAChC,CAMA,WAAA,CAAYV,CAAAA,CAAevB,CAAAA,CAAcC,CAAAA,CAA2B,CAClE,IAAMgB,EAAO,IAAA,CAAK,WAAA,CAAYjB,CAAAA,CAAMC,CAAE,CAAA,CACtC,OAAIgB,IAAS,IAAA,CAAa,IAAA,CACnBM,CAAAA,CAAQN,CACjB,CAmBA,UAAA,CAAWpB,EAAuB,CAChC,OAAOD,CAAAA,CAAUC,CAAI,CAAA,EAAK,IAAA,CAAK,YAAA,CAAaA,CAAI,CAClD,CACF,CAAA,CArTaE,CAAAA,CAiBa,iBAAA,CAAoB,GAAA,CAAU,IAjB3CA,CAAAA,CA4Ba,UAAA,CAAqC,CAC3D,GAAA,CAAK,SAAA,CAAW,GAAA,CAAK,UAAA,CAAY,GAAA,CAAK,QAAA,CAAU,GAAA,CAAK,QAAA,CACrD,GAAA,CAAK,SAAA,CAAW,IAAA,CAAM,WAAY,GAAA,CAAK,UACzC,CAAA,CA/BWA,CAAAA,CAoDa,gBAAA,CAAmB,GAAA,CApDtC,IAAMoC,CAAAA,CAANpC,CAAAA,CA4TMqC,CAAAA,CAA0B,IAAID,CAAAA,CAI9BE,CAAAA,CAAyBD","file":"chunk-TMQ37JQY.cjs","sourcesContent":["/**\n * Every active ISO 4217 currency code.\n *\n * This exists because `CurrencyExchange.isCurrency()` used to hold a\n * hand-written list of forty-six codes, and a code missing from it did not\n * error: `$100 in UAH` returned the original hundred dollars, unconverted, as\n * though the rate were 1. A wrong answer, not a missing feature.\n *\n * The list is the ISO 4217 active set, so \"is this a currency\" is answered by\n * the standard rather than by whichever codes happened to get added. Whether a\n * *rate* is available for one is a separate question, answered at resolution\n * time by whatever the exchange provider supports; conflating the two is what\n * produced the silent failure.\n *\n * Deliberately excluded:\n * - The historical/withdrawn codes (DEM, FRF, and the rest). They are not\n * active, no provider quotes them, and recognising them would only move the\n * failure later.\n * - The X-series non-currencies: XAU/XAG/XPT/XPD (metals), XDR (IMF special\n * drawing rights), XTS (reserved for testing) and XXX (explicitly \"no\n * currency\"). XXX in particular must never resolve.\n *\n * Cryptocurrencies are not here either. They are not ISO 4217 and are tracked\n * separately in `CurrencyExchangeService.CRYPTO_IDS`.\n */\nexport const ISO_4217_CODES: ReadonlySet<string> = new Set([\n\t\"AED\", \"AFN\", \"ALL\", \"AMD\", \"ANG\", \"AOA\", \"ARS\", \"AUD\", \"AWG\", \"AZN\",\n\t\"BAM\", \"BBD\", \"BDT\", \"BGN\", \"BHD\", \"BIF\", \"BMD\", \"BND\", \"BOB\", \"BOV\",\n\t\"BRL\", \"BSD\", \"BTN\", \"BWP\", \"BYN\", \"BZD\",\n\t\"CAD\", \"CDF\", \"CHE\", \"CHF\", \"CHW\", \"CLF\", \"CLP\", \"CNY\", \"COP\", \"COU\",\n\t\"CRC\", \"CUP\", \"CVE\", \"CZK\",\n\t\"DJF\", \"DKK\", \"DOP\", \"DZD\",\n\t\"EGP\", \"ERN\", \"ETB\", \"EUR\",\n\t\"FJD\", \"FKP\",\n\t\"GBP\", \"GEL\", \"GHS\", \"GIP\", \"GMD\", \"GNF\", \"GTQ\", \"GYD\",\n\t\"HKD\", \"HNL\", \"HTG\", \"HUF\",\n\t\"IDR\", \"ILS\", \"INR\", \"IQD\", \"IRR\", \"ISK\",\n\t\"JMD\", \"JOD\", \"JPY\",\n\t\"KES\", \"KGS\", \"KHR\", \"KMF\", \"KPW\", \"KRW\", \"KWD\", \"KYD\", \"KZT\",\n\t\"LAK\", \"LBP\", \"LKR\", \"LRD\", \"LSL\", \"LYD\",\n\t\"MAD\", \"MDL\", \"MGA\", \"MKD\", \"MMK\", \"MNT\", \"MOP\", \"MRU\", \"MUR\", \"MVR\",\n\t\"MWK\", \"MXN\", \"MXV\", \"MYR\", \"MZN\",\n\t\"NAD\", \"NGN\", \"NIO\", \"NOK\", \"NPR\", \"NZD\",\n\t\"OMR\",\n\t\"PAB\", \"PEN\", \"PGK\", \"PHP\", \"PKR\", \"PLN\", \"PYG\",\n\t\"QAR\",\n\t\"RON\", \"RSD\", \"RUB\", \"RWF\",\n\t\"SAR\", \"SBD\", \"SCR\", \"SDG\", \"SEK\", \"SGD\", \"SHP\", \"SLE\", \"SOS\", \"SRD\",\n\t\"SSP\", \"STN\", \"SVC\", \"SYP\", \"SZL\",\n\t\"THB\", \"TJS\", \"TMT\", \"TND\", \"TOP\", \"TRY\", \"TTD\", \"TWD\", \"TZS\",\n\t\"UAH\", \"UGX\", \"USD\", \"USN\", \"UYI\", \"UYU\", \"UYW\", \"UZS\",\n\t\"VED\", \"VES\", \"VND\", \"VUV\",\n\t\"WST\",\n\t\"XAF\", \"XCD\", \"XCG\", \"XOF\", \"XPF\",\n\t\"YER\",\n\t\"ZAR\", \"ZMW\", \"ZWG\",\n]);\n\n/**\n * Whether `code` is an active ISO 4217 currency code.\n *\n * @param code - A three-letter code, in any case.\n */\nexport function isIso4217(code: string): boolean {\n\treturn ISO_4217_CODES.has(code.toUpperCase());\n}\n","/**\n * Production-grade currency exchange service with scalable architecture\n * Integrates with DataQueryService for worker-based execution\n */\n\nimport { isIso4217 } from \"@solve-js/uom/Iso4217\";\nimport { createTimeoutSignal } from \"@solve-js/utilities/TimeoutSignal\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * Error codes for this service. Co-located rather than unioned into\n * `errors/ErrorCode.ts`'s core catalog (that catalog is scoped to the\n * parser/VM/engine/errors/config/lexer layers, not yet the ~17 domain\n * packages. See that file's module doc for the intended per-package\n * pattern this follows).\n */\nexport const CurrencyErrorCodes = {\n /** Frankfurter's rates endpoint returned a non-OK HTTP status. */\n API_ERROR: \"CURRENCY_API_ERROR\",\n /** A requested currency/crypto code isn't in the fetched rate table, an unrecognized code, not an API failure. */\n UNKNOWN_CODE: \"UNKNOWN_CURRENCY_CODE\",\n /** CoinGecko's simple-price endpoint returned a non-OK HTTP status. */\n CRYPTO_API_ERROR: \"CRYPTO_PRICE_API_ERROR\",\n} as const;\n\n// ============================================================================\n// CURRENCY EXCHANGE SERVICE\n// ============================================================================\n\n/**\n * Caches exchange rates fetched from an external source.\n *\n * Rates are global market data rather than per-engine configuration, which is\n * why one instance is shared. Two engines with private copies would fetch the\n * same endpoint twice and could disagree about one pair at one moment. See\n * `engine/EngineContext.ts`.\n */\nexport class CurrencyExchangeService {\n /**\n * Live rate tables cached from successful getRate() fetches, keyed by\n * uppercase base currency. Each table holds every rate the API returned\n * for that base (plus the base itself at 1), so any pair whose two codes\n * appear in one fresh table can be served synchronously, including\n * cross pairs via triangulation (EUR→GBP through a USD-base table).\n * Stale tables are ignored, not evicted; the next successful fetch for\n * the same base overwrites them.\n */\n private baseTables: Map<string, { fetchedAt: number; rates: Record<string, number> }> = new Map();\n\n /**\n * How long a fetched rate may be served synchronously by getRateSync().\n * Beyond this window callers fall through to the async path (expression\n * shows Pending until the fetch lands).\n */\n private static readonly RATE_FRESHNESS_MS = 15 * 60 * 1000;\n\n /**\n * Ticker → CoinGecko coin id, for the cryptocurrencies `isCurrency()`\n * recognizes. Frankfurter (the fiat rate source below) is ECB reference\n * rates only and has no concept of BTC/ETH/etc, routing a crypto code\n * through it as `base=BTC` fails outright, which is why crypto pairs\n * previously never resolved (see CurrencyAsyncResolver/VM.ts's ADD\n * handling for the two bugs that let that failure pass silently instead\n * of surfacing as a real fetch).\n */\n private static readonly CRYPTO_IDS: Record<string, string> = {\n BTC: \"bitcoin\", ETH: \"ethereum\", SOL: \"solana\", XRP: \"ripple\",\n ADA: \"cardano\", DOGE: \"dogecoin\", DOT: \"polkadot\",\n };\n\n private isCryptoCode(code: string): boolean {\n // An own-property check, not `in`: `in` also answers for everything on\n // Object.prototype, so a code spelt like an inherited name would pass.\n return Object.prototype.hasOwnProperty.call(CurrencyExchangeService.CRYPTO_IDS, code.toUpperCase());\n }\n\n constructor() {}\n\n // ------------------------------------------------------------------------\n // RATE FETCHING\n // ------------------------------------------------------------------------\n\n /**\n * Timeout (ms) for currency exchange rate fetches.\n *\n * If the frankfurter API doesn't respond within this window, the fetch\n * is aborted, preventing indefinite \"Pending\" states in the playground\n * and Obsidian plugin when the exchange rate API is unreachable.\n */\n private static readonly FETCH_TIMEOUT_MS = 10_000;\n\n /**\n * Fetch the live exchange rate for converting 1 unit of `from` into `to`.\n *\n * Routes cryptocurrency codes (see {@link CRYPTO_IDS}) to CoinGecko and\n * everything else to Frankfurter (ECB reference rates, fiat-only). On\n * success, caches the whole returned rate table for `from` so subsequent\n * lookups, including cross-pairs via triangulation, can be served\n * synchronously by {@link getRateSync} within the freshness window.\n *\n * @throws If the currency code is unrecognized or the fetch fails/times out.\n */\n async getRate(from: string, to: string, signal?: AbortSignal): Promise<number> {\n const fromUpper = from.toUpperCase();\n const toUpper = to.toUpperCase();\n\n if (this.isCryptoCode(fromUpper) || this.isCryptoCode(toUpper)) {\n return this.getCryptoRate(fromUpper, toUpper, signal);\n }\n\n // Combine the caller's optional abort signal with a hard timeout so a\n // hanging currency API never blocks re-evaluation indefinitely.\n const { signal: fetchSignal, cleanup } = createTimeoutSignal(\n signal,\n CurrencyExchangeService.FETCH_TIMEOUT_MS,\n \"Currency API fetch\",\n );\n\n try {\n // Built with URLSearchParams rather than interpolated. The code is\n // ISO-4217 by the time it gets here, but the query should be safe on\n // its own terms rather than by relying on a check that lives elsewhere.\n const query = new URLSearchParams({ base: fromUpper });\n const response = await fetch(`https://api.frankfurter.dev/v2/rates?${query.toString()}`, { signal: fetchSignal });\n if (!response.ok) throw ErrorFactory.external(CurrencyErrorCodes.API_ERROR, `Currency API returned ${response.status}`, { status: response.status });\n const data = await response.json();\n // The v2 endpoint returns a flat array of { date, base, quote, rate }\n // entries (one per target currency) rather than the classic v1 shape\n // { base, date, rates: { CODE: rate } }. Reading data.rates against\n // the real response is always undefined, so every conversion used to\n // throw \"Unknown currency\" no matter which currencies were requested.\n // Accept both shapes so a future API revision back to the object form\n // doesn't silently break this again.\n const rates: Record<string, number> = Array.isArray(data)\n ? Object.fromEntries(\n data\n .filter((entry: unknown): entry is { quote: string; rate: number } => {\n if (typeof entry !== \"object\" || entry === null) return false;\n const candidate = entry as { quote?: unknown; rate?: unknown };\n return typeof candidate.quote === \"string\" && typeof candidate.rate === \"number\";\n })\n .map((entry: { quote: string; rate: number }) => [entry.quote.toUpperCase(), entry.rate])\n )\n : (data.rates ?? {});\n if (rates[toUpper] === undefined) throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n\n // The API returns ALL rates for the base currency, cache the whole\n // table so subsequent conversions (including cross pairs via\n // triangulation) resolve synchronously within the freshness window\n // instead of going Pending again.\n this.baseTables.set(fromUpper, {\n fetchedAt: Date.now(),\n rates: { ...rates, [fromUpper]: 1 },\n });\n\n return rates[toUpper];\n } finally {\n cleanup();\n }\n }\n\n /**\n * Crypto rate fetch, routed through CoinGecko's no-auth simple-price\n * endpoint instead of Frankfurter (fiat-only, has no BTC/ETH concept).\n * Handles all three combinations, crypto→crypto, crypto→fiat\n * fiat→crypto, via prices denominated in USD (or the target fiat\n * directly, which CoinGecko's `vs_currencies` also accepts), then\n * caches the result as a same-shaped base table so getRateSync /\n * convertSync keep working unchanged for crypto pairs too.\n */\n private async getCryptoRate(fromUpper: string, toUpper: string, signal?: AbortSignal): Promise<number> {\n const { signal: fetchSignal, cleanup } = createTimeoutSignal(\n signal,\n CurrencyExchangeService.FETCH_TIMEOUT_MS,\n \"Crypto price API fetch\",\n );\n\n try {\n const fromIsCrypto = this.isCryptoCode(fromUpper);\n const toIsCrypto = this.isCryptoCode(toUpper);\n let rate: number;\n\n if (fromIsCrypto && toIsCrypto) {\n const fromId = CurrencyExchangeService.CRYPTO_IDS[fromUpper];\n const toId = CurrencyExchangeService.CRYPTO_IDS[toUpper];\n const data = await this.fetchCoinGeckoPrices([fromId, toId], \"usd\", fetchSignal);\n const fromUsd = data[fromId]?.usd;\n const toUsd = data[toId]?.usd;\n if (typeof fromUsd !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${fromUpper}`, { code: fromUpper });\n if (typeof toUsd !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n rate = fromUsd / toUsd;\n } else if (fromIsCrypto) {\n const fromId = CurrencyExchangeService.CRYPTO_IDS[fromUpper];\n const vs = toUpper.toLowerCase();\n const data = await this.fetchCoinGeckoPrices([fromId], vs, fetchSignal);\n const value = data[fromId]?.[vs];\n if (typeof value !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${toUpper}`, { code: toUpper });\n rate = value;\n } else {\n const toId = CurrencyExchangeService.CRYPTO_IDS[toUpper];\n const vs = fromUpper.toLowerCase();\n const data = await this.fetchCoinGeckoPrices([toId], vs, fetchSignal);\n const priceOfToInFrom = data[toId]?.[vs];\n if (typeof priceOfToInFrom !== \"number\") throw ErrorFactory.validation(CurrencyErrorCodes.UNKNOWN_CODE, `Unknown currency: ${fromUpper}`, { code: fromUpper });\n rate = 1 / priceOfToInFrom;\n }\n\n // Cache as a single-pair base table, same shape Frankfurter fetches\n // produce, so getRateSync/convertSync's triangulation logic doesn't\n // need to know or care which source a rate came from.\n this.baseTables.set(fromUpper, {\n fetchedAt: Date.now(),\n rates: { [fromUpper]: 1, [toUpper]: rate },\n });\n\n return rate;\n } finally {\n cleanup();\n }\n }\n\n private async fetchCoinGeckoPrices(ids: string[], vsCurrency: string, signal: AbortSignal): Promise<Record<string, Record<string, number>>> {\n const query = new URLSearchParams({ ids: ids.join(\",\"), vs_currencies: vsCurrency });\n const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?${query.toString()}`, { signal });\n if (!response.ok) throw ErrorFactory.external(CurrencyErrorCodes.CRYPTO_API_ERROR, `Crypto price API returned ${response.status}`, { status: response.status });\n return response.json();\n }\n\n /**\n * Seed a base rate table without a network fetch.\n *\n * Intended for tests and for future user-provided offline rates\n * production live data always comes from {@link getRate}. Seeded rates\n * obey the same freshness window as fetched ones.\n *\n * @param base - Base currency code (e.g. \"USD\").\n * @param rates - Map of currency code → rate relative to the base.\n */\n primeRates(base: string, rates: Record<string, number>): void {\n const baseUpper = base.toUpperCase();\n this.baseTables.set(baseUpper, {\n fetchedAt: Date.now(),\n rates: { ...rates, [baseUpper]: 1 },\n });\n }\n\n /**\n * Drop every cached/primed rate table.\n *\n * Mainly for test isolation: {@link sharedCurrencyExchange} is a\n * module-level singleton, so a rate primed or fetched by one test can\n * silently leak into a later test in the same file. Also usable in\n * production if a caller ever wants to force a full re-fetch.\n */\n clearRates(): void {\n this.baseTables.clear();\n }\n\n /**\n * Synchronous rate lookup: `1` for same-currency pairs, a cached LIVE\n * rate if one was fetched within {@link RATE_FRESHNESS_MS}, otherwise\n * `null`, callers fall through to the async fetch path and the\n * expression shows Pending until real data arrives.\n *\n * There is deliberately no hardcoded fallback table: a stale made-up\n * rate presented as a real conversion is worse than a Pending state.\n */\n getRateSync(from: string, to: string): number | null {\n const fromUpper = from.toUpperCase();\n const toUpper = to.toUpperCase();\n if (fromUpper === toUpper) {\n return 1;\n }\n const now = Date.now();\n for (const table of this.baseTables.values()) {\n if (now - table.fetchedAt > CurrencyExchangeService.RATE_FRESHNESS_MS) continue;\n const fromRate = table.rates[fromUpper];\n const toRate = table.rates[toUpper];\n if (fromRate && toRate) {\n return toRate / fromRate;\n }\n }\n return null;\n }\n\n /** Convert `value` from `from` to `to` using a freshly-fetched live rate (see {@link getRate}). */\n async convert(value: number, from: string, to: string): Promise<number> {\n const rate = await this.getRate(from, to);\n return value * rate;\n }\n\n /**\n * Get all currently cached fresh rates, keyed \"FROM:TO\".\n * @returns Snapshot of fresh live rates, or null when none are cached.\n */\n getAllRates(): Record<string, number> | null {\n const now = Date.now();\n const snapshot: Record<string, number> = {};\n let any = false;\n for (const [base, table] of this.baseTables) {\n if (now - table.fetchedAt > CurrencyExchangeService.RATE_FRESHNESS_MS) continue;\n for (const [code, rate] of Object.entries(table.rates)) {\n snapshot[`${base}:${code}`] = rate;\n any = true;\n }\n }\n return any ? snapshot : null;\n }\n\n /**\n * Check whether any fresh live rates are currently cached.\n */\n hasRates(): boolean {\n return this.getAllRates() !== null;\n }\n\n /**\n * Synchronous conversion using cached rates only\n * Returns null if rate not in cache\n */\n convertSync(value: number, from: string, to: string): number | null {\n const rate = this.getRateSync(from, to);\n if (rate === null) return null;\n return value * rate;\n }\n\n // ------------------------------------------------------------------------\n // CURRENCY VALIDATION\n // ------------------------------------------------------------------------\n\n /**\n * Check whether `code` is a recognized currency code: any active ISO 4217\n * code, or one of the cryptocurrencies in {@link CRYPTO_IDS}.\n *\n * This used to be a hand-written list of forty-six codes, which meant\n * `$100 in UAH` returned an unconverted hundred dollars rather than saying\n * it could not convert. Answering from the standard rather than from\n * whichever codes happened to get added is what stops that class of bug.\n *\n * Recognising a code is not the same as having a rate for it. That is\n * answered later, by the exchange provider; conflating the two is what\n * produced the silent failure.\n */\n isCurrency(code: string): boolean {\n return isIso4217(code) || this.isCryptoCode(code);\n }\n}\n\n// ============================================================================\n// SINGLETON INSTANCE\n// ============================================================================\n\n/** The shared rate cache. See {@link CurrencyExchangeService} for why it is shared. */\nexport const currencyExchangeService = new CurrencyExchangeService();\n\n// Export for backward compatibility\n/** Alias for {@link currencyExchangeService}, kept for older imports. */\nexport const sharedCurrencyExchange = currencyExchangeService;\n\n// Default export\nexport default currencyExchangeService;\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkE4HAKNBQ_cjs=require('./chunk-E4HAKNBQ.cjs'),chunkGXO7TSXQ_cjs=require('./chunk-GXO7TSXQ.cjs');var s=class{now(){return Date.now()}fields(t){let e=new Date(t);return {year:e.getFullYear(),month0:e.getMonth(),day:e.getDate(),weekday:e.getDay(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}}localMidnight(t,e,n){return new Date(t,e,n).getTime()}localWallClock(t,e,n,r){let a=new Date(t,e,n,0,0,0,0);return a.setMinutes(r),a.getTime()}addDays(t,e){let n=new Date(t);return n.setDate(n.getDate()+e),n.getTime()}addMonths(t,e){let n=new Date(t),r=n.getDate();return n.setDate(1),n.setMonth(n.getMonth()+e),n.setDate(Math.min(r,chunkE4HAKNBQ_cjs.b(n.getFullYear(),n.getMonth()))),n.getTime()}utcOffsetMinutes(t){return 0-new Date(t).getTimezoneOffset()}parseIso8601(t){return new Date(t).getTime()}formatLongDate(t,e){return new Date(t).toLocaleDateString(e,{weekday:"long",year:"numeric",month:"long",day:"numeric"})}formatTimeOfDay(t,e){return new Date(t).toLocaleTimeString(e)}zoneOffsetMinutes(t,e){let n=chunkE4HAKNBQ_cjs.l(t,e);return Math.round((chunkE4HAKNBQ_cjs.a(n.year,n.month0,n.day,n.hour,n.minute,n.second)-e)/6e4)||0}fieldsInZone(t,e){return chunkE4HAKNBQ_cjs.l(t,e)}formatTimeInZone(t,e){return chunkE4HAKNBQ_cjs.m(t,e)}formatDateInZone(t,e){return chunkE4HAKNBQ_cjs.n(t,e)}},k=new s;function L(o){return o?.calendar??k}var O=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?$/,l=class extends s{constructor(e){super();this.namedZone=e;}zone(){return this.namedZone}fields(e){let n=chunkE4HAKNBQ_cjs.l(this.namedZone,e),r=((chunkE4HAKNBQ_cjs.c(n.year,n.month0,n.day)+4)%7+7)%7;return {year:n.year,month0:n.month0,day:n.day,weekday:r,hour:n.hour,minute:n.minute,second:n.second,millisecond:(e%1e3+1e3)%1e3}}localMidnight(e,n,r){return chunkE4HAKNBQ_cjs.j(e,n,r,0,0,this.namedZone,this)}localWallClock(e,n,r,a){return chunkE4HAKNBQ_cjs.j(e,n,r,0,a,this.namedZone,this)}addDays(e,n){let r=chunkE4HAKNBQ_cjs.l(this.namedZone,e);return this.reanchor(r,r.day+n,e)}addMonths(e,n){let r=chunkE4HAKNBQ_cjs.l(this.namedZone,e),a=new Date(Date.UTC(r.year,r.month0+n,1)),i=Math.min(r.day,chunkE4HAKNBQ_cjs.b(a.getUTCFullYear(),a.getUTCMonth()));return chunkE4HAKNBQ_cjs.j(a.getUTCFullYear(),a.getUTCMonth(),i,r.hour,r.minute,this.namedZone,this)+r.second*1e3+(e%1e3+1e3)%1e3}utcOffsetMinutes(e){return this.zoneOffsetMinutes(this.namedZone,e)}parseIso8601(e){let n=O.exec(e.trim());if(n===null)return super.parseIso8601(e);let[,r,a,i,w,p,c,b]=n,I=b===void 0?0:Number(b.slice(0,3).padEnd(3,"0"));return chunkE4HAKNBQ_cjs.j(Number(r),Number(a)-1,Number(i),Number(w),Number(p),this.namedZone,this)+(c===void 0?0:Number(c))*1e3+I}formatLongDate(e,n){return chunkE4HAKNBQ_cjs.o(this.namedZone,e,n)}formatTimeOfDay(e,n){return chunkE4HAKNBQ_cjs.p(this.namedZone,e,n)}reanchor(e,n,r){return chunkE4HAKNBQ_cjs.j(e.year,e.month0,n,e.hour,e.minute,this.namedZone,this)+e.second*1e3+(r%1e3+1e3)%1e3}};function U(o){if(!chunkE4HAKNBQ_cjs.k(o))throw chunkGXO7TSXQ_cjs.c.config(chunkGXO7TSXQ_cjs.s.DATE_ZONE_UNKNOWN,`dateCalendarInZone("${o}") is not a time zone this runtime knows.`);return new l(o)}exports.a=s;exports.b=k;exports.c=L;exports.d=U;//# sourceMappingURL=chunk-TPPM4QSS.cjs.map
2
+ //# sourceMappingURL=chunk-TPPM4QSS.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/calendar/DateCalendar.ts"],"names":["DateCalendar","epochMs","d","year","month0","day","minutesPastMidnight","anchored","days","date","months","dayOfMonth","daysInMonth","text","locale","zone","f","zonedFields","utcMs","timeInZone","dateInZone","DATE_CALENDAR","calendarOf","context","ISO_LOCAL_DATE_TIME","ZonedDateCalendar","namedZone","weekday","dayNumber","zonedWallClockToUtcMs","target","clampedDay","matched","month","hour","minute","second","fraction","millisecond","longDateInZone","timeOfDayInZone","dateCalendarInZone","isSupportedZone","ErrorFactory","DatetimeErrorCodes"],"mappings":"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","file":"chunk-TPPM4QSS.cjs","sourcesContent":["import { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { DatetimeErrorCodes } from \"@solve-js/errors/ErrorCode\";\nimport type { CalendarBackend, CalendarFields, ZonedFields } from \"./CalendarBackend\";\nimport { dayNumber, daysInMonth, utcMs } from \"./Gregorian\";\nimport { dateInZone, isSupportedZone, longDateInZone, timeInZone, timeOfDayInZone, zonedFields, zonedWallClockToUtcMs } from \"./IntlZone\";\n\n/**\n * The default {@link CalendarBackend}: the JavaScript `Date` object, read in\n * the host process's time zone, with `Intl.DateTimeFormat` for named zones.\n *\n * This is the calendar code the engine has always run, moved behind the\n * interface method by method rather than rewritten, so a host that configures\n * nothing sees the same instants and the same strings it did before the\n * backend existed. Where `Date` has a quirk (a two-digit year in a\n * constructor maps to the 1900s, an out-of-range instant answers `NaN`), the\n * quirk is kept here deliberately: the point of this backend is to be the\n * behaviour the `Temporal` backend is measured against, not to improve on it.\n *\n * It stays the default because it is the one calendar every supported runtime\n * has. `Temporal` ships unflagged in Node 26 and in current Chrome, Firefox\n * and Deno, but not in Safari or in the Node 22 and 24 the engine supports,\n * and the smallest polyfill adds about twenty kilobytes gzipped to a bundle\n * that a host doing plain arithmetic never needs. A host that wants\n * `Temporal` opts in through the engine's `calendar` option with the backend\n * from `solve-engine/temporal`, and pays for it only then.\n */\nexport class DateCalendar implements CalendarBackend {\n\tnow(): number {\n\t\treturn Date.now();\n\t}\n\n\tfields(epochMs: number): CalendarFields {\n\t\tconst d = new Date(epochMs);\n\t\treturn {\n\t\t\tyear: d.getFullYear(),\n\t\t\tmonth0: d.getMonth(),\n\t\t\tday: d.getDate(),\n\t\t\tweekday: d.getDay(),\n\t\t\thour: d.getHours(),\n\t\t\tminute: d.getMinutes(),\n\t\t\tsecond: d.getSeconds(),\n\t\t\tmillisecond: d.getMilliseconds(),\n\t\t};\n\t}\n\n\tlocalMidnight(year: number, month0: number, day: number): number {\n\t\treturn new Date(year, month0, day).getTime();\n\t}\n\n\tlocalWallClock(year: number, month0: number, day: number, minutesPastMidnight: number): number {\n\t\t// Anchored at midnight and then moved by the minutes FIELD, so the\n\t\t// result is the wall-clock reading asked for whatever the day's length.\n\t\tconst anchored = new Date(year, month0, day, 0, 0, 0, 0);\n\t\tanchored.setMinutes(minutesPastMidnight);\n\t\treturn anchored.getTime();\n\t}\n\n\taddDays(epochMs: number, days: number): number {\n\t\tconst date = new Date(epochMs);\n\t\tdate.setDate(date.getDate() + days);\n\t\treturn date.getTime();\n\t}\n\n\taddMonths(epochMs: number, months: number): number {\n\t\tconst date = new Date(epochMs);\n\t\tconst dayOfMonth = date.getDate();\n\t\t// Parked on the 1st before the month field moves: `setMonth()` keeps\n\t\t// the day number, so a 31st aimed at a 30-day month would overflow\n\t\t// into the month after it. Clamping afterwards is what keeps the month\n\t\t// the caller asked for.\n\t\tdate.setDate(1);\n\t\tdate.setMonth(date.getMonth() + months);\n\t\tdate.setDate(Math.min(dayOfMonth, daysInMonth(date.getFullYear(), date.getMonth())));\n\t\treturn date.getTime();\n\t}\n\n\tutcOffsetMinutes(epochMs: number): number {\n\t\t// `getTimezoneOffset()` is (UTC minus local), so its sign is inverted\n\t\t// relative to the \"+HH:MM ahead of UTC\" reading every caller wants.\n\t\t// Subtracted from zero rather than negated, so a zero offset is 0 and\n\t\t// not -0, which a second backend could not be expected to reproduce.\n\t\treturn 0 - new Date(epochMs).getTimezoneOffset();\n\t}\n\n\tparseIso8601(text: string): number {\n\t\treturn new Date(text).getTime();\n\t}\n\n\tformatLongDate(epochMs: number, locale: string): string {\n\t\treturn new Date(epochMs).toLocaleDateString(locale, { weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\" });\n\t}\n\n\tformatTimeOfDay(epochMs: number, locale: string): string {\n\t\treturn new Date(epochMs).toLocaleTimeString(locale);\n\t}\n\n\tzoneOffsetMinutes(zone: string, epochMs: number): number {\n\t\t// The `Intl` round trip: read the instant as the zone's wall-clock\n\t\t// fields, re-read those fields as if they were UTC, and the difference\n\t\t// from the instant is the zone's offset then, daylight saving included.\n\t\tconst f = zonedFields(zone, epochMs);\n\t\t// `|| 0` folds the -0 a negative sub-minute difference rounds to.\n\t\treturn Math.round((utcMs(f.year, f.month0, f.day, f.hour, f.minute, f.second) - epochMs) / 60000) || 0;\n\t}\n\n\tfieldsInZone(zone: string, epochMs: number): ZonedFields {\n\t\treturn zonedFields(zone, epochMs);\n\t}\n\n\tformatTimeInZone(zone: string, epochMs: number): string {\n\t\treturn timeInZone(zone, epochMs);\n\t}\n\n\tformatDateInZone(zone: string, epochMs: number): string {\n\t\treturn dateInZone(zone, epochMs);\n\t}\n}\n\n/**\n * The one `Date` backend, shared by every engine that configures no other.\n *\n * Stateless, so sharing is safe: it holds no zone of its own and reads the\n * process's. It is also what the sites with no engine in hand use (the\n * normaliser rules that fuse a literal, `days in <period>`, the stocks and\n * historical-currency date phrases, and `formatValue`), which is why an\n * engine's own backend is the default here rather than a second copy.\n */\nexport const DATE_CALENDAR: CalendarBackend = new DateCalendar();\n\n/**\n * The backend a plugin function or converter should compute with: the one\n * on its execution context, or the `Date` backend when the handler was\n * called with no context (a direct call from a test, or an `as` converter\n * invoked outside the VM).\n *\n * @param context - The execution context the handler received, if any.\n * @returns The engine's backend when the context carries one, else {@link DATE_CALENDAR}.\n */\nexport function calendarOf(context?: { readonly calendar?: CalendarBackend }): CalendarBackend {\n\treturn context?.calendar ?? DATE_CALENDAR;\n}\n\n/**\n * The `Date` backend, computing in a named IANA zone instead of the host\n * process's.\n *\n * Every zone-free answer is inherited unchanged from {@link DateCalendar}:\n * `now()` is still the clock, `parseIso8601` still reads the two ECMAScript\n * spellings, and the four named-zone methods already took the zone as an\n * argument. What changes is what \"local\" means, which is exactly the set of\n * questions {@link CalendarBackend} says depends on a zone: which day an\n * instant falls on, what a wall-clock reading names, what a day or a month\n * later is, and what the offset from UTC is.\n *\n * Those are answered through `Intl`, the same data the base class already\n * reads named zones with, so the accuracy is the same and nothing new is\n * bundled. The one place it is a simplification is a wall clock that a\n * daylight-saving transition made ambiguous or non-existent (01:30 on a\n * spring-forward morning): {@link zonedWallClockToUtcMs} resolves it one way,\n * and a `Temporal` backend's `disambiguation: 'compatible'` may resolve it an\n * hour differently.\n */\n/**\n * An ISO 8601 date-time with a time of day and NO offset and no `Z`: the one\n * spelling whose instant depends on which zone reads it. Anchored at both\n * ends, so a date-only string and anything carrying an offset fall through to\n * the base class untouched.\n */\nconst ISO_LOCAL_DATE_TIME = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d+))?)?$/;\n\nclass ZonedDateCalendar extends DateCalendar {\n\t/**\n\t * @param namedZone - An IANA zone name `Intl` accepts.\n\t */\n\tconstructor(private readonly namedZone: string) {\n\t\tsuper();\n\t}\n\n\tzone(): string {\n\t\treturn this.namedZone;\n\t}\n\n\tfields(epochMs: number): CalendarFields {\n\t\tconst f = zonedFields(this.namedZone, epochMs);\n\t\t// `zonedFields` answers no weekday and no millisecond: the weekday is a\n\t\t// pure function of the zoned date (`Gregorian.dayNumber`, counting from a\n\t\t// Thursday), and the millisecond is the instant's own, which no zone\n\t\t// offset in use is fractional enough to move.\n\t\tconst weekday = (((dayNumber(f.year, f.month0, f.day) + 4) % 7) + 7) % 7;\n\t\treturn {\n\t\t\tyear: f.year, month0: f.month0, day: f.day, weekday,\n\t\t\thour: f.hour, minute: f.minute, second: f.second,\n\t\t\tmillisecond: ((epochMs % 1000) + 1000) % 1000,\n\t\t};\n\t}\n\n\tlocalMidnight(year: number, month0: number, day: number): number {\n\t\treturn zonedWallClockToUtcMs(year, month0, day, 0, 0, this.namedZone, this);\n\t}\n\n\tlocalWallClock(year: number, month0: number, day: number, minutesPastMidnight: number): number {\n\t\t// The minutes go in as the MINUTE field, not as elapsed time, so a\n\t\t// reading of 540 is 09:00 on that date even on a 23-hour day. `Date.UTC`\n\t\t// rolls a minute field past 59 into the hour, which is what makes one\n\t\t// argument enough.\n\t\treturn zonedWallClockToUtcMs(year, month0, day, 0, minutesPastMidnight, this.namedZone, this);\n\t}\n\n\taddDays(epochMs: number, days: number): number {\n\t\tconst f = zonedFields(this.namedZone, epochMs);\n\t\treturn this.reanchor(f, f.day + days, epochMs);\n\t}\n\n\taddMonths(epochMs: number, months: number): number {\n\t\tconst f = zonedFields(this.namedZone, epochMs);\n\t\tconst target = new Date(Date.UTC(f.year, f.month0 + months, 1));\n\t\tconst clampedDay = Math.min(f.day, daysInMonth(target.getUTCFullYear(), target.getUTCMonth()));\n\t\treturn zonedWallClockToUtcMs(\n\t\t\ttarget.getUTCFullYear(), target.getUTCMonth(), clampedDay,\n\t\t\tf.hour, f.minute, this.namedZone, this,\n\t\t) + f.second * 1000 + (((epochMs % 1000) + 1000) % 1000);\n\t}\n\n\tutcOffsetMinutes(epochMs: number): number {\n\t\treturn this.zoneOffsetMinutes(this.namedZone, epochMs);\n\t}\n\n\tparseIso8601(text: string): number {\n\t\t// The one reading in that contract that depends on a zone: a date-time\n\t\t// with no offset and no `Z` is LOCAL time, and local here is the named\n\t\t// zone. Without this the backend contradicted itself, computing\n\t\t// `2026-04-03` at New York midnight while reading `2026-04-03T09:30` as\n\t\t// half past nine in the host process's zone. It is also what the\n\t\t// `Temporal` backend already does (`TemporalCalendar.parseIso8601`\n\t\t// resolves a bare wall clock in its own zone), so the two agree.\n\t\t//\n\t\t// Everything else is the base class byte for byte: a date-only string is\n\t\t// still UTC midnight and an explicit offset is still subtracted, both\n\t\t// frozen by the interface's contract.\n\t\tconst matched = ISO_LOCAL_DATE_TIME.exec(text.trim());\n\t\tif (matched === null) return super.parseIso8601(text);\n\t\tconst [, year, month, day, hour, minute, second, fraction] = matched;\n\t\tconst millisecond = fraction === undefined ? 0 : Number(fraction.slice(0, 3).padEnd(3, \"0\"));\n\t\treturn zonedWallClockToUtcMs(Number(year), Number(month) - 1, Number(day), Number(hour), Number(minute), this.namedZone, this)\n\t\t\t+ (second === undefined ? 0 : Number(second)) * 1000 + millisecond;\n\t}\n\n\tformatLongDate(epochMs: number, locale: string): string {\n\t\treturn longDateInZone(this.namedZone, epochMs, locale);\n\t}\n\n\tformatTimeOfDay(epochMs: number, locale: string): string {\n\t\treturn timeOfDayInZone(this.namedZone, epochMs, locale);\n\t}\n\n\t/** Rebuild an instant on a (possibly overflowed) day, holding its wall clock down to the millisecond. */\n\tprivate reanchor(f: ZonedFields, day: number, epochMs: number): number {\n\t\treturn zonedWallClockToUtcMs(f.year, f.month0, day, f.hour, f.minute, this.namedZone, this)\n\t\t\t+ f.second * 1000 + (((epochMs % 1000) + 1000) % 1000);\n\t}\n}\n\n/**\n * A `Date` backend that computes in a named time zone rather than the host\n * process's.\n *\n * This is how a host pins the zone the engine reads dates in, and it is the\n * only knob for it: the zone belongs to the calendar backend, which already\n * owns what \"local\" means, so there is deliberately no `date.zone` config\n * field to drift against it.\n *\n * ```ts\n * import { createEngine, dateCalendarInZone } from \"solve-engine\";\n * const engine = createEngine({ calendar: dateCalendarInZone(\"Asia/Tokyo\") });\n * ```\n *\n * It ships on the `Date` backend on purpose. `Temporal` is undefined on Node\n * 24 and in Safari, so \"pass a `Temporal` backend\" would put the zone out of\n * reach for most hosts today; `Temporal` stays an accuracy upgrade for the\n * ambiguous wall clocks around a daylight-saving transition, never a\n * prerequisite for naming a zone at all.\n *\n * @param zone - An IANA zone name, e.g. `\"Asia/Tokyo\"`.\n * @returns A backend whose local zone is that one.\n * @throws A `DATE_ZONE_UNKNOWN` config error when this runtime's `Intl` does\n * not know the zone. Refused here rather than per line, because a backend\n * that cannot compute in the zone it was asked for must not quietly answer\n * in another one.\n */\nexport function dateCalendarInZone(zone: string): CalendarBackend {\n\tif (!isSupportedZone(zone)) {\n\t\tthrow ErrorFactory.config(\n\t\t\tDatetimeErrorCodes.DATE_ZONE_UNKNOWN,\n\t\t\t`dateCalendarInZone(\"${zone}\") is not a time zone this runtime knows.`,\n\t\t);\n\t}\n\treturn new ZonedDateCalendar(zone);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import {a}from'./chunk-RAF57WYO.js';import {l,m,g}from'./chunk-BCY2WY5P.js';import {b as b$1}from'./chunk-76F3LCIL.js';import {J as J$1,K}from'./chunk-CL7DM2FX.js';import {h,i,P as P$1}from'./chunk-LQIRBP4Q.js';import {b}from'./chunk-REZQFPVX.js';import {c as c$1}from'./chunk-Y7XRA2EV.js';import {c,b as b$2}from'./chunk-VB6QMU2W.js';var P=class{constructor(){this.root=null;}get length(){return this.root?this.root.size:0}get isEmpty(){return this.root===null}getAt(e){if(!(e<0||e>=(this.root?.size??0)))return this.nodeAt(this.root,e).lineId}insertAt(e,t){let[n,r]=I(this.root,e);this.root=S(S(n,te(t)),r);}deleteAt(e){if(e<0||e>=(this.root?.size??0))return;let[t,n]=I(this.root,e),[r,s]=I(n,1),i=r?r.lineId:void 0;return this.root=S(t,s),i}spliceAt(e,t,n){let r=Math.max(0,e),s=Math.min(Math.max(0,t),(this.root?.size??0)-r),[i,a]=I(this.root,r),[l,o]=I(a,s),c=ne(l),d=B(n,0,n.length);return this.root=S(S(i,d),o),c}replaceAll(e){this.root=B(e,0,e.length);}getRange(e,t){let n=Math.max(0,e),r=Math.min((this.root?.size??0)-1,t);if(n>r)return [];let s=[];return this.collectRange(this.root,n,r,0,s),s}clear(){this.root=null;}*[Symbol.iterator](){yield*this.inOrder(this.root);}*inOrder(e){e&&(yield*this.inOrder(e.left),yield e.lineId,yield*this.inOrder(e.right));}nodeAt(e,t){let n=e.left?e.left.size:0;return t<n?this.nodeAt(e.left,t):t===n?e:this.nodeAt(e.right,t-n-1)}collectRange(e,t,n,r,s){if(!e)return;let i=e.left?e.left.size:0,a=r+i;a>t&&e.left&&this.collectRange(e.left,t,n,r,s),a>=t&&a<=n&&s.push(e.lineId),a<n&&e.right&&this.collectRange(e.right,t,n,a+1,s);}};function te(u){return {lineId:u,size:1,priority:Math.random(),left:null,right:null}}function T(u){u.size=1+(u.left?u.left.size:0)+(u.right?u.right.size:0);}function S(u,e){return u?e?u.priority>e.priority?(u.right=S(u.right,e),T(u),u):(e.left=S(u,e.left),T(e),e):u:e}function I(u,e){if(!u)return [null,null];let t=u.left?u.left.size:0;if(e<=t){let[n,r]=I(u.left,e);return u.left=r,T(u),[n,u]}else {let[n,r]=I(u.right,e-t-1);return u.right=n,T(u),[u,r]}}function ne(u){let e=[];return F(u,e),e}function F(u,e){u&&(F(u.left,e),e.push(u.lineId),F(u.right,e));}function B(u,e,t){if(e>=t)return null;let n=Math.floor((e+t)/2),r=re(n);return {lineId:u[n],size:t-e,priority:r,left:B(u,e,n),right:B(u,n+1,t)}}function re(u){let e=u;return e=(e>>16^e)*73244475,e=(e>>16^e)*73244475,e=e>>16^e,e/4294967295}var R=class{constructor(e=b.performance.maxDocumentLines){this.lines=new Map;this.orderTree=new P;this.nextLineId=1;this._positionCache=null;this.dirtyLineIds=new Set;this.maxLines=e;}setDocument(e){if(b$1(e,this.maxLines)>this.maxLines)throw c.execution("DOCUMENT_TOO_LARGE",`This document has more than ${this.maxLines.toLocaleString("en-US")} lines, which is the most the engine will hold at once`,{maxLines:this.maxLines});this.lines.clear(),this.orderTree.clear(),this._positionCache=null,this.dirtyLineIds.clear(),this.nextLineId=1;let n=e.split(`
2
+ `),r=new Array(n.length);for(let s=0;s<n.length;s++){let i=this.nextLineId++;r[s]=i,this.lines.set(i,{lineId:i,textHash:a(n[s]),text:n[s],expressions:[],bytecodes:[],reads:[],writes:[],results:[],result:null,dirty:true,isVariableDef:false,isEmpty:n[s].trim().length===0,inlineSolveCount:0});}this.orderTree.replaceAll(r);for(let s of r)this.dirtyLineIds.add(s);}applyChanges(e){let t=[],n=[],r=[...e].sort((s,i)=>i.startLine-s.startLine);for(let s of r){let i=s.startLine-1,a$1=[];for(let o of s.insertLines){let c=this.nextLineId++;a$1.push(c),t.push(c),this.lines.set(c,{lineId:c,textHash:a(o),text:o,expressions:[],bytecodes:[],reads:[],writes:[],results:[],result:null,dirty:true,isVariableDef:false,isEmpty:o.trim().length===0,inlineSolveCount:0});}for(let o of a$1)this.dirtyLineIds.add(o);let l=this.orderTree.spliceAt(i,s.deleteCount,a$1);for(let o of l)n.push(o),this.lines.delete(o),this.dirtyLineIds.delete(o);}return this._positionCache=null,{inserted:t,removed:n}}insertLines(e,t){let n={startLine:e,deleteCount:0,insertLines:t};return this.applyChanges([n]).inserted}deleteLines(e,t){let n={startLine:e,deleteCount:t-e+1,insertLines:[]};return this.applyChanges([n]).removed}editLine(e,t){let n=this.getLineAt(e);if(!n)return false;let r=a(t);return r===n.textHash?false:(n.text=t,n.textHash=r,n.expressions=[],n.bytecodes=[],n.results=[],n.result=null,n.inlineSolveCount=0,n.dirty=true,this.dirtyLineIds.add(n.lineId),n.isEmpty=t.trim().length===0,true)}getLineAt(e){let t=e-1,n=this.orderTree.getAt(t);if(n!==void 0)return this.lines.get(n)}getLinePosition(e){if(this._positionCache)return this._positionCache.get(e)??-1;this._positionCache=new Map;let t=1;for(let n of this.orderTree)this._positionCache.set(n,t++);return this._positionCache.get(e)??-1}getVisibleLines(e,t){let n=this.orderTree.getRange(e-1,t-1),r=[];for(let s of n){let i=this.lines.get(s);i&&r.push(i);}return r}getAllLines(){return this.getVisibleLines(1,this.lineCount)}getLineById(e){return this.lines.get(e)}getDirtyLines(){let e=[];for(let t of this.lines.values())t.dirty&&e.push(t);return e}hasAnyDirtyLineBefore(e){for(let t of this.dirtyLineIds){let n=this.getLinePosition(t);if(n>=1&&n<e)return true}return false}hasAnyDirtyVariableDefLineBefore(e){for(let t of this.dirtyLineIds){let n=this.lines.get(t);if(!n||!n.isVariableDef)continue;let r=this.getLinePosition(t);if(r>=1&&r<e)return true}return false}get dirtyCount(){return this.dirtyLineIds.size}isBytecodeValid(e,t){let n=this.lines.get(e);return n!==void 0&&n.textHash===t}markClean(e){let t=this.lines.get(e);t&&(t.dirty=false,this.dirtyLineIds.delete(e));}markDirtyByLineNumber(e){let t=this.getLineAt(e);t&&(t.dirty=true,this.dirtyLineIds.add(t.lineId));}markDirty(e){let t=this.lines.get(e);t&&(t.dirty=true,this.dirtyLineIds.add(e));}invalidateAll(){for(let e of this.lines.values())e.dirty=true;this.dirtyLineIds=new Set(this.lines.keys());}updateLineResult(e,t,n,r,s,i,a,l=0){let o=this.lines.get(e);o&&(o.results=t,o.result=t[0]?.[0]??null,o.bytecodes=n,o.expressions=r,o.reads=s,o.writes=i,o.isVariableDef=a,o.inlineSolveCount=l,o.dirty=false,this.dirtyLineIds.delete(e));}updateLineCompiled(e,t,n,r,s,i,a=0){let l=this.lines.get(e);l&&(l.expressions=t,l.bytecodes=n,l.reads=r,l.writes=s,l.isVariableDef=i,l.inlineSolveCount=a);}get lineCount(){return this.orderTree.length}get isEmpty(){return this.orderTree.isEmpty}*[Symbol.iterator](){for(let e of this.orderTree){let t=this.lines.get(e);t&&(yield t);}}clear(){this.lines.clear(),this.orderTree.clear(),this._positionCache=null,this.nextLineId=1;}toJSON(){return {lineCount:this.lineCount,lines:this.getAllLines().map(e=>({lineId:e.lineId,text:e.text.substring(0,80),textHash:e.textHash,dirty:e.dirty,isVariableDef:e.isVariableDef,isEmpty:e.isEmpty,hasBytecode:e.bytecodes.length>0,hasResult:e.results.length>0,inlineSolveCount:e.inlineSolveCount,reads:e.reads,writes:e.writes}))}}};var A=class{constructor(){this.worker=null;this.nextId=1;this.pending=new Map;}ensureWorker(){return this.worker?this.worker:(this.worker=g(),this.worker.onmessage=e=>{let t=e.data;if(!t||t.type!=="COMPILE_RESULT")return;let n=this.pending.get(t.id);if(!n)return;this.pending.delete(t.id);let r=[];for(let s of t.results)r.push(this.reconstructResult(s));n.resolve(r);},this.worker.onerror=e=>{for(let[t,n]of this.pending)n.reject(new Error(`Compilation worker error: ${e.message}`)),this.pending.delete(t);},this.worker)}async compileBatch(e){if(e.length===0)return [];let t=this.ensureWorker(),n=this.nextId++;return new Promise((r,s)=>{this.pending.set(n,{resolve:r,reject:s}),t.postMessage({type:"COMPILE_BATCH",id:n,items:e});})}storeResults(e,t){let n=new Map;for(let i of e){if(i.error)continue;let a=t.getLineById(i.lineId);if(!a||a.textHash!==i.compiledAgainstHash)continue;let l=n.get(i.lineId);l||(l={bytecodes:[],reads:new Set,writes:new Set,isVariableDef:false,expressions:a.expressions.length>0?[...a.expressions]:[],textHash:i.compiledAgainstHash},n.set(i.lineId,l)),l.bytecodes.push(i.program);for(let o of i.reads)l.reads.add(o);for(let o of i.writes)l.writes.add(o);i.isVariableDef&&(l.isVariableDef=true);}let s=0;for(let[i,a]of n){if(a.bytecodes.length===0)continue;let o=t.getLineById(i)?.inlineSolveCount??0;t.updateLineCompiled(i,a.expressions,a.bytecodes,[...a.reads],[...a.writes],a.isVariableDef,o),s+=a.bytecodes.length;}return s}terminate(){this.worker&&(this.worker.terminate(),this.worker=null,this.pending.clear());}get isActive(){return this.worker!==null}reconstructResult(e){if(e.error)return {lineId:e.lineId,compiledAgainstHash:e.compiledAgainstHash,program:{opcodes:new Uint8Array(0),numbers:new Float64Array(0),strings:[],hasAsync:false},reads:[],writes:[],isVariableDef:false,error:e.error};let t=e.opcodesLength>0?new Uint8Array(e.opcodesBuffer,0,e.opcodesLength):new Uint8Array(0),n=e.numbersLength>0?new Float64Array(e.numbersBuffer,0,e.numbersLength):new Float64Array(0),r={opcodes:t,numbers:n,strings:e.strings,hasAsync:false};return {lineId:e.lineId,compiledAgainstHash:e.compiledAgainstHash,program:r,reads:e.reads,writes:e.writes,isVariableDef:e.isVariableDef,error:null}}};var U=128,k=3,J=6,Q=2,X=k,H=class u{constructor(){this.lastViewportStart=null;this.savedDirection=null;this.pageAccess=new Map;this.accessSeq=0;}static pageForLine(e){return Math.floor((e-1)/U)}static pageRange(e,t){return {startLine:e*U+1,endLine:Math.min((e+1)*U,t)}}detectDirection(e){return this.lastViewportStart===null?null:e.startLine>this.lastViewportStart?"down":e.startLine<this.lastViewportStart?"up":null}maintainAfterEval(e,t){this.savedDirection=this.detectDirection(e),this.lastViewportStart=e.startLine;let n=t.lineCount,r=u.pageForLine(e.startLine),s=u.pageForLine(e.endLine),i=u.pageForLine(n),a=Math.max(0,r-k),l=Math.min(i,s+k),o=Math.max(0,r-J),c=Math.min(i,s+J);for(let h=a;h<=l;h++)this.touchPage(h);for(let h=o;h<=c;h++)h>=a&&h<=l||this.evictPageResults(h,t,n);let d=o-1,p=Math.max(0,d-X+1);for(let h=p;h<=d;h++)this.evictPageBytecode(h,t,n);let f=c+1,g=Math.min(i,f+X-1);for(let h=f;h<=g;h++)this.evictPageBytecode(h,t,n);}getPreloadTargets(e,t){let n=this.savedDirection;if(!n)return [];let r=[],s=u.pageForLine(e.endLine),i=u.pageForLine(e.startLine),a=u.pageForLine(t.lineCount),l=[];if(n==="down"){let o=s+k+1,c=Math.min(o+Q-1,a);for(let d=o;d<=c&&d<=a;d++)l.push(d);}else {let o=i-k-1;for(let c=o;c>o-Q&&c>=0;c--)l.push(c);}for(let o of l){let c=u.pageRange(o,t.lineCount);for(let d=c.startLine;d<=c.endLine;d++){let p=t.getLineAt(d);if(p&&p.dirty&&!(p.bytecodes.length>0&&!p.isVariableDef)&&!p.isEmpty)if(p.expressions.length>0)for(let f of p.expressions)f.trim()&&r.push({lineId:p.lineId,expression:f,textHash:p.textHash});else {let f=c$1.findInlineSolves(p.text);if(f.length>0)for(let g of f)g.expression.trim()&&r.push({lineId:p.lineId,expression:g.expression,textHash:p.textHash});else {let g=p.text.trim();g&&r.push({lineId:p.lineId,expression:g,textHash:p.textHash});}}}}return r}clear(){this.pageAccess.clear(),this.accessSeq=0,this.lastViewportStart=null,this.savedDirection=null;}touchPage(e){this.pageAccess.set(e,++this.accessSeq);}evictPageResults(e,t,n){let r=u.pageRange(e,n);for(let s=r.startLine;s<=r.endLine;s++){let i=t.getLineAt(s);i&&!i.isVariableDef&&i.results.length>0&&(i.results=[],i.result=null);}}evictPageBytecode(e,t,n){let r=u.pageRange(e,n);for(let s=r.startLine;s<=r.endLine;s++){let i=t.getLineAt(s);!i||i.isVariableDef||(i.bytecodes.length>0||i.results.length>0)&&(i.bytecodes=[],i.results=[],i.result=null,t.markDirty(i.lineId));}}};var Y=(r=>(r[r.Tier1=1]="Tier1",r[r.Tier2=2]="Tier2",r[r.Tier3=3]="Tier3",r[r.Skipped=0]="Skipped",r))(Y||{}),D=class{constructor(e,t,n){this.compilationWorker=null;this.globalUnsubscribe=null;this.doc=e,this.engine=t,this.dag=t.getDag(),this.checkpointer=n??null,this.pageManager=new H,this.engine.setDocumentModel(this.doc),this.globalUnsubscribe=J$1.subscribe(r=>{for(let s of this.dag.getAffectedLines(K(r)))this.doc.markDirtyByLineNumber(s);});}evaluate(e,t){this.engine.setKeystrokeSignal(t??null),h();try{this.reseedAccumulators();let n=[],r=new Map,s={tier1:0,tier2:0,tier3:0,skipped:0},i=this.doc.lineCount,a=Math.min(e.endLine,i);for(let l=1;l<=a;l++){let o=this.doc.getLineAt(l);if(!o){s.skipped++;continue}let c=l>=e.startLine&&l<=e.endLine,d=this.evaluateSingleLine(o,l,c);n.push(d),d.tier===1?s.tier1++:d.tier===2?s.tier2++:d.tier===3?s.tier3++:s.skipped++,d.results&&c&&r.set(l,d.results.flat());}return this.pageManager.maintainAfterEval(e,this.doc),{lines:n,resultMap:r,tierCounts:s}}finally{this.engine.setKeystrokeSignal(null),i();}}backgroundCompile(e){let t=[],n=this.doc.lineCount,r=e.endLine+1;for(let s=r;s<=n;s++){let i=this.doc.getLineAt(s);if(!i||!i.dirty||i.bytecodes.length>0&&!i.isVariableDef)continue;let a=this.evaluateSingleLine(i,s,false);t.push(a);}return t}dispatchBackgroundCompiles(e){let t=this.collectInvisibleCompileTargets(e);t.length!==0&&(this.compilationWorker||(this.compilationWorker=new A),this.compilationWorker.compileBatch(t).then(n=>{this.compilationWorker.storeResults(n,this.doc);}).catch(n=>{}));}terminateWorker(){this.compilationWorker&&(this.compilationWorker.terminate(),this.compilationWorker=null),this.globalUnsubscribe&&(this.globalUnsubscribe(),this.globalUnsubscribe=null);}getDoc(){return this.doc}evaluateAll(e){let t={startLine:1,endLine:this.doc.lineCount};return this.evaluate(t,e)}setViewport(e,t){if(this.engine.setKeystrokeSignal(t??null),e.startLine>1&&this.hasDirtyLinesBefore(e.startLine))return this.checkpointer?.clear(),this.evaluate(e,t);this.pageManager.maintainAfterEval(e,this.doc),this.preloadNextPages(e),this.restoreTo(e.startLine-1),h();try{return this.collectEvalResults(e.startLine,e.endLine)}finally{this.engine.setKeystrokeSignal(null),i();}}applyTransaction(e){let t=new Set;for(let s of e)for(let i=0;i<s.deleteCount;i++){let a=s.startLine+i,l=this.dag.getWrites(a);for(let o of l)t.add(o);this.dag.removeLine(a),this.engine.getLineCache().removeAllForLine(a);}let n=new Set;for(let s of t){let i=this.dag.getAffectedLines(s);for(let a of i){let l=this.doc.getLineAt(a);l&&n.add(l.lineId);}}let r=this.doc.applyChanges(e);this.checkpointer?.clear();for(let s of n)this.doc.markDirty(s);return this.dag.clear(),{inserted:r.inserted,removed:r.removed}}reseedAccumulators(){let e=this.engine.resetAccumulators();if(e.size===0)return;let t=this.doc.lineCount;for(let n=1;n<=t;n++){let r=this.dag.getWrites(n);if(r.size!==0){for(let s of r)if(e.has(s)){this.doc.markDirtyByLineNumber(n);break}}}}collectEvalResults(e,t){let n=[],r=new Map,s={tier1:0,tier2:0,tier3:0,skipped:0},i=this.doc.lineCount,a=Math.min(t,i);for(let l=e;l<=a;l++){let o=this.doc.getLineAt(l);if(!o)continue;let c=this.evaluateSingleLine(o,l,true);n.push(c),c.tier===1?s.tier1++:c.tier===2?s.tier2++:c.tier===3?s.tier3++:s.skipped++,c.results&&r.set(l,c.results.flat());}return {lines:n,resultMap:r,tierCounts:s}}hasDirtyLinesBefore(e){return this.doc.hasAnyDirtyVariableDefLineBefore(e)}evaluateSingleLine(e,t,n){let r={lineId:e.lineId,lineNumber:t};if(e.isEmpty||l(e.text))return e.isEmpty=true,this.doc.markClean(e.lineId),{...r,tier:0,result:null,error:null};let{expressions:s,inlineSolveCount:i}=this.extractExpressions(e);return s.length===0?(e.isEmpty=true,this.doc.markClean(e.lineId),{...r,tier:0,result:null,error:null}):e.dirty?n?this.evaluateTier1(e,t,s,i,r):e.bytecodes.length>0&&e.bytecodes.length===s.length&&!e.isVariableDef?{...r,tier:0,result:null,error:null}:this.evaluateTier3(e,t,s,i,r):n&&e.bytecodes.length>0?this.evaluateTier2(e,t,r):{...r,tier:0,result:null,error:null}}evaluateTier1(e,t,n,r,s){let i=[],a=[],l=new Set,o=new Set,c=false,d=null,p=null,f=false,g=false;for(let y of n){if(!y.trim())continue;let b=null,L;try{let m=this.engine.evaluateLine(t,y);b=[m],d=m,L=this.engine.getLineCache().get(t,y);}catch(m){let x=m instanceof Error?m.message:String(m);p||(p=x),f=true,b=null;}if(b&&b.some(m=>m.type===12)&&(g=true),b?i.push(b):i.push([P$1("eval_failed",p??"unknown error")]),L){a.push(L.bytecode);for(let m of L.readVariables)l.add(m);L.writeVariable&&(o.add(L.writeVariable),c=true);}else try{let{program:m,reads:x,writes:E}=this.engine.compileExpression(y);a.push(m);for(let C of x)l.add(C);for(let C of E)o.add(C);E.length>0&&(c=!0);}catch(m){if(a.push({opcodes:new Uint8Array(0),numbers:new Float64Array(0),strings:[],hasAsync:false}),m instanceof b$2&&m.context){let x=m.context.reads,E=m.context.writes;if(Array.isArray(x))for(let C of x)l.add(C);if(Array.isArray(E))for(let C of E)o.add(C);}}}let h=[...l],v=[...o];return f||g?(this.doc.updateLineCompiled(e.lineId,n,a,h,v,c,r),e.results=i,e.result=i[0]?.[0]??null,e.inlineSolveCount=r,e.expressions=n):this.doc.updateLineResult(e.lineId,i,a,n,h,v,c,r),this.dag.registerLine(t,h,v),this.checkpointer&&v.length>0&&!f&&!g&&this.checkpointer.snapshot(t,e.lineId,v),{...s,tier:1,result:d,results:i,error:p}}evaluateTier2(e,t,n){if(e.bytecodes.length===0)return {...n,tier:0,result:null,error:null};let r=[],s=null,i=null,a=false;for(let l of e.bytecodes)if(l.opcodes.length!==0)try{let o=this.engine.executeCached(l,t);s=o,r.push([o]);}catch(o){let c=o instanceof Error?o.message:String(o);i||(i=c),a=true,r.push([P$1("exec_failed",c)]);}return this.dag.registerLine(t,e.reads,e.writes),e.results=r,e.result=r[0]?.[0]??null,a&&this.doc.markDirty(e.lineId),{...n,tier:2,result:s,results:r,error:i}}evaluateTier3(e,t,n,r,s){let i=[],a=new Set,l=new Set,o=false,c=null,d=null,p=false,f=false;for(let v of n)if(v.trim())try{let{program:y,reads:b,writes:L}=this.engine.compileExpression(v);i.push(y);for(let m of b)a.add(m);for(let m of L)l.add(m);L.length>0&&(o=!0),L.length>0&&y.opcodes.length>0&&(c=this.engine.executeCached(y,t),c&&c.type===12&&(f=!0));}catch(y){let b=y instanceof Error?y.message:String(y);d||(d=b),p=true,i.push({opcodes:new Uint8Array(0),numbers:new Float64Array(0),strings:[],hasAsync:false});}let g=[...a],h=[...l];return this.doc.updateLineCompiled(e.lineId,n,i,g,h,o,r),this.dag.registerLine(t,g,h),o&&c&&!p&&!f&&(e.results=[[c]],e.result=c,this.doc.markClean(e.lineId),this.checkpointer&&this.checkpointer.snapshot(t,e.lineId,h)),{...s,tier:3,result:c,results:o&&c&&!p&&!f?[[c]]:void 0,error:d}}restoreTo(e){this.checkpointer&&this.checkpointer.restoreTo(e);}getCheckpointer(){return this.checkpointer}getPageManager(){return this.pageManager}preloadNextPages(e){let t=this.pageManager.getPreloadTargets(e,this.doc);t.length!==0&&(this.compilationWorker||(this.compilationWorker=new A),this.compilationWorker.compileBatch(t).then(n=>{this.compilationWorker.storeResults(n,this.doc);}).catch(n=>{}));}collectInvisibleCompileTargets(e){let t=[],n=this.doc.lineCount,r=e.endLine+1;for(let s=r;s<=n;s++){let i=this.doc.getLineAt(s);if(!i||!i.dirty||i.bytecodes.length>0&&!i.isVariableDef||i.isEmpty||l(i.text))continue;let{expressions:a}=this.extractExpressions(i);if(a.length!==0)for(let l of a)l.trim()&&t.push({lineId:i.lineId,expression:l,textHash:i.textHash});}return t}extractExpressions(e){if(e.expressions.length>0)return {expressions:e.expressions,inlineSolveCount:e.inlineSolveCount};let t=e.text.trim();if(t.length===0)return {expressions:[],inlineSolveCount:0};let n=c$1.findInlineSolves(e.text);return n.length>0?{expressions:n.map(r=>r.expression),inlineSolveCount:n.length}:{expressions:[t],inlineSolveCount:0}}};function ee(u){return typeof u.unit=="string"?u.unit:String(u.value)}function ie(u,e,t={inputType:"markdown"}){let n=u.getDocumentModel(),r=new R;r.setDocument(e);let s=new D(r,u);try{let i=r.lineCount;s.evaluate({startLine:1,endLine:i});let a=[],l=[],o=0;for(let c=1;c<=i;c++){let d=r.getLineAt(c),p=d.text,f=o,g=o+p.length;o=g+1;let h=d.inlineSolveCount>0,v=[],y=null,b=null;d.isEmpty||(h?v=m(p,c).map((L,m)=>{let x=d.results[m]?.[0]??null;if(x&&x.type===13){let E=ee(x);return l.push(`Line ${c}: ${E}`),{...L,result:null,error:E}}return {...L,result:x,error:null}}):(y=d.expressions[0]??null,b=d.result??null,b&&b.type===13&&l.push(`Line ${c}: ${ee(b)}`))),a.push({lineNumber:c,text:p,startPosition:f,endPosition:g,isEmpty:d.isEmpty,hasInlineSolves:h,inlineSolves:v,expression:y,error:null,result:b});}return {lines:a,totalLines:i,errors:l}}finally{s.terminateWorker(),u.setDocumentModel(n);}}export{R as a,Y as b,D as c,ie as d};//# sourceMappingURL=chunk-UVHD7BBC.js.map
3
+ //# sourceMappingURL=chunk-UVHD7BBC.js.map