gloomberb 0.3.7 → 0.4.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 (133) hide show
  1. package/README.md +19 -8
  2. package/package.json +1 -1
  3. package/src/app.tsx +29 -65
  4. package/src/cli/base-converter.ts +31 -0
  5. package/src/cli/commands/search.ts +11 -3
  6. package/src/cli/commands/ticker.ts +22 -11
  7. package/src/cli/context.ts +27 -32
  8. package/src/cli/helpers.ts +1 -4
  9. package/src/cli/index.ts +140 -123
  10. package/src/cli/registry.test.ts +226 -0
  11. package/src/cli/registry.ts +201 -0
  12. package/src/cli.test.ts +219 -0
  13. package/src/components/chart/chart-controller.ts +309 -0
  14. package/src/components/chart/chart-data.ts +5 -6
  15. package/src/components/chart/chart-pane-settings.ts +27 -0
  16. package/src/components/chart/chart-resolution.test.ts +56 -0
  17. package/src/components/chart/chart-resolution.ts +362 -0
  18. package/src/components/chart/chart-types.ts +12 -4
  19. package/src/components/chart/chart-viewport.test.ts +25 -0
  20. package/src/components/chart/chart-viewport.ts +28 -0
  21. package/src/components/chart/comparison-chart-data.ts +20 -27
  22. package/src/components/chart/comparison-stock-chart.tsx +374 -99
  23. package/src/components/chart/stock-chart-renderer-switch.test.tsx +124 -0
  24. package/src/components/chart/stock-chart.tsx +455 -106
  25. package/src/components/command-bar/__snapshots__/command-bar.test.tsx.snap +4 -4
  26. package/src/components/command-bar/command-bar.test.tsx +650 -5
  27. package/src/components/command-bar/command-bar.tsx +359 -63
  28. package/src/components/command-bar/command-registry.ts +8 -0
  29. package/src/components/command-bar/helpers.test.ts +23 -1
  30. package/src/components/command-bar/helpers.ts +14 -5
  31. package/src/components/command-bar/pane-template-display.ts +12 -0
  32. package/src/components/command-bar/root-shortcuts.ts +2 -1
  33. package/src/components/command-bar/workflow-ops.ts +4 -2
  34. package/src/components/detail-feed-view.test.tsx +124 -49
  35. package/src/components/detail-feed-view.tsx +396 -160
  36. package/src/components/layout/floating-pane.tsx +1 -1
  37. package/src/components/layout/pane-header.tsx +26 -2
  38. package/src/components/layout/shell.tsx +62 -50
  39. package/src/components/layout/status-bar.test.tsx +66 -0
  40. package/src/components/layout/status-bar.tsx +26 -5
  41. package/src/components/onboarding/onboarding-wizard.test.tsx +65 -0
  42. package/src/components/onboarding/onboarding-wizard.tsx +5 -6
  43. package/src/components/ticker-list-table.test.tsx +83 -0
  44. package/src/components/ticker-list-table.tsx +174 -97
  45. package/src/components/ui/data-table.tsx +27 -2
  46. package/src/components/ui/index.ts +1 -0
  47. package/src/components/ui/page-stack-view.tsx +60 -0
  48. package/src/components/use-double-click-activation.ts +31 -0
  49. package/src/index.tsx +10 -10
  50. package/src/market-data/coordinator.test.ts +92 -4
  51. package/src/market-data/coordinator.ts +32 -5
  52. package/src/market-data/hooks.test.tsx +120 -0
  53. package/src/market-data/hooks.tsx +53 -16
  54. package/src/market-data/request-types.ts +4 -2
  55. package/src/market-data/selectors.ts +24 -58
  56. package/src/plugins/builtin/chat-controller.test.ts +370 -3
  57. package/src/plugins/builtin/chat-controller.ts +310 -35
  58. package/src/plugins/builtin/chat.test.tsx +118 -6
  59. package/src/plugins/builtin/chat.tsx +175 -116
  60. package/src/plugins/builtin/comparison-chart.test.tsx +66 -5
  61. package/src/plugins/builtin/comparison-chart.tsx +21 -1
  62. package/src/plugins/builtin/news.tsx +1 -11
  63. package/src/plugins/builtin/portfolio-list/cli/commands.ts +656 -0
  64. package/src/plugins/builtin/portfolio-list/command-bar.ts +122 -0
  65. package/src/plugins/builtin/portfolio-list/header.tsx +16 -34
  66. package/src/plugins/builtin/portfolio-list/index.tsx +5 -0
  67. package/src/plugins/builtin/portfolio-list/metrics.test.ts +61 -0
  68. package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
  69. package/src/plugins/builtin/portfolio-list/mutations.test.ts +187 -0
  70. package/src/plugins/builtin/portfolio-list/mutations.ts +226 -0
  71. package/src/plugins/builtin/portfolio-list/pane.tsx +39 -17
  72. package/src/plugins/builtin/portfolio-list/table.tsx +11 -2
  73. package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.test.tsx +163 -0
  74. package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +81 -0
  75. package/src/plugins/builtin/sec.tsx +1 -11
  76. package/src/plugins/builtin/ticker-detail/chart-tab.tsx +13 -2
  77. package/src/plugins/builtin/ticker-detail/financials-tab.tsx +21 -0
  78. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +45 -10
  79. package/src/plugins/builtin/ticker-detail/pane.tsx +35 -17
  80. package/src/plugins/builtin/ticker-detail/settings.ts +19 -1
  81. package/src/plugins/builtin/ticker-detail.test.tsx +47 -0
  82. package/src/plugins/catalog.ts +65 -0
  83. package/src/plugins/ibkr/broker-adapter.ts +28 -0
  84. package/src/plugins/ibkr/gateway-service.test.ts +45 -1
  85. package/src/plugins/ibkr/gateway-service.ts +141 -7
  86. package/src/plugins/pane-manager.test.ts +1 -1
  87. package/src/plugins/plugin-runtime.tsx +27 -7
  88. package/src/plugins/prediction-markets/cli.ts +28 -0
  89. package/src/plugins/prediction-markets/controller-data.ts +11 -3
  90. package/src/plugins/prediction-markets/controller.ts +141 -121
  91. package/src/plugins/prediction-markets/index.tsx +2 -0
  92. package/src/plugins/prediction-markets/launch.ts +51 -16
  93. package/src/plugins/prediction-markets/metrics.ts +9 -5
  94. package/src/plugins/prediction-markets/pane.test.tsx +119 -57
  95. package/src/plugins/prediction-markets/pane.tsx +74 -153
  96. package/src/plugins/prediction-markets/table.tsx +6 -3
  97. package/src/plugins/prediction-markets/types.ts +0 -1
  98. package/src/sources/gloomberb-cloud.test.ts +29 -0
  99. package/src/sources/gloomberb-cloud.ts +89 -1
  100. package/src/sources/provider-router.test.ts +265 -3
  101. package/src/sources/provider-router.ts +239 -11
  102. package/src/sources/yahoo-finance.test.ts +26 -0
  103. package/src/sources/yahoo-finance.ts +54 -3
  104. package/src/state/app-context-selector.test.tsx +99 -0
  105. package/src/state/app-context.test.ts +18 -0
  106. package/src/state/app-context.tsx +170 -65
  107. package/src/state/selectors.ts +25 -0
  108. package/src/theme/colors.ts +8 -8
  109. package/src/theme/themes.test.ts +2 -0
  110. package/src/theme/themes.ts +22 -10
  111. package/src/types/broker.ts +21 -0
  112. package/src/types/config.ts +17 -1
  113. package/src/types/data-provider.ts +18 -0
  114. package/src/types/financials.ts +31 -1
  115. package/src/types/plugin.ts +70 -0
  116. package/src/utils/api-client.test.ts +57 -0
  117. package/src/utils/api-client.ts +35 -12
  118. package/src/utils/back-navigation.ts +27 -0
  119. package/src/utils/format.test.ts +14 -0
  120. package/src/utils/format.ts +3 -3
  121. package/src/utils/market-status.ts +46 -1
  122. package/src/utils/quote-freshness.ts +127 -0
  123. package/src/utils/quote-resolution.test.ts +277 -0
  124. package/src/utils/quote-resolution.ts +641 -0
  125. package/src/utils/slugify.ts +3 -0
  126. package/src/utils/timestamp.ts +25 -0
  127. package/src/version.ts +1 -1
  128. package/src/cli/commands/portfolio.ts +0 -210
  129. package/src/cli/commands/watchlist.ts +0 -210
  130. package/src/plugins/builtin/data-providers.ts +0 -16
  131. package/src/sources/exchange-rates.ts +0 -18
  132. package/src/utils/ascii-chart.ts +0 -172
  133. package/src/utils/ticker-tokenizer.test.ts +0 -48
@@ -9,7 +9,9 @@ import {
9
9
  createInitialState,
10
10
  type AppAction,
11
11
  } from "../../state/app-context";
12
+ import { MarketDataCoordinator, setSharedMarketDataCoordinator } from "../../market-data/coordinator";
12
13
  import { cloneLayout, createDefaultConfig, type AppConfig } from "../../types/config";
14
+ import type { DataProvider } from "../../types/data-provider";
13
15
  import type { PricePoint, TickerFinancials } from "../../types/financials";
14
16
  import type { TickerRecord } from "../../types/ticker";
15
17
  import { StockChart } from "./stock-chart";
@@ -19,6 +21,7 @@ const TEST_PANE_ID = "ticker-detail:test";
19
21
  let testSetup: Awaited<ReturnType<typeof createTestRenderer>> | undefined;
20
22
  let root: ReturnType<typeof createRoot> | undefined;
21
23
  let harnessDispatch: ((action: AppAction) => void) | null = null;
24
+ let sharedCoordinator: MarketDataCoordinator | null = null;
22
25
  const actEnvironment = globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean };
23
26
 
24
27
  function makeTicker(symbol: string): TickerRecord {
@@ -100,8 +103,58 @@ async function flushFrames(count = 2) {
100
103
  }
101
104
  }
102
105
 
106
+ async function emitKeypress(event: { name?: string; sequence?: string }) {
107
+ await act(async () => {
108
+ testSetup!.renderer.keyInput.emit("keypress", {
109
+ ctrl: false,
110
+ meta: false,
111
+ option: false,
112
+ shift: false,
113
+ eventType: "press",
114
+ repeated: false,
115
+ ...event,
116
+ } as never);
117
+ await testSetup!.renderOnce();
118
+ });
119
+ }
120
+
121
+ function makeProvider(historyBySymbol: Record<string, PricePoint[]>): DataProvider {
122
+ return {
123
+ id: "test-provider",
124
+ name: "Test Provider",
125
+ getTickerFinancials: async (symbol) => ({
126
+ annualStatements: [],
127
+ quarterlyStatements: [],
128
+ priceHistory: historyBySymbol[symbol] ?? [],
129
+ }),
130
+ getQuote: async (symbol) => ({
131
+ symbol,
132
+ price: historyBySymbol[symbol]?.[historyBySymbol[symbol]!.length - 1]?.close ?? 0,
133
+ currency: "USD",
134
+ change: 0,
135
+ changePercent: 0,
136
+ lastUpdated: Date.now(),
137
+ }),
138
+ getExchangeRate: async () => 1,
139
+ search: async () => [],
140
+ getNews: async () => [],
141
+ getArticleSummary: async () => null,
142
+ getPriceHistory: async (symbol) => historyBySymbol[symbol] ?? [],
143
+ getChartResolutionSupport: async () => [
144
+ { resolution: "5m", maxRange: "1W" },
145
+ { resolution: "15m", maxRange: "1M" },
146
+ { resolution: "1h", maxRange: "3M" },
147
+ { resolution: "1d", maxRange: "5Y" },
148
+ { resolution: "1wk", maxRange: "ALL" },
149
+ { resolution: "1mo", maxRange: "ALL" },
150
+ ],
151
+ };
152
+ }
153
+
103
154
  afterEach(() => {
104
155
  harnessDispatch = null;
156
+ sharedCoordinator = null;
157
+ setSharedMarketDataCoordinator(null);
105
158
  if (root) {
106
159
  act(() => {
107
160
  root!.unmount();
@@ -116,6 +169,40 @@ afterEach(() => {
116
169
  });
117
170
 
118
171
  describe("StockChart renderer switching", () => {
172
+ test("keeps range and resolution controls visible when history is empty", async () => {
173
+ const symbol = "AAPL";
174
+ const config = makeChartConfig(symbol);
175
+ const ticker = makeTicker(symbol);
176
+ const provider = makeProvider({ [symbol]: [] });
177
+ sharedCoordinator = new MarketDataCoordinator(provider);
178
+ setSharedMarketDataCoordinator(sharedCoordinator);
179
+ const financials: TickerFinancials = {
180
+ annualStatements: [],
181
+ quarterlyStatements: [],
182
+ priceHistory: [],
183
+ };
184
+
185
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
186
+ testSetup = await createTestRenderer({ width: 120, height: 32 });
187
+ root = createRoot(testSetup.renderer);
188
+ act(() => {
189
+ root!.render(
190
+ <ChartHarness
191
+ config={config}
192
+ ticker={ticker}
193
+ financials={financials}
194
+ />,
195
+ );
196
+ });
197
+
198
+ await flushFrames();
199
+ const frame = testSetup.captureCharFrame();
200
+ expect(frame).toContain("No price history available.");
201
+ expect(frame).toContain("1:1D");
202
+ expect(frame).toContain("2:1W");
203
+ expect(frame).toContain("AUTO");
204
+ });
205
+
119
206
  test("switches from braille to kitty without crashing text updates", async () => {
120
207
  const symbol = "AAPL";
121
208
  const config = makeChartConfig(symbol);
@@ -162,4 +249,41 @@ describe("StockChart renderer switching", () => {
162
249
  await flushFrames();
163
250
  expect(testSetup.captureCharFrame()).toContain("AAPL");
164
251
  });
252
+
253
+ test("applies preset hotkeys without reverting to the previous stored range", async () => {
254
+ const symbol = "AAPL";
255
+ const config = makeChartConfig(symbol);
256
+ const ticker = makeTicker(symbol);
257
+ const provider = makeProvider({ [symbol]: makeHistory(180) });
258
+ sharedCoordinator = new MarketDataCoordinator(provider);
259
+ setSharedMarketDataCoordinator(sharedCoordinator);
260
+ const financials: TickerFinancials = {
261
+ annualStatements: [],
262
+ quarterlyStatements: [],
263
+ priceHistory: makeHistory(180),
264
+ };
265
+
266
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
267
+ testSetup = await createTestRenderer({ width: 120, height: 32 });
268
+ root = createRoot(testSetup.renderer);
269
+ act(() => {
270
+ root!.render(
271
+ <ChartHarness
272
+ config={config}
273
+ ticker={ticker}
274
+ financials={financials}
275
+ />,
276
+ );
277
+ });
278
+
279
+ await flushFrames(3);
280
+ expect(testSetup.captureCharFrame()).toContain("AAPL - 1W");
281
+
282
+ await emitKeypress({ name: "3", sequence: "3" });
283
+ await flushFrames(3);
284
+
285
+ const frame = testSetup.captureCharFrame();
286
+ expect(frame).toContain("AAPL - 15M");
287
+ expect(frame).not.toContain("AAPL - 1W");
288
+ });
165
289
  });