gloomberb 0.11.2 → 0.12.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 (531) hide show
  1. package/README.md +7 -4
  2. package/README.zh-CN.md +4 -2
  3. package/package.json +28 -1
  4. package/src/api-client/auth.ts +10 -0
  5. package/src/api-client/data.ts +108 -1
  6. package/src/api-client/index.test.ts +127 -0
  7. package/src/api-client/index.ts +134 -1
  8. package/src/api-client/normalizers.ts +39 -0
  9. package/src/api-client/paths.ts +85 -1
  10. package/src/api-client/types.ts +220 -0
  11. package/src/app/pane-runtime/index.tsx +15 -12
  12. package/src/app/pane-runtime/layout-placement.test.ts +27 -0
  13. package/src/app/pane-runtime/layout-placement.ts +13 -0
  14. package/src/app/pane-runtime/plugin-bindings.ts +62 -0
  15. package/src/app.tsx +60 -18
  16. package/src/architecture/browser-entry-graph.test.ts +96 -0
  17. package/src/brokers/profile-form.test.ts +25 -27
  18. package/src/brokers/test-broker.ts +68 -0
  19. package/src/capabilities/chart-series.ts +3 -2
  20. package/src/cli/commands/market.ts +2 -2
  21. package/src/cli/commands/plugins.ts +39 -11
  22. package/src/cli/desktop-pane-shot.ts +285 -16
  23. package/src/cli/index.ts +1 -1
  24. package/src/cli/pane-functions/capabilities.ts +61 -31
  25. package/src/cli/pane-functions/catalog.ts +16 -4
  26. package/src/cli/pane-functions/discovery.ts +1 -0
  27. package/src/cli/pane-functions/headless.test.ts +247 -0
  28. package/src/cli/pane-functions/headless.ts +423 -0
  29. package/src/cli/pane-functions/index.test.ts +9 -0
  30. package/src/cli/pane-functions/index.ts +6 -2
  31. package/src/cli/pane-functions/options.ts +27 -2
  32. package/src/cli/pane-functions/report.ts +4 -0
  33. package/src/cli/pane-functions/resolver.ts +26 -8
  34. package/src/cli/pane-functions/screenshot.test.ts +76 -0
  35. package/src/cli/pane-functions/screenshot.ts +236 -20
  36. package/src/cli/registry.ts +0 -22
  37. package/src/cli/restore-plugins.ts +34 -0
  38. package/src/cli/result.ts +7 -10
  39. package/src/components/chart/{static/chart → composite}/axis-overlays.test.tsx +3 -3
  40. package/src/components/chart/{static/chart → composite}/axis-overlays.tsx +6 -11
  41. package/src/components/chart/{static/chart → composite}/bitmap.ts +17 -3
  42. package/src/components/chart/composite/composite-chart.test.tsx +68 -20
  43. package/src/components/chart/composite/composite-chart.tsx +301 -204
  44. package/src/components/chart/composite/format.ts +8 -2
  45. package/src/components/chart/composite/interactions.test.ts +68 -102
  46. package/src/components/chart/composite/interactions.ts +214 -264
  47. package/src/components/chart/composite/price-axis-labels.test.ts +21 -0
  48. package/src/components/chart/{price-axis-labels.tsx → composite/price-axis-labels.tsx} +9 -4
  49. package/src/components/chart/composite/scene.ts +57 -3
  50. package/src/components/chart/composite/text-renderer.ts +3 -2
  51. package/src/components/chart/composite/time-scale.ts +138 -57
  52. package/src/components/chart/composite/types.ts +25 -1
  53. package/src/components/chart/core/data.ts +9 -13
  54. package/src/components/chart/core/date-window.ts +7 -1
  55. package/src/components/chart/core/pointer.ts +3 -0
  56. package/src/components/chart/core/types.ts +0 -45
  57. package/src/components/chart/native/chart-rasterizer.ts +0 -1
  58. package/src/components/chart/native/kitty/index.test.ts +0 -188
  59. package/src/components/chart/native/raster/crosshair.ts +6 -5
  60. package/src/components/chart/native/raster/primitives.ts +0 -23
  61. package/src/components/chart/native/renderer-selection.ts +81 -31
  62. package/src/components/chart/static/{chart/surface.test.tsx → chart-surface.test.tsx} +28 -80
  63. package/src/components/chart/static/chart-surface.tsx +150 -0
  64. package/src/components/chart/static/index.ts +8 -0
  65. package/src/components/chart/static/multi-line-chart-surface.tsx +51 -166
  66. package/src/components/chart/static/scatter-chart-surface.test.ts +30 -0
  67. package/src/components/chart/static/scatter-chart-surface.tsx +135 -34
  68. package/src/components/chart/static/series.ts +49 -0
  69. package/src/components/command-bar/action-runtime.ts +1 -3
  70. package/src/components/command-bar/assist/model.test.ts +17 -2
  71. package/src/components/command-bar/assist/model.ts +40 -9
  72. package/src/components/command-bar/commands/direct/index.ts +1 -1
  73. package/src/components/command-bar/commands/direct/runtime.ts +1 -1
  74. package/src/components/command-bar/commands/registry.ts +0 -11
  75. package/src/components/command-bar/helpers.test.ts +2 -2
  76. package/src/components/command-bar/helpers.ts +2 -6
  77. package/src/components/command-bar/keyboard-shortcuts.ts +0 -11
  78. package/src/components/command-bar/list/badge.test.ts +54 -0
  79. package/src/components/command-bar/list/badge.ts +62 -0
  80. package/src/components/command-bar/list/model.test.ts +103 -0
  81. package/src/components/command-bar/list/model.ts +61 -4
  82. package/src/components/command-bar/list/view.test.tsx +113 -0
  83. package/src/components/command-bar/list/view.tsx +147 -131
  84. package/src/components/command-bar/pane-templates/workflow.ts +1 -1
  85. package/src/components/command-bar/panel/body.tsx +51 -65
  86. package/src/components/command-bar/panel/index.tsx +48 -13
  87. package/src/components/command-bar/panel/layout.test.ts +139 -0
  88. package/src/components/command-bar/panel/layout.ts +65 -28
  89. package/src/components/command-bar/panel/native-surface.ts +24 -0
  90. package/src/components/command-bar/panel/prompt-binding.ts +54 -0
  91. package/src/components/command-bar/panel/runtime.ts +6 -3
  92. package/src/components/command-bar/panel/state.ts +41 -7
  93. package/src/components/command-bar/panel/types.ts +7 -1
  94. package/src/components/command-bar/routes/root/provider-search.ts +34 -15
  95. package/src/components/command-bar/routes/root/results.test.ts +161 -0
  96. package/src/components/command-bar/routes/root/results.ts +30 -28
  97. package/src/components/command-bar/routes/root/runtime.ts +37 -20
  98. package/src/components/command-bar/routes/root/search-providers.test.tsx +224 -0
  99. package/src/components/command-bar/routes/root/search-providers.ts +205 -0
  100. package/src/components/command-bar/routes/root/selection.ts +1 -12
  101. package/src/components/command-bar/routes/root/shortcuts.test.ts +8 -8
  102. package/src/components/command-bar/routes/ticker-search/actions.ts +10 -9
  103. package/src/components/command-bar/routes/ticker-search/results.test.ts +54 -1
  104. package/src/components/command-bar/routes/ticker-search/results.ts +60 -19
  105. package/src/components/command-bar/routes/ticker-search/route.ts +1 -0
  106. package/src/components/command-bar/routing/actions.ts +1 -81
  107. package/src/components/command-bar/routing/launch-request.ts +1 -1
  108. package/src/components/command-bar/routing/list-state.ts +6 -21
  109. package/src/components/command-bar/selection-runtime.ts +1 -1
  110. package/src/components/command-bar/surface/assist.test.tsx +14 -10
  111. package/src/components/command-bar/surface/environment.ts +8 -1
  112. package/src/components/command-bar/surface/index.test.tsx +84 -68
  113. package/src/components/command-bar/surface/index.tsx +33 -36
  114. package/src/components/command-bar/surface/test-harness.tsx +15 -3
  115. package/src/components/command-bar/theme-picker.tsx +43 -15
  116. package/src/components/command-bar/view-model.test.ts +53 -8
  117. package/src/components/command-bar/view-model.ts +43 -14
  118. package/src/components/command-bar/workflow/tickers.ts +1 -0
  119. package/src/components/command-bar/workflow/types.ts +1 -1
  120. package/src/components/data-table/export.test.ts +21 -0
  121. package/src/components/data-table/export.ts +21 -0
  122. package/src/components/data-table/view.test.tsx +45 -6
  123. package/src/components/data-table/view.tsx +55 -9
  124. package/src/components/index.ts +10 -2
  125. package/src/components/input-search-bar.test.tsx +36 -2
  126. package/src/components/input-search-bar.tsx +18 -1
  127. package/src/components/layout/header.test.tsx +57 -10
  128. package/src/components/layout/header.tsx +292 -149
  129. package/src/components/layout/market-summary.test.ts +81 -0
  130. package/src/components/layout/market-summary.ts +109 -0
  131. package/src/components/layout/shell/chrome.ts +96 -1
  132. package/src/components/layout/shell/index.tsx +11 -3
  133. package/src/components/layout/shell/menu.ts +9 -0
  134. package/src/components/layout/shell/pane/actions.ts +29 -0
  135. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  136. package/src/components/layout/shell/shortcuts.ts +3 -0
  137. package/src/components/layout/status-bar.test.tsx +9 -8
  138. package/src/components/layout/status-bar.tsx +85 -54
  139. package/src/components/onboarding/onboarding-frame.tsx +2 -26
  140. package/src/components/price-sparkline/index.ts +61 -34
  141. package/src/components/price-sparkline/view.tsx +1 -1
  142. package/src/components/sign-in-gate.test.tsx +128 -0
  143. package/src/components/sign-in-gate.tsx +149 -0
  144. package/src/components/speedometer-gauge/desktop.tsx +2 -12
  145. package/src/components/ticker/badge/list.tsx +17 -3
  146. package/src/components/ticker/list-table-view.tsx +6 -3
  147. package/src/components/ui/data-table/index.tsx +22 -4
  148. package/src/components/ui/data-table/opentui/index.tsx +165 -120
  149. package/src/components/ui/frame.tsx +28 -0
  150. package/src/components/ui/index.ts +3 -0
  151. package/src/components/ui/native-select.tsx +20 -10
  152. package/src/components/ui/select-button.tsx +138 -0
  153. package/src/components/ui/status.tsx +2 -2
  154. package/src/components/ui/table-layout.ts +1 -1
  155. package/src/components/use-double-click-activation.ts +7 -3
  156. package/src/core/app-services.ts +3 -3
  157. package/src/data/config/chart-settings.ts +4 -4
  158. package/src/data/config/layout.ts +12 -6
  159. package/src/data/config/store/index.test.ts +97 -0
  160. package/src/data/config/store/migrations.ts +41 -0
  161. package/src/data/config/store/normalize.ts +5 -3
  162. package/src/i18n/es.ts +6 -2
  163. package/src/i18n/ja.ts +6 -2
  164. package/src/i18n/ko.ts +6 -2
  165. package/src/i18n/zh-cn.ts +6 -2
  166. package/src/i18n/zh-tw.ts +6 -2
  167. package/src/layout-marketplace/gallery-terminal.tsx +126 -96
  168. package/src/layout-marketplace/gallery.test.tsx +65 -1
  169. package/src/layout-marketplace/pane-imagery.ts +1 -0
  170. package/src/layout-marketplace/payload.test.ts +17 -0
  171. package/src/layout-marketplace/payload.ts +40 -5
  172. package/src/market-data/coordinator/index.ts +3 -2
  173. package/src/market-data/coordinator/quotes.ts +173 -66
  174. package/src/market-data/coordinator/subscriptions.test.ts +215 -37
  175. package/src/pane-settings.ts +1 -1
  176. package/src/plugins/builtin/analytics/pane-model.ts +1 -1
  177. package/src/plugins/builtin/analytics/view.tsx +1 -1
  178. package/src/plugins/builtin/broker-manager/index.test.tsx +3 -2
  179. package/src/plugins/builtin/broker-manager/model.test.ts +2 -2
  180. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +16 -2
  181. package/src/plugins/builtin/chart-composer/cli-options.ts +12 -9
  182. package/src/plugins/builtin/chart-composer/pane.tsx +22 -8
  183. package/src/plugins/builtin/chart-composer/settings.ts +2 -13
  184. package/src/plugins/builtin/chat/content/composer.tsx +8 -4
  185. package/src/plugins/builtin/cloud/auth-dialog.tsx +14 -228
  186. package/src/plugins/builtin/cloud/auth-form.tsx +277 -0
  187. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  188. package/src/plugins/builtin/composite-plugins.ts +16 -1
  189. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  190. package/src/plugins/builtin/correlation/relationship/pane.tsx +2 -6
  191. package/src/plugins/builtin/correlation/relationship/view-model.ts +2 -2
  192. package/src/plugins/builtin/credit-conditions/index.test.tsx +12 -6
  193. package/src/plugins/builtin/credit-conditions/index.tsx +2 -21
  194. package/src/plugins/builtin/dividend-yield/index.tsx +1 -0
  195. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  196. package/src/plugins/builtin/earnings/index.tsx +1 -0
  197. package/src/plugins/builtin/earnings-calls/data.ts +223 -0
  198. package/src/plugins/builtin/earnings-calls/format.ts +49 -0
  199. package/src/plugins/builtin/earnings-calls/index.tsx +69 -0
  200. package/src/plugins/builtin/earnings-calls/pane.tsx +756 -0
  201. package/src/plugins/builtin/earnings-calls/prose.test.ts +36 -0
  202. package/src/plugins/builtin/earnings-calls/prose.ts +59 -0
  203. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +334 -0
  204. package/src/plugins/builtin/econ/detail-view.tsx +1 -2
  205. package/src/plugins/builtin/econ/fred-series-map.ts +16 -1
  206. package/src/plugins/builtin/econ/index.tsx +3 -1
  207. package/src/plugins/builtin/econ-statistics/cache.ts +4 -0
  208. package/src/plugins/builtin/econ-statistics/client.ts +92 -0
  209. package/src/plugins/builtin/econ-statistics/defs.ts +66 -0
  210. package/src/plugins/builtin/econ-statistics/detail.tsx +154 -0
  211. package/src/plugins/builtin/econ-statistics/headless.test.ts +54 -0
  212. package/src/plugins/builtin/econ-statistics/headless.ts +171 -0
  213. package/src/plugins/builtin/econ-statistics/index.tsx +54 -0
  214. package/src/plugins/builtin/econ-statistics/pane.tsx +356 -0
  215. package/src/plugins/builtin/econ-statistics/stats.ts +522 -0
  216. package/src/plugins/builtin/econ-statistics/transform.test.ts +86 -0
  217. package/src/plugins/builtin/econ-statistics/transform.ts +85 -0
  218. package/src/plugins/builtin/econ-statistics/trend.ts +57 -0
  219. package/src/plugins/builtin/econ-statistics/view.ts +90 -0
  220. package/src/plugins/builtin/fear-greed/charts.tsx +7 -18
  221. package/src/plugins/builtin/fear-greed/data.ts +6 -1
  222. package/src/plugins/builtin/futures/index.tsx +1 -0
  223. package/src/plugins/builtin/fx-matrix/index.tsx +1 -0
  224. package/src/plugins/builtin/help/index.tsx +4 -0
  225. package/src/plugins/builtin/holders/index.tsx +1 -0
  226. package/src/plugins/builtin/insider/index.tsx +1 -0
  227. package/src/plugins/builtin/ipo-calendar/index.tsx +1 -0
  228. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  229. package/src/plugins/builtin/kelly-sizer/sections.tsx +2 -3
  230. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  231. package/src/plugins/builtin/market-movers/index.tsx +1 -0
  232. package/src/plugins/builtin/market-valuation/align.ts +122 -0
  233. package/src/plugins/builtin/market-valuation/cache.ts +32 -0
  234. package/src/plugins/builtin/market-valuation/chart-projection.ts +217 -0
  235. package/src/plugins/builtin/market-valuation/chart-series.ts +89 -0
  236. package/src/plugins/builtin/market-valuation/client.test.ts +141 -0
  237. package/src/plugins/builtin/market-valuation/client.ts +116 -0
  238. package/src/plugins/builtin/market-valuation/defs.ts +251 -0
  239. package/src/plugins/builtin/market-valuation/detail.tsx +159 -0
  240. package/src/plugins/builtin/market-valuation/headless.test.ts +58 -0
  241. package/src/plugins/builtin/market-valuation/headless.ts +170 -0
  242. package/src/plugins/builtin/market-valuation/index.tsx +64 -0
  243. package/src/plugins/builtin/market-valuation/indicators.ts +422 -0
  244. package/src/plugins/builtin/market-valuation/model.test.ts +350 -0
  245. package/src/plugins/builtin/market-valuation/model.ts +8 -0
  246. package/src/plugins/builtin/market-valuation/pane.test.tsx +247 -0
  247. package/src/plugins/builtin/market-valuation/pane.tsx +344 -0
  248. package/src/plugins/builtin/market-valuation/series.ts +12 -0
  249. package/src/plugins/builtin/market-valuation/settings.ts +38 -0
  250. package/src/plugins/builtin/market-valuation/sources.ts +130 -0
  251. package/src/plugins/builtin/market-valuation/trend.ts +89 -0
  252. package/src/plugins/builtin/market-valuation/view.ts +137 -0
  253. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +123 -0
  254. package/src/plugins/builtin/market-valuation/zone-scale/index.tsx +12 -0
  255. package/src/plugins/builtin/market-valuation/zone-scale/model.ts +60 -0
  256. package/src/plugins/builtin/market-valuation/zone-scale/terminal.tsx +94 -0
  257. package/src/plugins/builtin/news/wire/breaking/filters.test.ts +99 -0
  258. package/src/plugins/builtin/news/wire/breaking/filters.ts +110 -0
  259. package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +157 -53
  260. package/src/plugins/builtin/news/wire/breaking/notifications.ts +91 -25
  261. package/src/plugins/builtin/news/wire/index.tsx +31 -44
  262. package/src/plugins/builtin/options/analytics.test.ts +83 -0
  263. package/src/plugins/builtin/options/analytics.ts +110 -0
  264. package/src/plugins/builtin/options/index.tsx +18 -2
  265. package/src/plugins/builtin/options/table.ts +121 -51
  266. package/src/plugins/builtin/options/types.ts +22 -15
  267. package/src/plugins/builtin/options/view.test.tsx +53 -1
  268. package/src/plugins/builtin/options/view.tsx +92 -41
  269. package/src/plugins/builtin/plugin-marketplace/feed.ts +80 -0
  270. package/src/plugins/builtin/plugin-marketplace/index.tsx +31 -0
  271. package/src/plugins/builtin/plugin-marketplace/model.test.ts +200 -0
  272. package/src/plugins/builtin/plugin-marketplace/model.ts +204 -0
  273. package/src/plugins/builtin/plugin-marketplace/pane.tsx +385 -0
  274. package/src/plugins/builtin/plugin-marketplace/store.ts +46 -0
  275. package/src/plugins/builtin/plugin-module.test.ts +2 -4
  276. package/src/plugins/builtin/plugin-module.ts +9 -8
  277. package/src/plugins/builtin/portfolio-list/index.tsx +1 -0
  278. package/src/plugins/builtin/research/index.tsx +4 -0
  279. package/src/plugins/builtin/research-search/command-bar-search.test.ts +81 -0
  280. package/src/plugins/builtin/research-search/command-bar-search.ts +175 -0
  281. package/src/plugins/builtin/research-search/data.ts +109 -0
  282. package/src/plugins/builtin/research-search/document-view.test.tsx +75 -0
  283. package/src/plugins/builtin/research-search/document-view.tsx +254 -0
  284. package/src/plugins/builtin/research-search/filter-bar.tsx +62 -0
  285. package/src/plugins/builtin/research-search/focus-handoff.ts +47 -0
  286. package/src/plugins/builtin/research-search/index.tsx +85 -0
  287. package/src/plugins/builtin/research-search/model.test.ts +40 -0
  288. package/src/plugins/builtin/research-search/model.ts +291 -0
  289. package/src/plugins/builtin/research-search/pane.test.tsx +241 -0
  290. package/src/plugins/builtin/research-search/pane.tsx +678 -0
  291. package/src/plugins/builtin/research-search/saved-view.tsx +171 -0
  292. package/src/plugins/builtin/research-search/snippet-text.tsx +35 -0
  293. package/src/plugins/builtin/research-search/snippet.test.ts +78 -0
  294. package/src/plugins/builtin/research-search/snippet.ts +134 -0
  295. package/src/plugins/builtin/scanner/flow-model.test.ts +11 -1
  296. package/src/plugins/builtin/scanner/flow-model.ts +29 -1
  297. package/src/plugins/builtin/scanner/flow-pane.tsx +78 -22
  298. package/src/plugins/builtin/scanner/index.ts +2 -0
  299. package/src/plugins/builtin/sec/index.tsx +1 -0
  300. package/src/plugins/builtin/sectors/index.tsx +1 -0
  301. package/src/plugins/builtin/shared/series-cache.ts +93 -0
  302. package/src/plugins/builtin/short-interest/index.tsx +1 -0
  303. package/src/plugins/builtin/short-interest/pane.tsx +1 -1
  304. package/src/plugins/builtin/thirteenf/index.tsx +1 -0
  305. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +3 -5
  306. package/src/plugins/builtin/ticker-detail/index.tsx +2 -14
  307. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
  308. package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
  309. package/src/plugins/builtin/volatility/index.tsx +1 -1
  310. package/src/plugins/builtin/world-indices/index.tsx +1 -0
  311. package/src/plugins/builtin/world-venue-map/index.ts +27 -0
  312. package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +106 -0
  313. package/src/plugins/builtin/world-venue-map/map.tsx +481 -0
  314. package/src/plugins/builtin/world-venue-map/model.test.ts +85 -0
  315. package/src/plugins/builtin/world-venue-map/model.ts +268 -0
  316. package/src/plugins/builtin/world-venue-map/pane.tsx +300 -0
  317. package/src/plugins/builtin/world-venue-map/world-outlines.ts +2 -0
  318. package/src/plugins/builtin/yield-curve/index.tsx +1 -1
  319. package/src/plugins/bundle.test.ts +109 -0
  320. package/src/plugins/bundle.ts +139 -0
  321. package/src/plugins/catalog-backend.ts +6 -44
  322. package/src/plugins/catalog-browser.test.ts +1 -0
  323. package/src/plugins/catalog-browser.ts +12 -0
  324. package/src/plugins/catalog-manifest.test.ts +43 -0
  325. package/src/plugins/catalog-manifest.ts +92 -0
  326. package/src/plugins/catalog-ui.ts +20 -4
  327. package/src/plugins/catalog.ts +9 -2
  328. package/src/plugins/current-target.ts +28 -0
  329. package/src/plugins/host-contract.ts +37 -0
  330. package/src/plugins/host-link.ts +158 -0
  331. package/src/plugins/host-modules.ts +61 -0
  332. package/src/plugins/loader.ts +41 -22
  333. package/src/plugins/ownership.ts +1 -0
  334. package/src/plugins/prediction-markets/index.tsx +1 -0
  335. package/src/plugins/registry/context.ts +3 -0
  336. package/src/plugins/registry/contributions.ts +27 -0
  337. package/src/plugins/registry/index.test.ts +25 -0
  338. package/src/plugins/registry/index.ts +8 -0
  339. package/src/plugins/registry/pane-settings.test.ts +53 -0
  340. package/src/plugins/registry/pane-settings.ts +29 -3
  341. package/src/plugins/seed.test.ts +83 -0
  342. package/src/plugins/seed.ts +80 -0
  343. package/src/public/broker.ts +31 -0
  344. package/src/public/market-data.ts +9 -0
  345. package/src/public/pane-hooks.ts +57 -0
  346. package/src/public/public-api.test.ts +285 -0
  347. package/src/public/react.ts +62 -0
  348. package/src/public/test-support.ts +23 -0
  349. package/src/public/time-series.ts +8 -0
  350. package/src/public/utils.ts +77 -0
  351. package/src/remote/layout-helpers.ts +6 -8
  352. package/src/remote/resources.ts +2 -0
  353. package/src/remote/schema.ts +1 -0
  354. package/src/remote/semantic-tree.test.tsx +105 -0
  355. package/src/remote/semantic-tree.tsx +53 -35
  356. package/src/renderers/browser/main.tsx +6 -0
  357. package/src/renderers/browser/ui-host.tsx +11 -0
  358. package/src/renderers/cloudflare/worker.test.ts +19 -0
  359. package/src/renderers/cloudflare/worker.ts +1 -1
  360. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -2
  361. package/src/renderers/electrobun/bun/external-plugins.ts +140 -0
  362. package/src/renderers/electrobun/bun/index.ts +6 -2
  363. package/src/renderers/electrobun/shared/protocol.ts +25 -0
  364. package/src/renderers/electrobun/view/build-assets.ts +0 -1
  365. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +51 -1
  366. package/src/renderers/electrobun/view/external-plugins.test.ts +45 -0
  367. package/src/renderers/electrobun/view/external-plugins.ts +63 -0
  368. package/src/renderers/electrobun/view/host/ascii-text.test.ts +48 -0
  369. package/src/renderers/electrobun/view/host/ascii-text.ts +11 -1
  370. package/src/renderers/electrobun/view/host/chart-surface.tsx +38 -32
  371. package/src/renderers/electrobun/view/host/mouse.ts +16 -2
  372. package/src/renderers/electrobun/view/main.tsx +27 -2
  373. package/src/renderers/electrobun/view/styles.css +5 -0
  374. package/src/renderers/electrobun/view/toast-host.tsx +18 -0
  375. package/src/renderers/electrobun/view/ui-host.tsx +3 -0
  376. package/src/renderers/opentui/chart-surface.tsx +5 -1
  377. package/src/renderers/opentui/host.tsx +20 -2
  378. package/src/renderers/opentui/interaction-performance.test.ts +79 -0
  379. package/src/renderers/opentui/interaction-performance.ts +188 -0
  380. package/src/renderers/opentui/start.tsx +26 -1
  381. package/src/renderers/opentui/test-utils.tsx +13 -0
  382. package/src/renderers/opentui/toast-host.tsx +26 -2
  383. package/src/renderers/opentui/ui-host.tsx +1 -0
  384. package/src/sources/provider-router/search.test.ts +191 -0
  385. package/src/sources/provider-router/search.ts +92 -39
  386. package/src/state/app/context/index.tsx +2 -0
  387. package/src/state/app/context/selector.test.tsx +33 -1
  388. package/src/state/hooks/quote-streaming.test.tsx +93 -0
  389. package/src/state/hooks/quote-streaming.ts +106 -30
  390. package/src/state/pane-table-export-registry.ts +50 -0
  391. package/src/theme/color-utils.ts +1 -1
  392. package/src/theme/colors.ts +50 -0
  393. package/src/theme/themes.test.ts +15 -2
  394. package/src/theme/themes.ts +19 -1
  395. package/src/tickers/search/index.test.ts +26 -0
  396. package/src/tickers/search/index.ts +42 -17
  397. package/src/tickers/search/ranking.ts +14 -0
  398. package/src/time-series/chart-data.test.ts +216 -0
  399. package/src/time-series/range.ts +12 -0
  400. package/src/time-series/resolution.test.ts +25 -26
  401. package/src/time-series/resolution.ts +44 -25
  402. package/src/time-series/resolve.ts +7 -0
  403. package/src/time-series/spec.ts +5 -5
  404. package/src/time-series/types.ts +3 -1
  405. package/src/time-series/use-chart-resolution.ts +5 -0
  406. package/src/types/config.ts +123 -3
  407. package/src/types/data-provider.ts +11 -0
  408. package/src/types/headless.ts +161 -0
  409. package/src/types/plugin.ts +104 -20
  410. package/src/ui/host.tsx +19 -1
  411. package/src/ui/index.tsx +1 -0
  412. package/src/ui/toast.tsx +8 -4
  413. package/src/utils/csv.test.ts +13 -0
  414. package/src/utils/csv.ts +37 -0
  415. package/src/utils/format.ts +35 -0
  416. package/src/utils/fuzzy-search.test.ts +94 -0
  417. package/src/utils/fuzzy-search.ts +81 -22
  418. package/src/utils/save-text-file.test.ts +24 -0
  419. package/src/utils/save-text-file.ts +36 -0
  420. package/src/utils/shortcut-labels.ts +14 -0
  421. package/src/components/chart/core/axis-format.ts +0 -157
  422. package/src/components/chart/core/index.test.ts +0 -1075
  423. package/src/components/chart/core/projection.ts +0 -357
  424. package/src/components/chart/core/render-utils.ts +0 -4
  425. package/src/components/chart/core/renderer.ts +0 -244
  426. package/src/components/chart/core/scene.ts +0 -180
  427. package/src/components/chart/core/time-axis.ts +0 -330
  428. package/src/components/chart/cursor-motion.ts +0 -47
  429. package/src/components/chart/indicators/types.ts +0 -26
  430. package/src/components/chart/market-session.ts +0 -176
  431. package/src/components/chart/multi-line/renderer.test.ts +0 -83
  432. package/src/components/chart/multi-line/renderer.ts +0 -161
  433. package/src/components/chart/multi-line/scene.ts +0 -188
  434. package/src/components/chart/native/raster/layout.ts +0 -129
  435. package/src/components/chart/native/raster/price-chart.ts +0 -244
  436. package/src/components/chart/rendering/chart-draw.ts +0 -270
  437. package/src/components/chart/rendering/geometry.ts +0 -95
  438. package/src/components/chart/rendering/pixel-buffer.ts +0 -267
  439. package/src/components/chart/scatter-chart-renderer.test.ts +0 -31
  440. package/src/components/chart/scatter-chart-renderer.ts +0 -223
  441. package/src/components/chart/static/chart/surface.tsx +0 -358
  442. package/src/components/command-bar/routes/root/article-results.test.ts +0 -83
  443. package/src/components/command-bar/routes/root/article-results.ts +0 -55
  444. package/src/plugins/builtin/news/wire/article-search.test.ts +0 -72
  445. package/src/plugins/builtin/news/wire/article-search.ts +0 -140
  446. package/src/plugins/builtin/substack/api/auth.ts +0 -185
  447. package/src/plugins/builtin/substack/api/cache.ts +0 -82
  448. package/src/plugins/builtin/substack/api/loaders.ts +0 -170
  449. package/src/plugins/builtin/substack/api/store.ts +0 -186
  450. package/src/plugins/builtin/substack/api/types.ts +0 -42
  451. package/src/plugins/builtin/substack/api.test.ts +0 -298
  452. package/src/plugins/builtin/substack/article-detail.tsx +0 -397
  453. package/src/plugins/builtin/substack/article-stack.tsx +0 -133
  454. package/src/plugins/builtin/substack/content.ts +0 -478
  455. package/src/plugins/builtin/substack/feed-tabs.tsx +0 -44
  456. package/src/plugins/builtin/substack/index.tsx +0 -49
  457. package/src/plugins/builtin/substack/login-view.tsx +0 -126
  458. package/src/plugins/builtin/substack/model.test.ts +0 -155
  459. package/src/plugins/builtin/substack/normalize.ts +0 -343
  460. package/src/plugins/builtin/substack/pane-footer.ts +0 -52
  461. package/src/plugins/builtin/substack/pane-state.ts +0 -170
  462. package/src/plugins/builtin/substack/pane.tsx +0 -547
  463. package/src/plugins/builtin/substack/read-state.ts +0 -30
  464. package/src/plugins/builtin/substack/table.ts +0 -111
  465. package/src/plugins/builtin/substack/types.ts +0 -71
  466. package/src/plugins/builtin/substack/utils.ts +0 -131
  467. package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +0 -229
  468. package/src/plugins/ibkr/account-cache.test.ts +0 -102
  469. package/src/plugins/ibkr/account-cache.ts +0 -24
  470. package/src/plugins/ibkr/broker-adapter.ts +0 -286
  471. package/src/plugins/ibkr/config.test.ts +0 -79
  472. package/src/plugins/ibkr/config.ts +0 -250
  473. package/src/plugins/ibkr/dialogs.tsx +0 -40
  474. package/src/plugins/ibkr/flex/index.test.ts +0 -264
  475. package/src/plugins/ibkr/flex/index.ts +0 -367
  476. package/src/plugins/ibkr/flex/statement-client.ts +0 -235
  477. package/src/plugins/ibkr/fundamental-parser.ts +0 -149
  478. package/src/plugins/ibkr/gateway/account-loaders.ts +0 -266
  479. package/src/plugins/ibkr/gateway/account-summary.ts +0 -164
  480. package/src/plugins/ibkr/gateway/client-lock.ts +0 -154
  481. package/src/plugins/ibkr/gateway/connection-events.ts +0 -114
  482. package/src/plugins/ibkr/gateway/connection.ts +0 -152
  483. package/src/plugins/ibkr/gateway/contracts.ts +0 -132
  484. package/src/plugins/ibkr/gateway/fundamentals.ts +0 -83
  485. package/src/plugins/ibkr/gateway/helpers.ts +0 -33
  486. package/src/plugins/ibkr/gateway/history-requests.ts +0 -158
  487. package/src/plugins/ibkr/gateway/history.ts +0 -120
  488. package/src/plugins/ibkr/gateway/instrument-lookup.ts +0 -117
  489. package/src/plugins/ibkr/gateway/market-data.ts +0 -345
  490. package/src/plugins/ibkr/gateway/order-execution.ts +0 -218
  491. package/src/plugins/ibkr/gateway/orders.ts +0 -63
  492. package/src/plugins/ibkr/gateway/price-normalization.test.ts +0 -44
  493. package/src/plugins/ibkr/gateway/price-normalization.ts +0 -50
  494. package/src/plugins/ibkr/gateway/quote-stream-controller.ts +0 -203
  495. package/src/plugins/ibkr/gateway/quote-stream.ts +0 -171
  496. package/src/plugins/ibkr/gateway/selection.ts +0 -51
  497. package/src/plugins/ibkr/gateway/service/index.test.ts +0 -675
  498. package/src/plugins/ibkr/gateway/service/index.ts +0 -429
  499. package/src/plugins/ibkr/gateway/service/lifecycle.ts +0 -191
  500. package/src/plugins/ibkr/gateway/service/manager.ts +0 -52
  501. package/src/plugins/ibkr/gateway/service/market-data.ts +0 -48
  502. package/src/plugins/ibkr/gateway/service/native-loader.ts +0 -12
  503. package/src/plugins/ibkr/gateway/service/native.ts +0 -543
  504. package/src/plugins/ibkr/gateway/timeouts.ts +0 -13
  505. package/src/plugins/ibkr/gateway/types.ts +0 -27
  506. package/src/plugins/ibkr/index.test.tsx +0 -162
  507. package/src/plugins/ibkr/index.tsx +0 -159
  508. package/src/plugins/ibkr/instance-selection.test.ts +0 -120
  509. package/src/plugins/ibkr/instance-selection.ts +0 -36
  510. package/src/plugins/ibkr/portfolio-performance.test.ts +0 -32
  511. package/src/plugins/ibkr/portfolio-performance.ts +0 -129
  512. package/src/plugins/ibkr/trade/badge.tsx +0 -28
  513. package/src/plugins/ibkr/trade/dialogs.tsx +0 -44
  514. package/src/plugins/ibkr/trade/preview-panel.tsx +0 -130
  515. package/src/plugins/ibkr/trade/tab/actions.tsx +0 -443
  516. package/src/plugins/ibkr/trade/tab/field-editors.tsx +0 -79
  517. package/src/plugins/ibkr/trade/tab/footer.ts +0 -53
  518. package/src/plugins/ibkr/trade/tab/header.tsx +0 -167
  519. package/src/plugins/ibkr/trade/tab/index.test.tsx +0 -178
  520. package/src/plugins/ibkr/trade/tab/index.tsx +0 -298
  521. package/src/plugins/ibkr/trade/tab/model.ts +0 -159
  522. package/src/plugins/ibkr/trade/tab/order-request.ts +0 -64
  523. package/src/plugins/ibkr/trade/tab/shortcuts.ts +0 -89
  524. package/src/plugins/ibkr/trade/tab/state-sync.ts +0 -86
  525. package/src/plugins/ibkr/trade/ticket-panel.tsx +0 -301
  526. package/src/plugins/ibkr/trade/utils.test.ts +0 -175
  527. package/src/plugins/ibkr/trade/utils.ts +0 -144
  528. package/src/plugins/ibkr/trading/pane-view.tsx +0 -237
  529. package/src/plugins/ibkr/trading/pane.tsx +0 -332
  530. package/src/plugins/ibkr/trading/state.test.ts +0 -109
  531. package/src/plugins/ibkr/trading/state.ts +0 -335
@@ -1,429 +0,0 @@
1
- import type { TimeRange } from "../../../../time-series/range";
2
- import type { ChartResolutionSupport, ManualChartResolution } from "../../../../time-series/resolution";
3
- import { getBrokerRemoteClient } from "../../../../brokers/remote-broker-adapter";
4
- import type { BrokerPosition } from "../../../../types/broker";
5
- import type { QuoteSubscriptionTarget } from "../../../../types/data-provider";
6
- import type { Quote, PricePoint, TickerFinancials } from "../../../../types/financials";
7
- import type { BrokerContractRef, InstrumentSearchResult } from "../../../../types/instrument";
8
- import type {
9
- BrokerAccount,
10
- BrokerExecution,
11
- BrokerOrder,
12
- BrokerOrderPreview,
13
- BrokerOrderRequest,
14
- } from "../../../../types/trading";
15
- import type {
16
- IbkrGatewayConfig,
17
- IbkrSnapshot,
18
- ResolvedIbkrGatewayConnection,
19
- } from "../types";
20
- import {
21
- loadNativeGatewayModule as loadDefaultNativeGatewayModule,
22
- type NativeGatewayModule,
23
- } from "./native-loader";
24
-
25
- export type {
26
- IbkrGatewayConfig,
27
- ResolvedIbkrGatewayConnection,
28
- } from "../types";
29
-
30
- type NativeGatewayManager = any;
31
- type NativeGatewayService = any;
32
- type Listener = () => void;
33
- type ResolvedGatewayListener = (
34
- instanceId: string | undefined,
35
- connection: ResolvedIbkrGatewayConnection,
36
- ) => void | Promise<void>;
37
-
38
- const DEFAULT_SNAPSHOT: IbkrSnapshot = {
39
- status: { state: "disconnected", updatedAt: Date.now() },
40
- accounts: [],
41
- openOrders: [],
42
- executions: [],
43
- };
44
-
45
- let resolvedGatewayListener: ResolvedGatewayListener | null = null;
46
- let loadedNativeGatewayModule: NativeGatewayModule | null = null;
47
- let nativeGatewayModulePromise: Promise<NativeGatewayModule> | null = null;
48
- let nativeGatewayManager: NativeGatewayManager | null = null;
49
- let nativeGatewayModuleLoader: () => Promise<NativeGatewayModule>;
50
-
51
- const snapshots = new Map<string, IbkrSnapshot>();
52
- const listeners = new Map<string, Set<Listener>>();
53
-
54
- function getSnapshotEntry(instanceId?: string): IbkrSnapshot {
55
- if (!instanceId) return DEFAULT_SNAPSHOT;
56
- return snapshots.get(instanceId) ?? DEFAULT_SNAPSHOT;
57
- }
58
-
59
- function defaultNativeGatewayModuleLoader(): Promise<NativeGatewayModule> {
60
- return loadDefaultNativeGatewayModule();
61
- }
62
-
63
- nativeGatewayModuleLoader = defaultNativeGatewayModuleLoader;
64
-
65
- export function setNativeIbkrGatewayModuleLoader(loader: (() => Promise<NativeGatewayModule>) | null): void {
66
- nativeGatewayModuleLoader = loader ?? defaultNativeGatewayModuleLoader;
67
- }
68
-
69
- function applySnapshot(instanceId: string, patch: Partial<IbkrSnapshot>, shouldNotify: boolean): IbkrSnapshot {
70
- const current = getSnapshotEntry(instanceId);
71
- const next = {
72
- ...current,
73
- ...patch,
74
- status: patch.status ?? current.status,
75
- accounts: patch.accounts ?? current.accounts,
76
- openOrders: patch.openOrders ?? current.openOrders,
77
- executions: patch.executions ?? current.executions,
78
- };
79
- if (
80
- next.status === current.status
81
- && next.accounts === current.accounts
82
- && next.openOrders === current.openOrders
83
- && next.executions === current.executions
84
- ) {
85
- return current;
86
- }
87
- snapshots.set(instanceId, next);
88
- if (shouldNotify) notify(instanceId);
89
- return next;
90
- }
91
-
92
- function updateSnapshot(instanceId: string, patch: Partial<IbkrSnapshot>): void {
93
- applySnapshot(instanceId, patch, true);
94
- }
95
-
96
- function cacheSnapshot(instanceId: string, patch: Partial<IbkrSnapshot>): IbkrSnapshot {
97
- return applySnapshot(instanceId, patch, false);
98
- }
99
-
100
- function notify(instanceId: string): void {
101
- for (const listener of listeners.get(instanceId) ?? []) {
102
- listener();
103
- }
104
- }
105
-
106
- async function loadNativeGatewayModule(): Promise<NativeGatewayModule> {
107
- if (!nativeGatewayModulePromise) {
108
- nativeGatewayModulePromise = nativeGatewayModuleLoader().catch((error) => {
109
- nativeGatewayModulePromise = null;
110
- throw error;
111
- });
112
- }
113
- const module = await nativeGatewayModulePromise;
114
- loadedNativeGatewayModule = module;
115
- nativeGatewayManager = module.ibkrGatewayManager;
116
- module.setResolvedIbkrGatewayListener(resolvedGatewayListener);
117
- return module;
118
- }
119
-
120
- async function getNativeService(instanceId: string): Promise<NativeGatewayService> {
121
- const module = await loadNativeGatewayModule();
122
- return module.ibkrGatewayManager.getService(instanceId);
123
- }
124
-
125
- export function setResolvedIbkrGatewayListener(listener: ResolvedGatewayListener | null): void {
126
- resolvedGatewayListener = listener;
127
- if (getBrokerRemoteClient()) return;
128
- if (loadedNativeGatewayModule) {
129
- loadedNativeGatewayModule.setResolvedIbkrGatewayListener(listener);
130
- return;
131
- }
132
- if (!nativeGatewayModulePromise) {
133
- return;
134
- }
135
- void nativeGatewayModulePromise.then((module) => {
136
- module.setResolvedIbkrGatewayListener(listener);
137
- }).catch(() => {});
138
- }
139
-
140
- class IbkrGatewayServiceFacade {
141
- constructor(private readonly instanceId: string) {}
142
-
143
- getSnapshot(): IbkrSnapshot {
144
- const remoteStatus = getBrokerRemoteClient()?.getStatus(this.instanceId);
145
- if (remoteStatus) {
146
- return cacheSnapshot(this.instanceId, { status: remoteStatus });
147
- }
148
- if (nativeGatewayManager) {
149
- return nativeGatewayManager.getService(this.instanceId).getSnapshot();
150
- }
151
- return getSnapshotEntry(this.instanceId);
152
- }
153
-
154
- getResolvedConnection(): ResolvedIbkrGatewayConnection | null {
155
- if (nativeGatewayManager) {
156
- return nativeGatewayManager.getService(this.instanceId).getResolvedConnection();
157
- }
158
- return null;
159
- }
160
-
161
- subscribe(listener: Listener): () => void {
162
- if (!listeners.has(this.instanceId)) listeners.set(this.instanceId, new Set());
163
- listeners.get(this.instanceId)!.add(listener);
164
-
165
- const remoteDispose = getBrokerRemoteClient()?.subscribeStatus(this.instanceId, () => {
166
- const status = getBrokerRemoteClient()?.getStatus(this.instanceId);
167
- if (status) {
168
- updateSnapshot(this.instanceId, { status });
169
- } else {
170
- listener();
171
- }
172
- });
173
-
174
- if (remoteDispose) {
175
- return () => {
176
- remoteDispose();
177
- listeners.get(this.instanceId)?.delete(listener);
178
- };
179
- }
180
-
181
- let nativeDispose: (() => void) | null = null;
182
- if (nativeGatewayManager) {
183
- const service = nativeGatewayManager.getService(this.instanceId);
184
- nativeDispose = service.subscribe(() => {
185
- updateSnapshot(this.instanceId, service.getSnapshot());
186
- });
187
- }
188
- listener();
189
-
190
- return () => {
191
- nativeDispose?.();
192
- listeners.get(this.instanceId)?.delete(listener);
193
- };
194
- }
195
-
196
- async connect(config: IbkrGatewayConfig): Promise<void> {
197
- const remote = getBrokerRemoteClient();
198
- if (remote) {
199
- await remote.invoke<void>(this.instanceId, "connect");
200
- return;
201
- }
202
- const service = await getNativeService(this.instanceId);
203
- await service.connect(config);
204
- updateSnapshot(this.instanceId, service.getSnapshot());
205
- }
206
-
207
- async disconnect(): Promise<void> {
208
- const remote = getBrokerRemoteClient();
209
- if (remote) return remote.invoke<void>(this.instanceId, "disconnect");
210
- const service = await getNativeService(this.instanceId);
211
- await service.disconnect();
212
- updateSnapshot(this.instanceId, service.getSnapshot());
213
- }
214
-
215
- async getAccounts(config: IbkrGatewayConfig): Promise<BrokerAccount[]> {
216
- const remote = getBrokerRemoteClient();
217
- const accounts = remote
218
- ? await remote.invoke<BrokerAccount[]>(this.instanceId, "listAccounts")
219
- : await (await getNativeService(this.instanceId)).getAccounts(config);
220
- updateSnapshot(this.instanceId, { accounts });
221
- return accounts;
222
- }
223
-
224
- async getPositions(config: IbkrGatewayConfig): Promise<BrokerPosition[]> {
225
- const remote = getBrokerRemoteClient();
226
- return remote
227
- ? remote.invoke(this.instanceId, "importPositions")
228
- : (await getNativeService(this.instanceId)).getPositions(config);
229
- }
230
-
231
- async listOpenOrders(config: IbkrGatewayConfig): Promise<BrokerOrder[]> {
232
- const remote = getBrokerRemoteClient();
233
- const openOrders = remote
234
- ? await remote.invoke<BrokerOrder[]>(this.instanceId, "listOpenOrders")
235
- : await (await getNativeService(this.instanceId)).listOpenOrders(config);
236
- updateSnapshot(this.instanceId, { openOrders });
237
- return openOrders;
238
- }
239
-
240
- async listExecutions(config: IbkrGatewayConfig): Promise<BrokerExecution[]> {
241
- const remote = getBrokerRemoteClient();
242
- const executions = remote
243
- ? await remote.invoke<BrokerExecution[]>(this.instanceId, "listExecutions")
244
- : await (await getNativeService(this.instanceId)).listExecutions(config);
245
- updateSnapshot(this.instanceId, { executions });
246
- return executions;
247
- }
248
-
249
- async searchInstruments(query: string, config: IbkrGatewayConfig): Promise<InstrumentSearchResult[]> {
250
- const remote = getBrokerRemoteClient();
251
- return remote
252
- ? remote.invoke(this.instanceId, "searchInstruments", [query])
253
- : (await getNativeService(this.instanceId)).searchInstruments(query, config);
254
- }
255
-
256
- async getTickerFinancials(
257
- ticker: string,
258
- config: IbkrGatewayConfig,
259
- exchange = "",
260
- instrument?: BrokerContractRef | null,
261
- ): Promise<TickerFinancials> {
262
- const remote = getBrokerRemoteClient();
263
- return remote
264
- ? remote.invoke(this.instanceId, "getTickerFinancials", [ticker, exchange, instrument])
265
- : (await getNativeService(this.instanceId)).getTickerFinancials(ticker, config, exchange, instrument);
266
- }
267
-
268
- async getQuote(
269
- ticker: string,
270
- config: IbkrGatewayConfig,
271
- exchange = "",
272
- instrument?: BrokerContractRef | null,
273
- ): Promise<Quote> {
274
- const remote = getBrokerRemoteClient();
275
- return remote
276
- ? remote.invoke(this.instanceId, "getQuote", [ticker, exchange, instrument])
277
- : (await getNativeService(this.instanceId)).getQuote(ticker, config, exchange, instrument);
278
- }
279
-
280
- async getPriceHistory(
281
- ticker: string,
282
- config: IbkrGatewayConfig,
283
- exchange: string,
284
- range: TimeRange,
285
- instrument?: BrokerContractRef | null,
286
- ): Promise<PricePoint[]> {
287
- const remote = getBrokerRemoteClient();
288
- return remote
289
- ? remote.invoke(this.instanceId, "getPriceHistory", [ticker, exchange, range, instrument])
290
- : (await getNativeService(this.instanceId)).getPriceHistory(ticker, config, exchange, range, instrument);
291
- }
292
-
293
- getChartResolutionSupport(
294
- ticker: string,
295
- config: IbkrGatewayConfig,
296
- exchange = "",
297
- instrument?: BrokerContractRef | null,
298
- ): Promise<ChartResolutionSupport[]> | ChartResolutionSupport[] {
299
- const remote = getBrokerRemoteClient();
300
- return remote
301
- ? remote.invoke(this.instanceId, "getChartResolutionSupport", [ticker, exchange, instrument])
302
- : getNativeService(this.instanceId).then((service) => service.getChartResolutionSupport(ticker, config, exchange, instrument));
303
- }
304
-
305
- async getPriceHistoryForResolution(
306
- ticker: string,
307
- config: IbkrGatewayConfig,
308
- exchange: string,
309
- bufferRange: TimeRange,
310
- resolution: ManualChartResolution,
311
- instrument?: BrokerContractRef | null,
312
- ): Promise<PricePoint[]> {
313
- const remote = getBrokerRemoteClient();
314
- return remote
315
- ? remote.invoke(this.instanceId, "getPriceHistoryForResolution", [ticker, exchange, bufferRange, resolution, instrument])
316
- : (await getNativeService(this.instanceId)).getPriceHistoryForResolution(ticker, config, exchange, bufferRange, resolution, instrument);
317
- }
318
-
319
- async getDetailedPriceHistory(
320
- ticker: string,
321
- config: IbkrGatewayConfig,
322
- exchange: string,
323
- startDate: Date,
324
- endDate: Date,
325
- barSize: string,
326
- instrument?: BrokerContractRef | null,
327
- ): Promise<PricePoint[]> {
328
- const remote = getBrokerRemoteClient();
329
- return remote
330
- ? remote.invoke(this.instanceId, "getDetailedPriceHistory", [ticker, exchange, startDate, endDate, barSize, instrument])
331
- : (await getNativeService(this.instanceId)).getDetailedPriceHistory(ticker, config, exchange, startDate, endDate, barSize, instrument);
332
- }
333
-
334
- subscribeQuotes(
335
- config: IbkrGatewayConfig,
336
- targets: QuoteSubscriptionTarget[],
337
- onQuote: (target: QuoteSubscriptionTarget, quote: Quote) => void,
338
- ): () => void {
339
- const remote = getBrokerRemoteClient();
340
- if (remote) return remote.subscribeQuotes(this.instanceId, targets, onQuote);
341
-
342
- let nativeDispose: (() => void) | null = null;
343
- let disposed = false;
344
- void getNativeService(this.instanceId).then((service) => {
345
- if (disposed) return;
346
- nativeDispose = service.subscribeQuotes(config, targets, onQuote);
347
- }).catch(() => {});
348
- return () => {
349
- disposed = true;
350
- nativeDispose?.();
351
- };
352
- }
353
-
354
- async previewOrder(config: IbkrGatewayConfig, request: BrokerOrderRequest): Promise<BrokerOrderPreview> {
355
- const remote = getBrokerRemoteClient();
356
- return remote
357
- ? remote.invoke(this.instanceId, "previewOrder", [request])
358
- : (await getNativeService(this.instanceId)).previewOrder(config, request);
359
- }
360
-
361
- async placeOrder(config: IbkrGatewayConfig, request: BrokerOrderRequest): Promise<BrokerOrder> {
362
- const remote = getBrokerRemoteClient();
363
- return remote
364
- ? remote.invoke(this.instanceId, "placeOrder", [request])
365
- : (await getNativeService(this.instanceId)).placeOrder(config, request);
366
- }
367
-
368
- async modifyOrder(config: IbkrGatewayConfig, orderId: number, request: BrokerOrderRequest): Promise<BrokerOrder> {
369
- const remote = getBrokerRemoteClient();
370
- return remote
371
- ? remote.invoke(this.instanceId, "modifyOrder", [orderId, request])
372
- : (await getNativeService(this.instanceId)).modifyOrder(config, orderId, request);
373
- }
374
-
375
- async cancelOrder(config: IbkrGatewayConfig, orderId: number): Promise<void> {
376
- const remote = getBrokerRemoteClient();
377
- return remote
378
- ? remote.invoke(this.instanceId, "cancelOrder", [orderId])
379
- : (await getNativeService(this.instanceId)).cancelOrder(config, orderId);
380
- }
381
- }
382
-
383
- class IbkrGatewayServiceManager {
384
- private services = new Map<string, IbkrGatewayServiceFacade>();
385
-
386
- getService(instanceId: string): IbkrGatewayServiceFacade {
387
- let service = this.services.get(instanceId);
388
- if (!service) {
389
- service = new IbkrGatewayServiceFacade(instanceId);
390
- this.services.set(instanceId, service);
391
- }
392
- return service;
393
- }
394
-
395
- getSnapshot(instanceId?: string): IbkrSnapshot {
396
- if (!instanceId) return DEFAULT_SNAPSHOT;
397
- return this.getService(instanceId).getSnapshot();
398
- }
399
-
400
- subscribe(instanceId: string | undefined, listener: Listener): () => void {
401
- if (!instanceId) return () => {};
402
- return this.getService(instanceId).subscribe(listener);
403
- }
404
-
405
- async removeInstance(instanceId: string): Promise<void> {
406
- const remote = getBrokerRemoteClient();
407
- if (remote) {
408
- await remote.removeInstance(instanceId);
409
- } else if (nativeGatewayManager) {
410
- await nativeGatewayManager.removeInstance(instanceId);
411
- }
412
- this.services.delete(instanceId);
413
- snapshots.delete(instanceId);
414
- notify(instanceId);
415
- }
416
-
417
- async destroyAll(): Promise<void> {
418
- const remote = getBrokerRemoteClient();
419
- if (remote) {
420
- await remote.destroyAll();
421
- } else if (nativeGatewayManager) {
422
- await nativeGatewayManager.destroyAll();
423
- }
424
- this.services.clear();
425
- snapshots.clear();
426
- }
427
- }
428
-
429
- export const ibkrGatewayManager = new IbkrGatewayServiceManager();
@@ -1,191 +0,0 @@
1
- import { ConnectionState, IBApiNext, type MarketDataType } from "@stoqey/ib";
2
- import { firstValueFrom, filter, take, timeout } from "rxjs";
3
- import { debugLog } from "../../../../utils/debug-log";
4
- import type { IbkrClientLockManager } from "../client-lock";
5
- import {
6
- buildConnectionNote,
7
- resolveGatewayConnection,
8
- } from "../connection";
9
- import {
10
- getIbErrorCode,
11
- getIbErrorMessage,
12
- isClientIdInUseError,
13
- marketDataTypeFromConfig,
14
- } from "../market-data";
15
- import type { IbkrGatewayConfig, IbkrSnapshot, ResolvedIbkrGatewayConnection } from "../types";
16
-
17
- const gatewayLifecycleLog = debugLog.createLogger("ibkr-gateway");
18
-
19
- export type ResolvedGatewayListener = (
20
- instanceId: string | undefined,
21
- connection: ResolvedIbkrGatewayConnection,
22
- ) => void | Promise<void>;
23
-
24
- export interface ConnectIbkrGatewayInternalContext {
25
- instanceId: string | undefined;
26
- bindConnectionEvents: (api: IBApiNext) => void;
27
- disconnect: () => Promise<void>;
28
- getApi: () => IBApiNext | null;
29
- getConfigKey: () => string | null;
30
- getRequestedClientId: () => number | undefined;
31
- getSnapshot: () => IbkrSnapshot;
32
- loadInitialSnapshot: () => Promise<void>;
33
- setActiveMarketDataType: (marketDataType: MarketDataType) => void;
34
- setApi: (api: IBApiNext | null) => void;
35
- setAutoMarketData: (auto: boolean) => void;
36
- setConfigKey: (configKey: string | null) => void;
37
- setConnectionNote: (connectionNote: string | undefined) => void;
38
- updateSnapshot: (snapshot: IbkrSnapshot) => void;
39
- }
40
-
41
- export async function connectIbkrGatewayInternal(
42
- context: ConnectIbkrGatewayInternalContext,
43
- config: IbkrGatewayConfig,
44
- configKey: string,
45
- connectionNote?: string,
46
- ): Promise<void> {
47
- if (context.getApi() && context.getConfigKey() !== configKey) {
48
- await context.disconnect();
49
- }
50
-
51
- context.setConnectionNote(connectionNote);
52
- context.updateSnapshot({
53
- ...context.getSnapshot(),
54
- status: {
55
- state: "connecting",
56
- updatedAt: Date.now(),
57
- mode: "gateway",
58
- message: connectionNote,
59
- },
60
- lastError: undefined,
61
- });
62
-
63
- let api = context.getApi();
64
- if (!api) {
65
- api = new IBApiNext({
66
- host: config.host,
67
- port: config.port,
68
- reconnectInterval: 2_000,
69
- });
70
- context.setApi(api);
71
- context.bindConnectionEvents(api);
72
- }
73
-
74
- let unsubscribeConflict = () => {};
75
- const conflictPromise = new Promise<never>((_, reject) => {
76
- const subscription = api!.error.subscribe((err) => {
77
- const code = getIbErrorCode(err);
78
- const message = getIbErrorMessage(err);
79
- if (!isClientIdInUseError(code, message)) return;
80
- subscription.unsubscribe();
81
- reject(new Error(message || `IBKR client ID ${config.clientId} is already in use.`));
82
- });
83
- unsubscribeConflict = () => subscription.unsubscribe();
84
- });
85
-
86
- api.connect(config.clientId);
87
- try {
88
- await Promise.race([
89
- firstValueFrom(api.connectionState.pipe(
90
- filter((state) => state === ConnectionState.Connected),
91
- take(1),
92
- timeout(10_000),
93
- )),
94
- conflictPromise,
95
- ]);
96
- } finally {
97
- unsubscribeConflict();
98
- }
99
-
100
- gatewayLifecycleLog.info("Connected to IBKR gateway", {
101
- instanceId: context.instanceId,
102
- requestedClientId: context.getRequestedClientId() ?? config.clientId,
103
- actualClientId: config.clientId,
104
- host: config.host,
105
- port: config.port,
106
- });
107
-
108
- context.setAutoMarketData((config.marketDataType ?? "auto") === "auto");
109
- const activeMarketDataType = marketDataTypeFromConfig(config);
110
- context.setActiveMarketDataType(activeMarketDataType);
111
- api.setMarketDataType(activeMarketDataType);
112
- context.setConfigKey(configKey);
113
- await context.loadInitialSnapshot();
114
- context.updateSnapshot({
115
- ...context.getSnapshot(),
116
- status: {
117
- state: "connected",
118
- updatedAt: Date.now(),
119
- mode: "gateway",
120
- message: connectionNote,
121
- },
122
- });
123
- }
124
-
125
- export async function connectWithClientFallback({
126
- config,
127
- configKey,
128
- clientLocks,
129
- snapshot,
130
- updateSnapshot,
131
- connectInternal,
132
- disconnect,
133
- onResolved,
134
- }: {
135
- config: IbkrGatewayConfig;
136
- configKey: string;
137
- clientLocks: IbkrClientLockManager;
138
- snapshot: IbkrSnapshot;
139
- updateSnapshot: (snapshot: IbkrSnapshot) => void;
140
- connectInternal: (config: IbkrGatewayConfig, configKey: string, connectionNote?: string) => Promise<void>;
141
- disconnect: () => Promise<void>;
142
- onResolved: (connection: ResolvedIbkrGatewayConnection) => void;
143
- }): Promise<void> {
144
- let resolvedConfig: ResolvedIbkrGatewayConnection;
145
- try {
146
- resolvedConfig = await resolveGatewayConnection(config);
147
- } catch (error: any) {
148
- const message = error?.message || String(error || "");
149
- updateSnapshot({
150
- ...snapshot,
151
- status: {
152
- state: "error",
153
- updatedAt: Date.now(),
154
- mode: "gateway",
155
- message,
156
- },
157
- lastError: message,
158
- });
159
- throw error;
160
- }
161
-
162
- const candidates = clientLocks.getClientIdCandidates(resolvedConfig.requestedClientId);
163
- let lastConflict: Error | null = null;
164
-
165
- for (const clientId of candidates) {
166
- const claimed = await clientLocks.tryClaim(resolvedConfig, clientId, resolvedConfig.requestedClientId);
167
- if (!claimed) continue;
168
-
169
- try {
170
- await connectInternal(
171
- { ...config, host: resolvedConfig.host, port: resolvedConfig.port, clientId },
172
- configKey,
173
- buildConnectionNote(resolvedConfig.requestedClientId, clientId, resolvedConfig.requestedPort, resolvedConfig.port),
174
- );
175
- onResolved({ ...resolvedConfig, clientId });
176
- return;
177
- } catch (error: any) {
178
- const code = getIbErrorCode(error);
179
- const message = getIbErrorMessage(error) || error?.message || String(error || "");
180
- await disconnect();
181
- if (!isClientIdInUseError(code, message)) {
182
- throw error;
183
- }
184
- lastConflict = new Error(message || `IBKR client ID ${clientId} is already in use.`);
185
- }
186
- }
187
-
188
- throw lastConflict ?? new Error(
189
- `No IBKR client IDs are available near ${resolvedConfig.requestedClientId}. Close other sessions or choose a different client ID.`,
190
- );
191
- }
@@ -1,52 +0,0 @@
1
- import type { IbkrSnapshot } from "../types";
2
-
3
- export interface IbkrGatewayServiceLike {
4
- getSnapshot(): IbkrSnapshot;
5
- subscribe(listener: () => void): () => void;
6
- disconnect(): Promise<void>;
7
- }
8
-
9
- export class IbkrGatewayServiceManager<T extends IbkrGatewayServiceLike = IbkrGatewayServiceLike> {
10
- private services = new Map<string, T>();
11
-
12
- constructor(
13
- private readonly createService?: (instanceId: string) => T,
14
- private readonly fallbackSnapshot?: IbkrSnapshot,
15
- ) {}
16
-
17
- getService(instanceId: string): T {
18
- let service = this.services.get(instanceId);
19
- if (!service) {
20
- if (!this.createService) throw new Error("IBKR gateway service factory is required.");
21
- service = this.createService(instanceId);
22
- this.services.set(instanceId, service);
23
- }
24
- return service;
25
- }
26
-
27
- getSnapshot(instanceId?: string): IbkrSnapshot {
28
- if (!instanceId) {
29
- if (!this.fallbackSnapshot) throw new Error("IBKR gateway snapshot fallback is required without an instance ID.");
30
- return this.fallbackSnapshot;
31
- }
32
- return this.getService(instanceId).getSnapshot();
33
- }
34
-
35
- subscribe(instanceId: string | undefined, listener: () => void): () => void {
36
- if (!instanceId) return () => {};
37
- return this.getService(instanceId).subscribe(listener);
38
- }
39
-
40
- async removeInstance(instanceId: string): Promise<void> {
41
- const service = this.services.get(instanceId);
42
- if (!service) return;
43
- await service.disconnect();
44
- this.services.delete(instanceId);
45
- }
46
-
47
- async destroyAll(): Promise<void> {
48
- const services = [...this.services.values()];
49
- this.services.clear();
50
- await Promise.allSettled(services.map((service) => service.disconnect()));
51
- }
52
- }