solve-engine 1.0.0-beta.0 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/BytecodeBuilder-3egMyuDi.d.cts +274 -0
  2. package/dist/BytecodeBuilder-3egMyuDi.d.ts +274 -0
  3. package/dist/Configuration-fVpd-HC-.d.cts +228 -0
  4. package/dist/Configuration-fVpd-HC-.d.ts +228 -0
  5. package/dist/EngineError-DvPSnhZi.d.cts +304 -0
  6. package/dist/EngineError-DvPSnhZi.d.ts +304 -0
  7. package/dist/Lexer-BJdhlnej.d.cts +531 -0
  8. package/dist/Lexer-D9l4Yrk2.d.ts +531 -0
  9. package/dist/NormalizerRule-BrVoVjmP.d.cts +163 -0
  10. package/dist/NormalizerRule-CEjf1FyD.d.ts +163 -0
  11. package/dist/PackageRegistry-D-Tv_7ca.d.cts +2572 -0
  12. package/dist/PackageRegistry-DaH4aIKP.d.ts +2572 -0
  13. package/dist/Parselet-CK8cQu2a.d.cts +299 -0
  14. package/dist/Parselet-ConOIdRO.d.ts +299 -0
  15. package/dist/ScopeManager-B5k0nk05.d.ts +559 -0
  16. package/dist/ScopeManager-CKfQtl7l.d.cts +559 -0
  17. package/dist/Token-0jpvUdPY.d.cts +245 -0
  18. package/dist/Token-0jpvUdPY.d.ts +245 -0
  19. package/dist/VMCheckpoints-BmDwIXgK.d.ts +171 -0
  20. package/dist/VMCheckpoints-CqFuLwrT.d.cts +171 -0
  21. package/dist/Value-KtAQNHur.d.cts +295 -0
  22. package/dist/Value-KtAQNHur.d.ts +295 -0
  23. package/dist/chunk-2RWAXT6O.js +3 -0
  24. package/dist/chunk-2RWAXT6O.js.map +1 -0
  25. package/dist/chunk-34RRD7PC.js +1492 -0
  26. package/dist/chunk-34RRD7PC.js.map +1 -0
  27. package/dist/chunk-3PPFLFH4.js +5097 -0
  28. package/dist/chunk-3PPFLFH4.js.map +1 -0
  29. package/dist/chunk-3VGDNEE3.js +84 -0
  30. package/dist/chunk-3VGDNEE3.js.map +1 -0
  31. package/dist/chunk-3YNVWKR2.cjs +370 -0
  32. package/dist/chunk-3YNVWKR2.cjs.map +1 -0
  33. package/dist/chunk-47LRVGOT.cjs +316 -0
  34. package/dist/chunk-47LRVGOT.cjs.map +1 -0
  35. package/dist/chunk-4MG4XKO2.js +1644 -0
  36. package/dist/chunk-4MG4XKO2.js.map +1 -0
  37. package/dist/chunk-4QADQTWS.js +2392 -0
  38. package/dist/chunk-4QADQTWS.js.map +1 -0
  39. package/dist/chunk-53B6KDDJ.cjs +1651 -0
  40. package/dist/chunk-53B6KDDJ.cjs.map +1 -0
  41. package/dist/chunk-5X2PTP6F.cjs +104 -0
  42. package/dist/chunk-5X2PTP6F.cjs.map +1 -0
  43. package/dist/chunk-5YEMOYSE.js +264 -0
  44. package/dist/chunk-5YEMOYSE.js.map +1 -0
  45. package/dist/chunk-64W6GLLZ.js +481 -0
  46. package/dist/chunk-64W6GLLZ.js.map +1 -0
  47. package/dist/chunk-6BKTCEUP.cjs +233 -0
  48. package/dist/chunk-6BKTCEUP.cjs.map +1 -0
  49. package/dist/chunk-6NTVRDQV.cjs +1642 -0
  50. package/dist/chunk-6NTVRDQV.cjs.map +1 -0
  51. package/dist/chunk-6RDSQURE.js +290 -0
  52. package/dist/chunk-6RDSQURE.js.map +1 -0
  53. package/dist/chunk-75JP4BZX.js +93 -0
  54. package/dist/chunk-75JP4BZX.js.map +1 -0
  55. package/dist/chunk-B7LXJ6LC.cjs +36 -0
  56. package/dist/chunk-B7LXJ6LC.cjs.map +1 -0
  57. package/dist/chunk-BVAR5J2F.js +257 -0
  58. package/dist/chunk-BVAR5J2F.js.map +1 -0
  59. package/dist/chunk-C4XZV6E7.cjs +269 -0
  60. package/dist/chunk-C4XZV6E7.cjs.map +1 -0
  61. package/dist/chunk-CCJPSHGI.cjs +40 -0
  62. package/dist/chunk-CCJPSHGI.cjs.map +1 -0
  63. package/dist/chunk-CLL7RUQV.cjs +316 -0
  64. package/dist/chunk-CLL7RUQV.cjs.map +1 -0
  65. package/dist/chunk-DM3LMRBC.js +329 -0
  66. package/dist/chunk-DM3LMRBC.js.map +1 -0
  67. package/dist/chunk-DUEZFTK2.js +38 -0
  68. package/dist/chunk-DUEZFTK2.js.map +1 -0
  69. package/dist/chunk-EBSPLUW4.cjs +489 -0
  70. package/dist/chunk-EBSPLUW4.cjs.map +1 -0
  71. package/dist/chunk-EHAHVROS.cjs +261 -0
  72. package/dist/chunk-EHAHVROS.cjs.map +1 -0
  73. package/dist/chunk-EIGTWK5N.js +167 -0
  74. package/dist/chunk-EIGTWK5N.js.map +1 -0
  75. package/dist/chunk-EPOXXJBK.js +96 -0
  76. package/dist/chunk-EPOXXJBK.js.map +1 -0
  77. package/dist/chunk-FEAIOR7N.cjs +91 -0
  78. package/dist/chunk-FEAIOR7N.cjs.map +1 -0
  79. package/dist/chunk-G535KJEG.js +312 -0
  80. package/dist/chunk-G535KJEG.js.map +1 -0
  81. package/dist/chunk-GCM5JHMX.js +88 -0
  82. package/dist/chunk-GCM5JHMX.js.map +1 -0
  83. package/dist/chunk-GOLDJNMZ.js +368 -0
  84. package/dist/chunk-GOLDJNMZ.js.map +1 -0
  85. package/dist/chunk-GW32KPCU.cjs +360 -0
  86. package/dist/chunk-GW32KPCU.cjs.map +1 -0
  87. package/dist/chunk-HTXVVJRA.cjs +1549 -0
  88. package/dist/chunk-HTXVVJRA.cjs.map +1 -0
  89. package/dist/chunk-HWSZJQCI.js +311 -0
  90. package/dist/chunk-HWSZJQCI.js.map +1 -0
  91. package/dist/chunk-IF532O7C.js +101 -0
  92. package/dist/chunk-IF532O7C.js.map +1 -0
  93. package/dist/chunk-J73SJHR3.cjs +2415 -0
  94. package/dist/chunk-J73SJHR3.cjs.map +1 -0
  95. package/dist/chunk-JBSYC7BB.cjs +7473 -0
  96. package/dist/chunk-JBSYC7BB.cjs.map +1 -0
  97. package/dist/chunk-KVILKGMS.js +228 -0
  98. package/dist/chunk-KVILKGMS.js.map +1 -0
  99. package/dist/chunk-LIPPNDBE.js +258 -0
  100. package/dist/chunk-LIPPNDBE.js.map +1 -0
  101. package/dist/chunk-LR7YASZF.cjs +172 -0
  102. package/dist/chunk-LR7YASZF.cjs.map +1 -0
  103. package/dist/chunk-M4N5GA5Z.cjs +309 -0
  104. package/dist/chunk-M4N5GA5Z.cjs.map +1 -0
  105. package/dist/chunk-M5LX5AOO.js +7459 -0
  106. package/dist/chunk-M5LX5AOO.js.map +1 -0
  107. package/dist/chunk-MZOVP3WI.cjs +96 -0
  108. package/dist/chunk-MZOVP3WI.cjs.map +1 -0
  109. package/dist/chunk-N5YFR4UP.cjs +10 -0
  110. package/dist/chunk-N5YFR4UP.cjs.map +1 -0
  111. package/dist/chunk-NGBBNL4K.cjs +4 -0
  112. package/dist/chunk-NGBBNL4K.cjs.map +1 -0
  113. package/dist/chunk-NH2O2AUR.js +146 -0
  114. package/dist/chunk-NH2O2AUR.js.map +1 -0
  115. package/dist/chunk-NLNDMWZC.js +31 -0
  116. package/dist/chunk-NLNDMWZC.js.map +1 -0
  117. package/dist/chunk-NMCRQP3Z.cjs +778 -0
  118. package/dist/chunk-NMCRQP3Z.cjs.map +1 -0
  119. package/dist/chunk-NMD5VRN4.cjs +1327 -0
  120. package/dist/chunk-NMD5VRN4.cjs.map +1 -0
  121. package/dist/chunk-OC6LTXYS.cjs +286 -0
  122. package/dist/chunk-OC6LTXYS.cjs.map +1 -0
  123. package/dist/chunk-OT6OJY7C.cjs +114 -0
  124. package/dist/chunk-OT6OJY7C.cjs.map +1 -0
  125. package/dist/chunk-PFSDGGYL.js +8 -0
  126. package/dist/chunk-PFSDGGYL.js.map +1 -0
  127. package/dist/chunk-QNJ4ACRT.cjs +155 -0
  128. package/dist/chunk-QNJ4ACRT.cjs.map +1 -0
  129. package/dist/chunk-QWY3VEZN.js +1637 -0
  130. package/dist/chunk-QWY3VEZN.js.map +1 -0
  131. package/dist/chunk-RFYD5TJE.js +111 -0
  132. package/dist/chunk-RFYD5TJE.js.map +1 -0
  133. package/dist/chunk-RIN643A3.js +354 -0
  134. package/dist/chunk-RIN643A3.js.map +1 -0
  135. package/dist/chunk-RZCWSXTA.cjs +5122 -0
  136. package/dist/chunk-RZCWSXTA.cjs.map +1 -0
  137. package/dist/chunk-SDGRK7EP.js +774 -0
  138. package/dist/chunk-SDGRK7EP.js.map +1 -0
  139. package/dist/chunk-VEKIWQ3F.cjs +39 -0
  140. package/dist/chunk-VEKIWQ3F.cjs.map +1 -0
  141. package/dist/chunk-WQTTOGXC.cjs +99 -0
  142. package/dist/chunk-WQTTOGXC.cjs.map +1 -0
  143. package/dist/chunk-X6K3HUOY.cjs +86 -0
  144. package/dist/chunk-X6K3HUOY.cjs.map +1 -0
  145. package/dist/chunk-XJCMXB2E.cjs +333 -0
  146. package/dist/chunk-XJCMXB2E.cjs.map +1 -0
  147. package/dist/chunk-XVWCOTR6.js +1324 -0
  148. package/dist/chunk-XVWCOTR6.js.map +1 -0
  149. package/dist/chunk-YLJ4XMA6.js +33 -0
  150. package/dist/chunk-YLJ4XMA6.js.map +1 -0
  151. package/dist/chunk-Z2XP767T.cjs +35 -0
  152. package/dist/chunk-Z2XP767T.cjs.map +1 -0
  153. package/dist/chunk-Z4X2RWOF.js +37 -0
  154. package/dist/chunk-Z4X2RWOF.js.map +1 -0
  155. package/dist/constants.cjs +22 -0
  156. package/dist/constants.cjs.map +1 -0
  157. package/dist/constants.d.cts +12 -0
  158. package/dist/constants.d.ts +12 -0
  159. package/dist/constants.js +5 -0
  160. package/dist/constants.js.map +1 -0
  161. package/dist/engine.cjs +79 -0
  162. package/dist/engine.cjs.map +1 -0
  163. package/dist/engine.d.cts +587 -0
  164. package/dist/engine.d.ts +587 -0
  165. package/dist/engine.js +34 -0
  166. package/dist/engine.js.map +1 -0
  167. package/dist/errors.cjs +81 -0
  168. package/dist/errors.cjs.map +1 -0
  169. package/dist/errors.d.cts +95 -0
  170. package/dist/errors.d.ts +95 -0
  171. package/dist/errors.js +4 -0
  172. package/dist/errors.js.map +1 -0
  173. package/dist/format.cjs +171 -0
  174. package/dist/format.cjs.map +1 -0
  175. package/dist/format.d.cts +51 -0
  176. package/dist/format.d.ts +51 -0
  177. package/dist/format.js +168 -0
  178. package/dist/format.js.map +1 -0
  179. package/dist/index.cjs +97 -0
  180. package/dist/index.cjs.map +1 -0
  181. package/dist/index.d.cts +152 -0
  182. package/dist/index.d.ts +152 -0
  183. package/dist/index.js +75 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/language.cjs +308 -0
  186. package/dist/language.cjs.map +1 -0
  187. package/dist/language.d.cts +110 -0
  188. package/dist/language.d.ts +110 -0
  189. package/dist/language.js +287 -0
  190. package/dist/language.js.map +1 -0
  191. package/dist/lexer.cjs +64 -0
  192. package/dist/lexer.cjs.map +1 -0
  193. package/dist/lexer.d.cts +56 -0
  194. package/dist/lexer.d.ts +56 -0
  195. package/dist/lexer.js +11 -0
  196. package/dist/lexer.js.map +1 -0
  197. package/dist/normalizer.cjs +40 -0
  198. package/dist/normalizer.cjs.map +1 -0
  199. package/dist/normalizer.d.cts +364 -0
  200. package/dist/normalizer.d.ts +364 -0
  201. package/dist/normalizer.js +11 -0
  202. package/dist/normalizer.js.map +1 -0
  203. package/dist/packages.cjs +121 -0
  204. package/dist/packages.cjs.map +1 -0
  205. package/dist/packages.d.cts +691 -0
  206. package/dist/packages.d.ts +691 -0
  207. package/dist/packages.js +24 -0
  208. package/dist/packages.js.map +1 -0
  209. package/dist/parser.cjs +55 -0
  210. package/dist/parser.cjs.map +1 -0
  211. package/dist/parser.d.cts +46 -0
  212. package/dist/parser.d.ts +46 -0
  213. package/dist/parser.js +10 -0
  214. package/dist/parser.js.map +1 -0
  215. package/dist/pipeline-CrsRPmsv.d.ts +285 -0
  216. package/dist/pipeline-DPUQt7yL.d.cts +285 -0
  217. package/dist/resolvers.cjs +13 -0
  218. package/dist/resolvers.cjs.map +1 -0
  219. package/dist/resolvers.d.cts +111 -0
  220. package/dist/resolvers.d.ts +111 -0
  221. package/dist/resolvers.js +4 -0
  222. package/dist/resolvers.js.map +1 -0
  223. package/dist/services.cjs +21 -0
  224. package/dist/services.cjs.map +1 -0
  225. package/dist/services.d.cts +30 -0
  226. package/dist/services.d.ts +30 -0
  227. package/dist/services.js +4 -0
  228. package/dist/services.js.map +1 -0
  229. package/dist/uom.cjs +56 -0
  230. package/dist/uom.cjs.map +1 -0
  231. package/dist/uom.d.cts +224 -0
  232. package/dist/uom.d.ts +224 -0
  233. package/dist/uom.js +11 -0
  234. package/dist/uom.js.map +1 -0
  235. package/dist/utilities.cjs +32 -0
  236. package/dist/utilities.cjs.map +1 -0
  237. package/dist/utilities.d.cts +113 -0
  238. package/dist/utilities.d.ts +113 -0
  239. package/dist/utilities.js +7 -0
  240. package/dist/utilities.js.map +1 -0
  241. package/dist/variables.cjs +17 -0
  242. package/dist/variables.cjs.map +1 -0
  243. package/dist/variables.d.cts +87 -0
  244. package/dist/variables.d.ts +87 -0
  245. package/dist/variables.js +4 -0
  246. package/dist/variables.js.map +1 -0
  247. package/dist/vm.cjs +284 -0
  248. package/dist/vm.cjs.map +1 -0
  249. package/dist/vm.d.cts +68 -0
  250. package/dist/vm.d.ts +68 -0
  251. package/dist/vm.js +194 -0
  252. package/dist/vm.js.map +1 -0
  253. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"uom.cjs"}
package/dist/uom.d.cts ADDED
@@ -0,0 +1,224 @@
1
+ import { QueryClient } from '@tanstack/query-core';
2
+ import { T as Token } from './Token-0jpvUdPY.cjs';
3
+ import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.cjs';
4
+ import { IAsyncResolver, AsyncCheckResult } from './resolvers.cjs';
5
+ import './Value-KtAQNHur.cjs';
6
+
7
+ /**
8
+ * Caches exchange rates fetched from an external source.
9
+ *
10
+ * Rates are global market data rather than per-engine configuration, which is
11
+ * why one instance is shared. Two engines with private copies would fetch the
12
+ * same endpoint twice and could disagree about one pair at one moment. See
13
+ * `engine/EngineContext.ts`.
14
+ */
15
+ declare class CurrencyExchangeService {
16
+ /**
17
+ * Live rate tables cached from successful getRate() fetches, keyed by
18
+ * uppercase base currency. Each table holds every rate the API returned
19
+ * for that base (plus the base itself at 1), so any pair whose two codes
20
+ * appear in one fresh table can be served synchronously, including
21
+ * cross pairs via triangulation (EUR→GBP through a USD-base table).
22
+ * Stale tables are ignored, not evicted; the next successful fetch for
23
+ * the same base overwrites them.
24
+ */
25
+ private baseTables;
26
+ /**
27
+ * How long a fetched rate may be served synchronously by getRateSync().
28
+ * Beyond this window callers fall through to the async path (expression
29
+ * shows Pending until the fetch lands).
30
+ */
31
+ private static readonly RATE_FRESHNESS_MS;
32
+ /**
33
+ * Ticker → CoinGecko coin id, for the cryptocurrencies `isCurrency()`
34
+ * recognizes. Frankfurter (the fiat rate source below) is ECB reference
35
+ * rates only and has no concept of BTC/ETH/etc, routing a crypto code
36
+ * through it as `base=BTC` fails outright, which is why crypto pairs
37
+ * previously never resolved (see CurrencyAsyncResolver/VM.ts's ADD
38
+ * handling for the two bugs that let that failure pass silently instead
39
+ * of surfacing as a real fetch).
40
+ */
41
+ private static readonly CRYPTO_IDS;
42
+ private isCryptoCode;
43
+ constructor();
44
+ /**
45
+ * Timeout (ms) for currency exchange rate fetches.
46
+ *
47
+ * If the frankfurter API doesn't respond within this window, the fetch
48
+ * is aborted, preventing indefinite "Pending" states in the playground
49
+ * and Obsidian plugin when the exchange rate API is unreachable.
50
+ */
51
+ private static readonly FETCH_TIMEOUT_MS;
52
+ /**
53
+ * Fetch the live exchange rate for converting 1 unit of `from` into `to`.
54
+ *
55
+ * Routes cryptocurrency codes (see {@link CRYPTO_IDS}) to CoinGecko and
56
+ * everything else to Frankfurter (ECB reference rates, fiat-only). On
57
+ * success, caches the whole returned rate table for `from` so subsequent
58
+ * lookups, including cross-pairs via triangulation, can be served
59
+ * synchronously by {@link getRateSync} within the freshness window.
60
+ *
61
+ * @throws If the currency code is unrecognized or the fetch fails/times out.
62
+ */
63
+ getRate(from: string, to: string, signal?: AbortSignal): Promise<number>;
64
+ /**
65
+ * Crypto rate fetch, routed through CoinGecko's no-auth simple-price
66
+ * endpoint instead of Frankfurter (fiat-only, has no BTC/ETH concept).
67
+ * Handles all three combinations, crypto→crypto, crypto→fiat
68
+ * fiat→crypto, via prices denominated in USD (or the target fiat
69
+ * directly, which CoinGecko's `vs_currencies` also accepts), then
70
+ * caches the result as a same-shaped base table so getRateSync /
71
+ * convertSync keep working unchanged for crypto pairs too.
72
+ */
73
+ private getCryptoRate;
74
+ private fetchCoinGeckoPrices;
75
+ /**
76
+ * Seed a base rate table without a network fetch.
77
+ *
78
+ * Intended for tests and for future user-provided offline rates
79
+ * production live data always comes from {@link getRate}. Seeded rates
80
+ * obey the same freshness window as fetched ones.
81
+ *
82
+ * @param base - Base currency code (e.g. "USD").
83
+ * @param rates - Map of currency code → rate relative to the base.
84
+ */
85
+ primeRates(base: string, rates: Record<string, number>): void;
86
+ /**
87
+ * Drop every cached/primed rate table.
88
+ *
89
+ * Mainly for test isolation: {@link sharedCurrencyExchange} is a
90
+ * module-level singleton, so a rate primed or fetched by one test can
91
+ * silently leak into a later test in the same file. Also usable in
92
+ * production if a caller ever wants to force a full re-fetch.
93
+ */
94
+ clearRates(): void;
95
+ /**
96
+ * Synchronous rate lookup: `1` for same-currency pairs, a cached LIVE
97
+ * rate if one was fetched within {@link RATE_FRESHNESS_MS}, otherwise
98
+ * `null`, callers fall through to the async fetch path and the
99
+ * expression shows Pending until real data arrives.
100
+ *
101
+ * There is deliberately no hardcoded fallback table: a stale made-up
102
+ * rate presented as a real conversion is worse than a Pending state.
103
+ */
104
+ getRateSync(from: string, to: string): number | null;
105
+ /** Convert `value` from `from` to `to` using a freshly-fetched live rate (see {@link getRate}). */
106
+ convert(value: number, from: string, to: string): Promise<number>;
107
+ /**
108
+ * Get all currently cached fresh rates, keyed "FROM:TO".
109
+ * @returns Snapshot of fresh live rates, or null when none are cached.
110
+ */
111
+ getAllRates(): Record<string, number> | null;
112
+ /**
113
+ * Check whether any fresh live rates are currently cached.
114
+ */
115
+ hasRates(): boolean;
116
+ /**
117
+ * Synchronous conversion using cached rates only
118
+ * Returns null if rate not in cache
119
+ */
120
+ convertSync(value: number, from: string, to: string): number | null;
121
+ /**
122
+ * Check whether `code` is a recognized currency code (fiat or the
123
+ * cryptocurrencies in {@link CRYPTO_IDS}), a fixed allowlist, not a
124
+ * live lookup against any API.
125
+ */
126
+ isCurrency(code: string): boolean;
127
+ }
128
+ /** The shared rate cache. See {@link CurrencyExchangeService} for why it is shared. */
129
+ declare const currencyExchangeService: CurrencyExchangeService;
130
+ /** Alias for {@link currencyExchangeService}, kept for older imports. */
131
+ declare const sharedCurrencyExchange: CurrencyExchangeService;
132
+
133
+ /**
134
+ * Currency async resolver, bridges CurrencyExchangeService to the
135
+ * IAsyncResolver interface for the Suspense architecture.
136
+ *
137
+ * Uses TanStack Query (injected via queryClient) as the single cache layer.
138
+ */
139
+
140
+ /**
141
+ * Fetches exchange rates before the VM runs, so a conversion has real numbers.
142
+ *
143
+ * Until rates arrive the line evaluates to a pending value rather than a
144
+ * guessed one, and re-evaluates when they land.
145
+ */
146
+ declare class CurrencyAsyncResolver implements IAsyncResolver {
147
+ readonly namespace = "currency";
148
+ private exchange;
149
+ constructor(exchange?: CurrencyExchangeService);
150
+ preflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null;
151
+ destroy(): void;
152
+ }
153
+
154
+ /**
155
+ * Validate `unit` against the known unit table.
156
+ *
157
+ * @returns `unit` unchanged in all cases. This does NOT normalize casing
158
+ * or aliasing (units are strictly case-sensitive, see the module note
159
+ * above). A unit the table doesn't recognize is still
160
+ * returned as-is (not thrown), so callers must not assume a returned
161
+ * string is actually convertible, check with {@link isConvertibleUnit}
162
+ * or {@link canConvert} first if that matters.
163
+ *
164
+ * Kept as an identity function purely for API compatibility. It used to guard
165
+ * a validity cache, which existed because validating a unit meant a
166
+ * throw/catch round trip through the old dependency. Validation is now a Map
167
+ * lookup, so the cache cost more than it saved: worse, it was capped at 1000
168
+ * entries against a 1456-unit table, so any sweep over the full vocabulary
169
+ * (which is exactly what LanguageService does to build completions) evicted
170
+ * on almost every call. That one change took the full-table sweep from 7.7ms
171
+ * to under 20us.
172
+ */
173
+ declare function resolveUnit(unit: string): string;
174
+ /**
175
+ * Get the measure/dimension kind for `unit` (e.g. `"length"`, `"mass"`,
176
+ * `"temperature"`), used to check whether two units are even in the same
177
+ * dimension before attempting a conversion.
178
+ *
179
+ * @returns `undefined` if `unit` isn't recognized, rather than throwing.
180
+ */
181
+ declare function getMeasure(unit: string): string | undefined;
182
+ /**
183
+ * Check whether `from` can be converted to `to`. Same unit, or same
184
+ * measure kind (length, mass, ...) and the underlying tables accept the pair.
185
+ * Never throws; returns `false` on any failure.
186
+ */
187
+ declare function canConvert(from: string, to: string): boolean;
188
+ /**
189
+ * Convert `value` from unit `from` to unit `to`.
190
+ *
191
+ * Does not validate that the conversion is possible, callers should check
192
+ * with {@link canConvert} first if `from`/`to` aren't already known-good.
193
+ *
194
+ * THROWS a RangeError for an unknown unit or a cross-measure pair. `VM.ts`'s
195
+ * `extractDurationMs()` depends on that, see {@link convertRaw}.
196
+ *
197
+ * This used to memoize a per-pair conversion factor in an LFU cache. The cache
198
+ * is gone: computing the factor is now two Map reads, while the cache cost a
199
+ * template-string key allocation on every call plus the LFU's own frequency
200
+ * bookkeeping, so it was slower than the work it avoided. Removing it is
201
+ * bit-exact, not merely close: the cache stored `convertRaw(1, f, t)`, which is
202
+ * exactly `fromRatio / toRatio`, and then multiplied, which is the identical
203
+ * expression `convertRaw(value, f, t)` evaluates. It also deleted the special
204
+ * case that existed only to keep offset-based temperature pairs out of a
205
+ * factor cache.
206
+ */
207
+ declare function convertUnit(value: number, from: string, to: string): number;
208
+ /** Check whether `unit` is a unit the conversion tables recognize. Never throws. */
209
+ declare function isConvertibleUnit(unit: string): boolean;
210
+ /**
211
+ * Convert `value` (in `unit`) to whichever unit of the same measure gives
212
+ * the most human-readable magnitude, e.g. 1500 metres becomes 1.5 km. Falls
213
+ * back to returning `value`/`unit` unchanged if `unit` isn't recognized,
214
+ * which is what every extended unit and workday does.
215
+ *
216
+ * Note the chosen unit is drawn from the best-unit lists, which are not
217
+ * restricted to spellings the lexer accepts: 0.5 l reports "mL".
218
+ */
219
+ declare function getBestUnit(value: number, unit: string): {
220
+ value: number;
221
+ unit: string;
222
+ };
223
+
224
+ export { CurrencyAsyncResolver, CurrencyExchangeService, canConvert, convertUnit, currencyExchangeService, getBestUnit, getMeasure, isConvertibleUnit, resolveUnit, sharedCurrencyExchange };
package/dist/uom.d.ts ADDED
@@ -0,0 +1,224 @@
1
+ import { QueryClient } from '@tanstack/query-core';
2
+ import { T as Token } from './Token-0jpvUdPY.js';
3
+ import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.js';
4
+ import { IAsyncResolver, AsyncCheckResult } from './resolvers.js';
5
+ import './Value-KtAQNHur.js';
6
+
7
+ /**
8
+ * Caches exchange rates fetched from an external source.
9
+ *
10
+ * Rates are global market data rather than per-engine configuration, which is
11
+ * why one instance is shared. Two engines with private copies would fetch the
12
+ * same endpoint twice and could disagree about one pair at one moment. See
13
+ * `engine/EngineContext.ts`.
14
+ */
15
+ declare class CurrencyExchangeService {
16
+ /**
17
+ * Live rate tables cached from successful getRate() fetches, keyed by
18
+ * uppercase base currency. Each table holds every rate the API returned
19
+ * for that base (plus the base itself at 1), so any pair whose two codes
20
+ * appear in one fresh table can be served synchronously, including
21
+ * cross pairs via triangulation (EUR→GBP through a USD-base table).
22
+ * Stale tables are ignored, not evicted; the next successful fetch for
23
+ * the same base overwrites them.
24
+ */
25
+ private baseTables;
26
+ /**
27
+ * How long a fetched rate may be served synchronously by getRateSync().
28
+ * Beyond this window callers fall through to the async path (expression
29
+ * shows Pending until the fetch lands).
30
+ */
31
+ private static readonly RATE_FRESHNESS_MS;
32
+ /**
33
+ * Ticker → CoinGecko coin id, for the cryptocurrencies `isCurrency()`
34
+ * recognizes. Frankfurter (the fiat rate source below) is ECB reference
35
+ * rates only and has no concept of BTC/ETH/etc, routing a crypto code
36
+ * through it as `base=BTC` fails outright, which is why crypto pairs
37
+ * previously never resolved (see CurrencyAsyncResolver/VM.ts's ADD
38
+ * handling for the two bugs that let that failure pass silently instead
39
+ * of surfacing as a real fetch).
40
+ */
41
+ private static readonly CRYPTO_IDS;
42
+ private isCryptoCode;
43
+ constructor();
44
+ /**
45
+ * Timeout (ms) for currency exchange rate fetches.
46
+ *
47
+ * If the frankfurter API doesn't respond within this window, the fetch
48
+ * is aborted, preventing indefinite "Pending" states in the playground
49
+ * and Obsidian plugin when the exchange rate API is unreachable.
50
+ */
51
+ private static readonly FETCH_TIMEOUT_MS;
52
+ /**
53
+ * Fetch the live exchange rate for converting 1 unit of `from` into `to`.
54
+ *
55
+ * Routes cryptocurrency codes (see {@link CRYPTO_IDS}) to CoinGecko and
56
+ * everything else to Frankfurter (ECB reference rates, fiat-only). On
57
+ * success, caches the whole returned rate table for `from` so subsequent
58
+ * lookups, including cross-pairs via triangulation, can be served
59
+ * synchronously by {@link getRateSync} within the freshness window.
60
+ *
61
+ * @throws If the currency code is unrecognized or the fetch fails/times out.
62
+ */
63
+ getRate(from: string, to: string, signal?: AbortSignal): Promise<number>;
64
+ /**
65
+ * Crypto rate fetch, routed through CoinGecko's no-auth simple-price
66
+ * endpoint instead of Frankfurter (fiat-only, has no BTC/ETH concept).
67
+ * Handles all three combinations, crypto→crypto, crypto→fiat
68
+ * fiat→crypto, via prices denominated in USD (or the target fiat
69
+ * directly, which CoinGecko's `vs_currencies` also accepts), then
70
+ * caches the result as a same-shaped base table so getRateSync /
71
+ * convertSync keep working unchanged for crypto pairs too.
72
+ */
73
+ private getCryptoRate;
74
+ private fetchCoinGeckoPrices;
75
+ /**
76
+ * Seed a base rate table without a network fetch.
77
+ *
78
+ * Intended for tests and for future user-provided offline rates
79
+ * production live data always comes from {@link getRate}. Seeded rates
80
+ * obey the same freshness window as fetched ones.
81
+ *
82
+ * @param base - Base currency code (e.g. "USD").
83
+ * @param rates - Map of currency code → rate relative to the base.
84
+ */
85
+ primeRates(base: string, rates: Record<string, number>): void;
86
+ /**
87
+ * Drop every cached/primed rate table.
88
+ *
89
+ * Mainly for test isolation: {@link sharedCurrencyExchange} is a
90
+ * module-level singleton, so a rate primed or fetched by one test can
91
+ * silently leak into a later test in the same file. Also usable in
92
+ * production if a caller ever wants to force a full re-fetch.
93
+ */
94
+ clearRates(): void;
95
+ /**
96
+ * Synchronous rate lookup: `1` for same-currency pairs, a cached LIVE
97
+ * rate if one was fetched within {@link RATE_FRESHNESS_MS}, otherwise
98
+ * `null`, callers fall through to the async fetch path and the
99
+ * expression shows Pending until real data arrives.
100
+ *
101
+ * There is deliberately no hardcoded fallback table: a stale made-up
102
+ * rate presented as a real conversion is worse than a Pending state.
103
+ */
104
+ getRateSync(from: string, to: string): number | null;
105
+ /** Convert `value` from `from` to `to` using a freshly-fetched live rate (see {@link getRate}). */
106
+ convert(value: number, from: string, to: string): Promise<number>;
107
+ /**
108
+ * Get all currently cached fresh rates, keyed "FROM:TO".
109
+ * @returns Snapshot of fresh live rates, or null when none are cached.
110
+ */
111
+ getAllRates(): Record<string, number> | null;
112
+ /**
113
+ * Check whether any fresh live rates are currently cached.
114
+ */
115
+ hasRates(): boolean;
116
+ /**
117
+ * Synchronous conversion using cached rates only
118
+ * Returns null if rate not in cache
119
+ */
120
+ convertSync(value: number, from: string, to: string): number | null;
121
+ /**
122
+ * Check whether `code` is a recognized currency code (fiat or the
123
+ * cryptocurrencies in {@link CRYPTO_IDS}), a fixed allowlist, not a
124
+ * live lookup against any API.
125
+ */
126
+ isCurrency(code: string): boolean;
127
+ }
128
+ /** The shared rate cache. See {@link CurrencyExchangeService} for why it is shared. */
129
+ declare const currencyExchangeService: CurrencyExchangeService;
130
+ /** Alias for {@link currencyExchangeService}, kept for older imports. */
131
+ declare const sharedCurrencyExchange: CurrencyExchangeService;
132
+
133
+ /**
134
+ * Currency async resolver, bridges CurrencyExchangeService to the
135
+ * IAsyncResolver interface for the Suspense architecture.
136
+ *
137
+ * Uses TanStack Query (injected via queryClient) as the single cache layer.
138
+ */
139
+
140
+ /**
141
+ * Fetches exchange rates before the VM runs, so a conversion has real numbers.
142
+ *
143
+ * Until rates arrive the line evaluates to a pending value rather than a
144
+ * guessed one, and re-evaluates when they land.
145
+ */
146
+ declare class CurrencyAsyncResolver implements IAsyncResolver {
147
+ readonly namespace = "currency";
148
+ private exchange;
149
+ constructor(exchange?: CurrencyExchangeService);
150
+ preflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null;
151
+ destroy(): void;
152
+ }
153
+
154
+ /**
155
+ * Validate `unit` against the known unit table.
156
+ *
157
+ * @returns `unit` unchanged in all cases. This does NOT normalize casing
158
+ * or aliasing (units are strictly case-sensitive, see the module note
159
+ * above). A unit the table doesn't recognize is still
160
+ * returned as-is (not thrown), so callers must not assume a returned
161
+ * string is actually convertible, check with {@link isConvertibleUnit}
162
+ * or {@link canConvert} first if that matters.
163
+ *
164
+ * Kept as an identity function purely for API compatibility. It used to guard
165
+ * a validity cache, which existed because validating a unit meant a
166
+ * throw/catch round trip through the old dependency. Validation is now a Map
167
+ * lookup, so the cache cost more than it saved: worse, it was capped at 1000
168
+ * entries against a 1456-unit table, so any sweep over the full vocabulary
169
+ * (which is exactly what LanguageService does to build completions) evicted
170
+ * on almost every call. That one change took the full-table sweep from 7.7ms
171
+ * to under 20us.
172
+ */
173
+ declare function resolveUnit(unit: string): string;
174
+ /**
175
+ * Get the measure/dimension kind for `unit` (e.g. `"length"`, `"mass"`,
176
+ * `"temperature"`), used to check whether two units are even in the same
177
+ * dimension before attempting a conversion.
178
+ *
179
+ * @returns `undefined` if `unit` isn't recognized, rather than throwing.
180
+ */
181
+ declare function getMeasure(unit: string): string | undefined;
182
+ /**
183
+ * Check whether `from` can be converted to `to`. Same unit, or same
184
+ * measure kind (length, mass, ...) and the underlying tables accept the pair.
185
+ * Never throws; returns `false` on any failure.
186
+ */
187
+ declare function canConvert(from: string, to: string): boolean;
188
+ /**
189
+ * Convert `value` from unit `from` to unit `to`.
190
+ *
191
+ * Does not validate that the conversion is possible, callers should check
192
+ * with {@link canConvert} first if `from`/`to` aren't already known-good.
193
+ *
194
+ * THROWS a RangeError for an unknown unit or a cross-measure pair. `VM.ts`'s
195
+ * `extractDurationMs()` depends on that, see {@link convertRaw}.
196
+ *
197
+ * This used to memoize a per-pair conversion factor in an LFU cache. The cache
198
+ * is gone: computing the factor is now two Map reads, while the cache cost a
199
+ * template-string key allocation on every call plus the LFU's own frequency
200
+ * bookkeeping, so it was slower than the work it avoided. Removing it is
201
+ * bit-exact, not merely close: the cache stored `convertRaw(1, f, t)`, which is
202
+ * exactly `fromRatio / toRatio`, and then multiplied, which is the identical
203
+ * expression `convertRaw(value, f, t)` evaluates. It also deleted the special
204
+ * case that existed only to keep offset-based temperature pairs out of a
205
+ * factor cache.
206
+ */
207
+ declare function convertUnit(value: number, from: string, to: string): number;
208
+ /** Check whether `unit` is a unit the conversion tables recognize. Never throws. */
209
+ declare function isConvertibleUnit(unit: string): boolean;
210
+ /**
211
+ * Convert `value` (in `unit`) to whichever unit of the same measure gives
212
+ * the most human-readable magnitude, e.g. 1500 metres becomes 1.5 km. Falls
213
+ * back to returning `value`/`unit` unchanged if `unit` isn't recognized,
214
+ * which is what every extended unit and workday does.
215
+ *
216
+ * Note the chosen unit is drawn from the best-unit lists, which are not
217
+ * restricted to spellings the lexer accepts: 0.5 l reports "mL".
218
+ */
219
+ declare function getBestUnit(value: number, unit: string): {
220
+ value: number;
221
+ unit: string;
222
+ };
223
+
224
+ export { CurrencyAsyncResolver, CurrencyExchangeService, canConvert, convertUnit, currencyExchangeService, getBestUnit, getMeasure, isConvertibleUnit, resolveUnit, sharedCurrencyExchange };
package/dist/uom.js ADDED
@@ -0,0 +1,11 @@
1
+ export { CurrencyAsyncResolver } from './chunk-EPOXXJBK.js';
2
+ export { CurrencyExchangeService, currencyExchangeService, sharedCurrencyExchange } from './chunk-DM3LMRBC.js';
3
+ import './chunk-75JP4BZX.js';
4
+ import './chunk-Z4X2RWOF.js';
5
+ import './chunk-BVAR5J2F.js';
6
+ export { canConvert, convertUnit, getBestUnit, getMeasure, isConvertibleUnit, resolveUnit } from './chunk-NH2O2AUR.js';
7
+ import './chunk-4MG4XKO2.js';
8
+ import './chunk-6RDSQURE.js';
9
+ import './chunk-YLJ4XMA6.js';
10
+ //# sourceMappingURL=uom.js.map
11
+ //# sourceMappingURL=uom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"uom.js"}
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ var chunk5X2PTP6F_cjs = require('./chunk-5X2PTP6F.cjs');
4
+ var chunkCCJPSHGI_cjs = require('./chunk-CCJPSHGI.cjs');
5
+ var chunkN5YFR4UP_cjs = require('./chunk-N5YFR4UP.cjs');
6
+ var chunkVEKIWQ3F_cjs = require('./chunk-VEKIWQ3F.cjs');
7
+ require('./chunk-B7LXJ6LC.cjs');
8
+
9
+
10
+
11
+ Object.defineProperty(exports, "abortLogger", {
12
+ enumerable: true,
13
+ get: function () { return chunk5X2PTP6F_cjs.abortLogger; }
14
+ });
15
+ Object.defineProperty(exports, "djb2Hash", {
16
+ enumerable: true,
17
+ get: function () { return chunk5X2PTP6F_cjs.djb2Hash; }
18
+ });
19
+ Object.defineProperty(exports, "autoFormatIntegerOrFloat", {
20
+ enumerable: true,
21
+ get: function () { return chunkCCJPSHGI_cjs.autoFormatIntegerOrFloat; }
22
+ });
23
+ Object.defineProperty(exports, "stripQuotes", {
24
+ enumerable: true,
25
+ get: function () { return chunkN5YFR4UP_cjs.stripQuotes; }
26
+ });
27
+ Object.defineProperty(exports, "createTimeoutSignal", {
28
+ enumerable: true,
29
+ get: function () { return chunkVEKIWQ3F_cjs.createTimeoutSignal; }
30
+ });
31
+ //# sourceMappingURL=utilities.cjs.map
32
+ //# sourceMappingURL=utilities.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"utilities.cjs"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Fast, non-cryptographic string hashing utilities.
3
+ *
4
+ * djb2 is chosen for its speed, simplicity, and excellent distribution
5
+ * for short strings (typical line lengths in markdown documents).
6
+ * It produces a 32-bit unsigned integer hash.
7
+ */
8
+ /**
9
+ * djb2 string hash, fast, simple, good distribution.
10
+ * Used for O(1) line text change detection in DocumentModel.
11
+ */
12
+ declare function djb2Hash(str: string): number;
13
+
14
+ /**
15
+ * Format `number` for display, branching on whether it's a whole number:
16
+ * integers are always rendered with zero decimal places (never padded to
17
+ * `decimalPlaces`), while non-integers are rendered with up to
18
+ * `decimalPlaces` fractional digits. `includeThousandSeparators` controls
19
+ * whether groups are separated (e.g. `"1,234"`) per `numberLocale`.
20
+ *
21
+ * @param number - The value to format.
22
+ * @param decimalPlaces - Max fractional digits for non-integer values (default 2).
23
+ * @param includeThousandSeparators - Whether to group digits (default false).
24
+ * @param numberLocale - `Intl`/`toLocaleString` locale to format with (default "en-US").
25
+ */
26
+ declare function autoFormatIntegerOrFloat(number: number, decimalPlaces?: number, includeThousandSeparators?: boolean, numberLocale?: string): string;
27
+
28
+ /**
29
+ * Strips a single layer of matching double quotes from a string, if present.
30
+ * Returns the input unchanged if it isn't fully wrapped in quotes.
31
+ *
32
+ * Used for STRING token values, which the lexer emits with their surrounding
33
+ * `"..."` quotes still attached.
34
+ */
35
+ declare function stripQuotes(value: string): string;
36
+
37
+ /**
38
+ * Multiplex an optional caller AbortSignal with a hard timeout into a single
39
+ * AbortSignal suitable for fetch().
40
+ *
41
+ * Implemented manually rather than with AbortSignal.any()/AbortSignal.timeout()
42
+ * (Chrome 116+) to stay compatible with the TypeScript lib targets used by
43
+ * this project.
44
+ *
45
+ * Handles the already-aborted caller: addEventListener("abort", …) on a signal
46
+ * that has already fired never invokes the listener, so without the upfront
47
+ * `aborted` check the fetch would proceed even though the caller cancelled.
48
+ */
49
+ declare function createTimeoutSignal(callerSignal: AbortSignal | undefined, timeoutMs: number, label: string): {
50
+ signal: AbortSignal;
51
+ cleanup: () => void;
52
+ };
53
+
54
+ /**
55
+ * Records abort-signal lifecycle for debugging cancellation.
56
+ *
57
+ * Keystroke cancellation is hard to reason about after the fact, because the
58
+ * evidence is gone by the time anything looks wrong. This keeps it.
59
+ */
60
+ declare const abortLogger: {
61
+ /** Whether debug logging is currently active. */
62
+ readonly enabled: boolean;
63
+ /**
64
+ * Log creation of the keystroke-level AbortController.
65
+ * Called in the plugin constructor and on each new keystroke.
66
+ */
67
+ keystrokeCreated(): void;
68
+ /**
69
+ * Log abortion of the keystroke-level AbortController.
70
+ * @param reason Why the keystroke was aborted (e.g. "New keystroke",
71
+ * "Document switch", "Plugin destroyed").
72
+ */
73
+ keystrokeAborted(reason: string): void;
74
+ /**
75
+ * Log creation of a local AbortController that is linked to the
76
+ * keystroke signal.
77
+ * @param source Which code path created the controller
78
+ * (e.g. "executeAndStore", "executeRaw", "preflight", "vm").
79
+ */
80
+ localControllerCreated(source: string): void;
81
+ /**
82
+ * Log that a local AbortController was linked to the keystroke signal.
83
+ * When the keystroke signal is aborted, this local controller will
84
+ * be aborted automatically.
85
+ * @param source The code path that created the controller.
86
+ */
87
+ signalLinked(source: string): void;
88
+ /**
89
+ * Log that a local AbortController's listener was removed from the
90
+ * keystroke signal (cleanup).
91
+ * @param source The code path.
92
+ */
93
+ signalUnlinked(source: string): void;
94
+ /**
95
+ * Log that the keystroke signal was propagated INTO the engine.
96
+ * @param isAborted Whether the signal was already aborted when set.
97
+ */
98
+ keystrokeSignalSet(isAborted: boolean): void;
99
+ /**
100
+ * Log that the keystroke signal was CLEARED from the engine
101
+ * (typically in the evaluator's finally block).
102
+ */
103
+ keystrokeSignalCleared(): void;
104
+ /**
105
+ * Log that a stale async result was discarded because its signal
106
+ * was aborted.
107
+ * @param queryKey The cache key for the discarded result.
108
+ * @param context Additional context (e.g. "after await", "after error").
109
+ */
110
+ staleDataDiscarded(queryKey: string, context: string): void;
111
+ };
112
+
113
+ export { abortLogger, autoFormatIntegerOrFloat, createTimeoutSignal, djb2Hash, stripQuotes };