gloomberb 0.11.0 → 0.11.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.
- package/README.md +38 -15
- package/README.zh-CN.md +12 -12
- package/package.json +10 -3
- package/src/api-client/auth.ts +14 -10
- package/src/api-client/data.ts +54 -0
- package/src/api-client/index.test.ts +124 -0
- package/src/api-client/index.ts +139 -4
- package/src/api-client/paths.ts +89 -0
- package/src/api-client/request.ts +15 -2
- package/src/api-client/socket-health.test.ts +1 -0
- package/src/api-client/socket.ts +2 -1
- package/src/api-client/types.ts +163 -0
- package/src/app/pane-runtime/index.tsx +4 -1
- package/src/app/pane-runtime/plugin-bindings.test.ts +117 -0
- package/src/app/pane-runtime/plugin-bindings.ts +25 -4
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +25 -14
- package/src/app/runtime/desktop-deeplink.test.ts +16 -0
- package/src/app/runtime/desktop-deeplink.ts +66 -2
- package/src/app/runtime/desktop-menu.ts +3 -0
- package/src/app/runtime/plugin-bindings.ts +30 -28
- package/src/app/runtime/update.ts +8 -6
- package/src/app.tsx +21 -7
- package/src/architecture/import-boundaries.test.ts +5 -1
- package/src/capabilities/factories.ts +4 -0
- package/src/cli/commands/automation.test.ts +9 -0
- package/src/cli/commands/automation.ts +22 -73
- package/src/cli/index.ts +10 -6
- package/src/cli/registry.ts +1 -1
- package/src/components/chart/composite/composite-chart.test.tsx +45 -2
- package/src/components/chart/composite/composite-chart.tsx +16 -12
- package/src/components/chart/composite/format.test.ts +34 -0
- package/src/components/chart/composite/format.ts +33 -10
- package/src/components/chart/composite/scene.ts +0 -21
- package/src/components/chart/composite/tools.ts +49 -0
- package/src/components/chart/core/axis-format.ts +13 -3
- package/src/components/chart/core/index.test.ts +7 -0
- package/src/components/chart/core/renderer.ts +3 -4
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -1
- package/src/components/command-bar/layout-items/current-layout.ts +1 -1
- package/src/components/command-bar/pane-templates/workflow.ts +4 -0
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +3 -0
- package/src/components/command-bar/routes/root/shortcuts.test.ts +19 -0
- package/src/components/command-bar/routes/root/shortcuts.ts +3 -1
- package/src/components/command-bar/surface/index.test.tsx +6 -6
- package/src/components/command-bar/surface/index.tsx +4 -1
- package/src/components/command-bar/surface/pane.test.tsx +66 -2
- package/src/components/command-bar/view-model.test.ts +2 -1
- package/src/components/command-bar/workflow/ops.test.ts +54 -0
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/company-logo.test.ts +19 -0
- package/src/components/company-logo.tsx +60 -0
- package/src/components/feed-data-table/stack-view.tsx +7 -1
- package/src/components/index.ts +1 -0
- package/src/components/layout/detached-pane-shell.tsx +85 -15
- package/src/components/layout/header.tsx +5 -5
- package/src/components/layout/pane/title.ts +31 -3
- package/src/components/layout/shell/active-drag.ts +4 -11
- package/src/components/layout/shell/drag/index.ts +4 -20
- package/src/components/layout/shell/drag/runtime.ts +3 -4
- package/src/components/layout/shell/index.test.tsx +17 -3
- package/src/components/layout/shell/index.tsx +89 -31
- package/src/components/layout/shell/menu.test.ts +37 -1
- package/src/components/layout/shell/menu.ts +14 -0
- package/src/components/layout/shell/native/pointer-runtime.ts +22 -8
- package/src/components/layout/shell/pane/actions.ts +0 -5
- package/src/components/layout/shell/pane/management-shortcuts.ts +9 -4
- package/src/components/layout/shell/shortcuts.ts +6 -3
- package/src/components/layout/shell/ticker-link-menu.test.ts +82 -0
- package/src/components/layout/shell/ticker-link-menu.ts +78 -0
- package/src/components/layout/status-bar.test.tsx +62 -61
- package/src/components/layout/status-bar.tsx +53 -75
- package/src/components/onboarding/account-step/form-panel.tsx +4 -2
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.test.tsx +44 -1
- package/src/components/onboarding/onboarding-wizard.tsx +13 -5
- package/src/components/onboarding/wizard-account.ts +4 -23
- package/src/components/table-view-shared.test.ts +11 -0
- package/src/components/table-view-shared.tsx +26 -0
- package/src/components/ui/data-table/index.tsx +19 -1
- package/src/components/ui/fields.tsx +5 -1
- package/src/core/state/app/layout-reducer.ts +36 -0
- package/src/core/state/app/layout.ts +10 -5
- package/src/core/state/app/state.ts +0 -13
- package/src/core/state/app/types.ts +6 -4
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/config/layout.ts +2 -0
- package/src/data/config/store/index.test.ts +27 -6
- package/src/data/config/store/normalize.ts +3 -5
- package/src/data/plugin-state-store.ts +11 -0
- package/src/data/sqlite/cache.test.ts +10 -0
- package/src/i18n/es.ts +13 -5
- package/src/i18n/ja.ts +13 -5
- package/src/i18n/ko.ts +13 -5
- package/src/i18n/zh-cn.ts +13 -5
- package/src/i18n/zh-tw.ts +13 -5
- package/src/layout-marketplace/api.test.ts +54 -0
- package/src/layout-marketplace/api.ts +65 -0
- package/src/layout-marketplace/gallery-desktop.test.tsx +262 -0
- package/src/layout-marketplace/gallery-desktop.tsx +375 -0
- package/src/layout-marketplace/gallery-terminal.tsx +376 -0
- package/src/layout-marketplace/gallery.test.tsx +84 -0
- package/src/layout-marketplace/gallery.tsx +323 -0
- package/src/layout-marketplace/geometry.test.ts +47 -0
- package/src/layout-marketplace/geometry.ts +80 -0
- package/src/layout-marketplace/mini-workspace.test.tsx +122 -0
- package/src/layout-marketplace/mini-workspace.tsx +428 -0
- package/src/layout-marketplace/model.test.ts +118 -0
- package/src/layout-marketplace/model.ts +171 -0
- package/src/layout-marketplace/name-dialog.tsx +60 -0
- package/src/layout-marketplace/pane-imagery.ts +85 -0
- package/src/layout-marketplace/pane.tsx +20 -0
- package/src/layout-marketplace/payload.test.ts +246 -0
- package/src/layout-marketplace/payload.ts +624 -0
- package/src/layout-marketplace/use-marketplace.ts +63 -0
- package/src/market-data/coordinator/index.test.ts +2 -2
- package/src/market-data/coordinator/index.ts +1 -1
- package/src/market-data/hooks.tsx +0 -41
- package/src/market-data/market/format.test.ts +7 -0
- package/src/market-data/market/freshness.ts +5 -2
- package/src/market-data/quotes/freshness.test.ts +16 -0
- package/src/news/aggregator.test.ts +92 -3
- package/src/news/aggregator.ts +98 -18
- package/src/news/hooks.test.tsx +2 -0
- package/src/news/hooks.ts +27 -1
- package/src/news/news-model.ts +5 -2
- package/src/news/types.ts +7 -0
- package/src/plugins/broker-sync/broker-sync.test.ts +58 -0
- package/src/plugins/broker-sync/normalize.ts +42 -5
- package/src/plugins/builtin/account-management/pane.tsx +5 -5
- package/src/plugins/builtin/ai/index.tsx +18 -2
- package/src/plugins/builtin/ai/screener/pane.test.tsx +47 -4
- package/src/plugins/builtin/ai/screener/pane.tsx +35 -12
- package/src/plugins/builtin/alerts/alert-engine.test.ts +53 -1
- package/src/plugins/builtin/alerts/alert-engine.ts +34 -1
- package/src/plugins/builtin/alerts/index.test.tsx +49 -6
- package/src/plugins/builtin/alerts/index.tsx +11 -6
- package/src/plugins/builtin/alerts/pane.tsx +51 -9
- package/src/plugins/builtin/alerts/quotes.ts +11 -3
- package/src/plugins/builtin/alerts/types.ts +1 -0
- package/src/plugins/builtin/analytics/index.tsx +11 -1
- package/src/plugins/builtin/analytics/pane-model.ts +6 -4
- package/src/plugins/builtin/broker-manager/index.tsx +3 -0
- package/src/plugins/builtin/buildout/model/index.ts +1 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +17 -18
- package/src/plugins/builtin/cds/client.test.ts +83 -0
- package/src/plugins/builtin/cds/client.ts +67 -0
- package/src/plugins/builtin/cds/index.tsx +41 -0
- package/src/plugins/builtin/cds/model.test.ts +232 -0
- package/src/plugins/builtin/cds/model.ts +401 -0
- package/src/plugins/builtin/cds/pane.test.tsx +132 -0
- package/src/plugins/builtin/cds/pane.tsx +358 -0
- package/src/plugins/builtin/chart-composer/chart-spec.ts +31 -0
- package/src/plugins/builtin/chart-composer/index.tsx +88 -2
- package/src/plugins/builtin/chart-composer/pane-share.test.ts +71 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +103 -15
- package/src/plugins/builtin/chat/content/index.tsx +4 -1
- package/src/plugins/builtin/chat/controller/channels.ts +7 -1
- package/src/plugins/builtin/chat/controller/index.ts +14 -9
- package/src/plugins/builtin/chat/controller/notifications.ts +13 -3
- package/src/plugins/builtin/chat/controller/persistence.ts +0 -3
- package/src/plugins/builtin/chat/controller/realtime.ts +3 -3
- package/src/plugins/builtin/chat/controller/send.ts +1 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +18 -11
- package/src/plugins/builtin/chat/controller/state.ts +1 -3
- package/src/plugins/builtin/chat/controller/storage.ts +0 -2
- package/src/plugins/builtin/chat/controller/utils.ts +4 -6
- package/src/plugins/builtin/chat/controller/view.ts +2 -2
- package/src/plugins/builtin/chat/controller.test.ts +142 -14
- package/src/plugins/builtin/chat/message/desktop.test.tsx +88 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -1
- package/src/plugins/builtin/chat/message/profile-popover.test.tsx +1 -29
- package/src/plugins/builtin/chat/profile-popover.ts +53 -22
- package/src/plugins/builtin/chat/sidebar.test.tsx +81 -0
- package/src/plugins/builtin/chat/sidebar.tsx +63 -0
- package/src/plugins/builtin/chat/test-harness.tsx +29 -1
- package/src/plugins/builtin/cloud/auth-actions.tsx +14 -7
- package/src/plugins/builtin/cloud/auth-commands.ts +21 -51
- package/src/plugins/builtin/cloud/auth-dialog.tsx +296 -0
- package/src/{components/onboarding/account-step/model.test.ts → plugins/builtin/cloud/auth-model.test.ts} +1 -1
- package/src/{components/onboarding/account-step/model.ts → plugins/builtin/cloud/auth-model.ts} +37 -3
- package/src/plugins/builtin/cloud/browser.tsx +9 -0
- package/src/plugins/builtin/cloud/buildout-module.tsx +23 -0
- package/src/plugins/builtin/cloud/device-signin.ts +2 -8
- package/src/plugins/builtin/cloud/index.tsx +2 -0
- package/src/plugins/builtin/cloud/plugin.tsx +14 -24
- package/src/plugins/builtin/cloud/upgrade-command.ts +13 -6
- package/src/plugins/builtin/cloud-tweets/pane-share.test.ts +56 -0
- package/src/plugins/builtin/cloud-tweets/pane.tsx +20 -5
- package/src/plugins/builtin/cloud-tweets/registration.ts +50 -6
- package/src/plugins/builtin/composite-plugins.ts +3 -1
- package/src/plugins/builtin/congress-trades/detail.tsx +43 -1
- package/src/plugins/builtin/congress-trades/model.test.ts +85 -0
- package/src/plugins/builtin/congress-trades/model.ts +69 -1
- package/src/plugins/builtin/congress-trades/pane.tsx +51 -2
- package/src/plugins/builtin/connections/index.ts +3 -0
- package/src/plugins/builtin/dividend-yield/client.ts +18 -0
- package/src/plugins/builtin/dividend-yield/pane.tsx +7 -6
- package/src/plugins/builtin/earnings/index.tsx +5 -3
- package/src/plugins/builtin/earnings/model.test.ts +19 -1
- package/src/plugins/builtin/earnings/model.ts +17 -15
- package/src/plugins/builtin/econ/calendar-model.ts +0 -5
- package/src/plugins/builtin/econ/index.test.tsx +6 -1
- package/src/plugins/builtin/fear-greed/charts.tsx +12 -8
- package/src/plugins/builtin/help/index.tsx +2 -2
- package/src/plugins/builtin/holders/thirteenf-match.ts +1 -2
- package/src/plugins/builtin/insider/index.tsx +27 -11
- package/src/plugins/builtin/kelly-sizer/index.tsx +4 -1
- package/src/plugins/builtin/layout-manager/index.tsx +17 -4
- package/src/plugins/builtin/news/index.tsx +11 -6
- package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +2 -0
- package/src/plugins/builtin/news/wire/breaking/pane.test.tsx +2 -0
- package/src/plugins/builtin/news/wire/breaking/pane.tsx +4 -1
- package/src/plugins/builtin/news/wire/feed-config.test.ts +15 -1
- package/src/plugins/builtin/news/wire/feed-config.ts +25 -5
- package/src/plugins/builtin/news/wire/index.tsx +3 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +7 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +34 -1
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +4 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +8 -2
- package/src/plugins/builtin/news/wire/rss/source.test.ts +12 -0
- package/src/plugins/builtin/news/wire/rss/source.ts +1 -1
- package/src/plugins/builtin/notes/files.ts +80 -0
- package/src/plugins/builtin/notes/index.tsx +3 -0
- package/src/plugins/builtin/notes/sync.test.ts +49 -0
- package/src/plugins/builtin/notes/sync.ts +98 -0
- package/src/plugins/builtin/options/index.tsx +1 -0
- package/src/plugins/builtin/options/view.test.tsx +25 -3
- package/src/plugins/builtin/options/view.tsx +1 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.test.ts +22 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +12 -7
- package/src/plugins/builtin/portfolio-list/cli/render.ts +5 -3
- package/src/plugins/builtin/portfolio-list/column-values.ts +15 -4
- package/src/plugins/builtin/portfolio-list/header.tsx +13 -3
- package/src/plugins/builtin/portfolio-list/index.tsx +8 -0
- package/src/plugins/builtin/portfolio-list/metrics.test.ts +31 -1
- package/src/plugins/builtin/portfolio-list/pane/index.test.tsx +1 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +10 -7
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +6 -1
- package/src/plugins/builtin/portfolio-list/position-metrics.ts +25 -6
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +35 -21
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +20 -6
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -12
- package/src/plugins/builtin/research/equity-diagnostic-pane.test.tsx +329 -0
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +582 -0
- package/src/plugins/builtin/research/index.test.ts +14 -0
- package/src/plugins/builtin/research/index.tsx +29 -0
- package/src/plugins/builtin/sec/index.tsx +24 -9
- package/src/plugins/builtin/sectors/index.tsx +14 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +18 -11
- package/src/plugins/builtin/shared/public-pane.test.ts +12 -0
- package/src/plugins/builtin/shared/public-pane.ts +9 -0
- package/src/plugins/builtin/shared/public-share.ts +23 -0
- package/src/plugins/builtin/shared/ticker-source.ts +32 -0
- package/src/plugins/builtin/shared/ticker-surface.test.ts +27 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +17 -0
- package/src/plugins/builtin/substack/api/cache.ts +7 -3
- package/src/plugins/builtin/substack/api/loaders.ts +36 -12
- package/src/plugins/builtin/substack/api/types.ts +2 -0
- package/src/plugins/builtin/substack/pane-state.ts +1 -1
- package/src/plugins/builtin/substack/pane.tsx +55 -12
- package/src/plugins/builtin/thirteenf/api.test.ts +1 -1
- package/src/plugins/builtin/thirteenf/api.ts +40 -18
- package/src/plugins/builtin/thirteenf/data.ts +15 -7
- package/src/plugins/builtin/thirteenf/pane.tsx +45 -10
- package/src/plugins/builtin/ticker-detail/index.tsx +10 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +12 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +8 -2
- package/src/plugins/builtin/ticker-detail/settings.ts +12 -0
- package/src/plugins/builtin/treasury-auctions/index.tsx +2 -0
- package/src/plugins/builtin/world-indices/index.tsx +2 -0
- package/src/plugins/catalog-browser.test.ts +78 -0
- package/src/plugins/catalog-browser.ts +136 -0
- package/src/plugins/gridlock-notification.ts +2 -1
- package/src/plugins/ibkr/flex/index.test.ts +19 -0
- package/src/plugins/ibkr/flex/index.ts +1 -1
- package/src/plugins/pane-manager/gridlock.ts +87 -3
- package/src/plugins/pane-manager.test.ts +30 -0
- package/src/plugins/pane-manager.ts +6 -1
- package/src/plugins/prediction-markets/chart.tsx +2 -2
- package/src/plugins/prediction-markets/controller/catalog.ts +77 -2
- package/src/plugins/prediction-markets/controller/data.ts +7 -1
- package/src/plugins/prediction-markets/controller/index.ts +9 -2
- package/src/plugins/prediction-markets/controller/keyboard.ts +10 -14
- package/src/plugins/prediction-markets/detail/overview.tsx +21 -0
- package/src/plugins/prediction-markets/detail/pane.tsx +43 -34
- package/src/plugins/prediction-markets/detail/trades.tsx +34 -9
- package/src/plugins/prediction-markets/detail.test.tsx +29 -2
- package/src/plugins/prediction-markets/index.tsx +8 -4
- package/src/plugins/prediction-markets/navigation.ts +0 -1
- package/src/plugins/prediction-markets/pane.test.tsx +77 -0
- package/src/plugins/prediction-markets/pane.tsx +12 -0
- package/src/plugins/prediction-markets/plugin.test.tsx +36 -0
- package/src/plugins/prediction-markets/services/kalshi/adapter.ts +49 -9
- package/src/plugins/prediction-markets/services/polymarket/adapter.ts +31 -0
- package/src/plugins/prediction-markets/test-helpers.tsx +9 -0
- package/src/plugins/registry/index.ts +2 -0
- package/src/plugins/ticker-navigation.test.ts +24 -0
- package/src/plugins/ticker-navigation.ts +40 -0
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/app-services.ts +61 -0
- package/src/renderers/browser/cloud-transport.test.ts +68 -0
- package/src/renderers/browser/cloud-transport.ts +48 -0
- package/src/renderers/browser/config-host.ts +58 -0
- package/src/renderers/browser/deeplink-bridge.test.ts +41 -0
- package/src/renderers/browser/deeplink-bridge.ts +22 -0
- package/src/renderers/browser/error-boundary.tsx +23 -0
- package/src/renderers/browser/main.tsx +64 -0
- package/src/renderers/browser/persistence.ts +74 -0
- package/src/renderers/browser/storage.test.ts +66 -0
- package/src/renderers/browser/storage.ts +50 -0
- package/src/renderers/browser/ticker-repository.ts +59 -0
- package/src/renderers/browser/ui-host.tsx +40 -0
- package/src/renderers/cloudflare/worker.test.ts +136 -0
- package/src/renderers/cloudflare/worker.ts +116 -0
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -2
- package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/plugin-state.ts +7 -1
- package/src/renderers/electrobun/view/app-services.ts +14 -3
- package/src/renderers/electrobun/view/build-assets.ts +12 -10
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/data-table/index.tsx +10 -1
- package/src/renderers/electrobun/view/desktop/controls.tsx +2 -0
- package/src/renderers/electrobun/view/dom-ui-host.tsx +143 -0
- package/src/renderers/electrobun/view/host/box.test.tsx +33 -0
- package/src/renderers/electrobun/view/host/box.tsx +11 -6
- package/src/renderers/electrobun/view/host/chart-surface.tsx +7 -1
- package/src/renderers/electrobun/view/host/input.tsx +11 -7
- package/src/renderers/electrobun/view/host/native.ts +0 -5
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +5 -0
- package/src/renderers/electrobun/view/styles.css +107 -7
- package/src/renderers/electrobun/view/toast-host.test.tsx +78 -0
- package/src/renderers/electrobun/view/toast-host.tsx +69 -43
- package/src/renderers/electrobun/view/ui-host.tsx +6 -137
- package/src/renderers/opentui/start.tsx +2 -0
- package/src/renderers/share/layout-view.test.tsx +58 -0
- package/src/renderers/share/layout-view.tsx +133 -0
- package/src/renderers/share/main.tsx +102 -0
- package/src/renderers/share/styles.css +54 -0
- package/src/renderers/share/view.test.tsx +100 -0
- package/src/renderers/share/view.tsx +150 -0
- package/src/shares/api.test.ts +105 -0
- package/src/shares/api.ts +127 -0
- package/src/shares/chart-snapshot.test.ts +34 -0
- package/src/shares/chart-snapshot.ts +28 -0
- package/src/shares/location.test.ts +19 -0
- package/src/shares/location.ts +11 -0
- package/src/shares/pane.test.ts +110 -0
- package/src/shares/pane.ts +54 -0
- package/src/shares/payload.ts +177 -0
- package/src/sources/gloomberb-cloud/index.test.ts +61 -1
- package/src/sources/gloomberb-cloud/index.ts +86 -14
- package/src/sources/gloomberb-cloud/normalizers.test.ts +34 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -5
- package/src/sources/provider-router/history.test.ts +2 -2
- package/src/sources/provider-router/news.test.ts +34 -0
- package/src/sources/provider-router/news.ts +15 -1
- package/src/sources/sec-edgar.test.ts +59 -0
- package/src/sources/sec-edgar.ts +63 -23
- package/src/sources/yahoo-finance/mappers.ts +3 -0
- package/src/sources/yahoo-finance/snapshots.ts +10 -2
- package/src/sources/yahoo-finance/symbols.test.ts +10 -0
- package/src/sources/yahoo-finance/symbols.ts +13 -8
- package/src/sources/yahoo-finance.test.ts +1 -1
- package/src/sources/yahoo-finance.ts +6 -2
- package/src/state/app/bootstrap.ts +6 -7
- package/src/state/app/context/index.test.ts +41 -1
- package/src/state/app/context/index.test.tsx +34 -16
- package/src/state/selectors-ui.ts +0 -8
- package/src/sync/baseline.ts +32 -0
- package/src/sync/controller.test.ts +124 -1
- package/src/sync/controller.ts +54 -12
- package/src/sync/core-contributors.test.ts +44 -0
- package/src/sync/core-contributors.ts +59 -10
- package/src/sync/react.ts +22 -2
- package/src/sync/types.ts +12 -0
- package/src/theme/font-scale.ts +0 -11
- package/src/tickers/search/index.test.ts +27 -0
- package/src/tickers/search/upsert.ts +10 -0
- package/src/types/capability-route-source.ts +2 -1
- package/src/types/config.ts +35 -5
- package/src/types/desktop-menu.ts +1 -0
- package/src/types/plugin.ts +36 -0
- package/src/ui/context-menu.tsx +1 -1
- package/src/ui/host.tsx +4 -0
- package/src/ui/toast.tsx +2 -0
- package/src/utils/back-navigation.ts +0 -4
- package/src/utils/price-history.ts +11 -10
- package/src/utils/sec.test.ts +6 -0
- package/src/utils/sec.ts +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="https://
|
|
3
|
+
<img src="https://gloom.sh/gloomberb-logo-grayscale.svg" alt="Gloomberb logo" width="76" />
|
|
4
4
|
|
|
5
5
|
# Gloomberb
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
Desktop app for macOS and Windows. Terminal UI for macOS, Linux, and Windows.
|
|
10
10
|
|
|
11
|
-
<a href="https://
|
|
11
|
+
<a href="https://gloom.sh/download/desktop"><strong>Download desktop</strong></a>
|
|
12
12
|
·
|
|
13
13
|
<a href="#install"><strong>Install the TUI</strong></a>
|
|
14
14
|
·
|
|
@@ -17,7 +17,7 @@ Desktop app for macOS and Windows. Terminal UI for macOS, Linux, and Windows.
|
|
|
17
17
|
<br />
|
|
18
18
|
<br />
|
|
19
19
|
|
|
20
|
-
<img src="https://
|
|
20
|
+
<img src="https://gloom.sh/landing-terminal.png" alt="Gloomberb terminal showing portfolio, watchlists, market data, and chart panels." width="720" />
|
|
21
21
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
@@ -29,8 +29,24 @@ Gloomberb has two ways in:
|
|
|
29
29
|
|---------|----------|-------------|
|
|
30
30
|
| Desktop app | A polished app window, pop-out panes, OS shortcuts, and built-in updates | Published for macOS and Windows. It also installs a `gloomberb` terminal command for the TUI. |
|
|
31
31
|
| Terminal UI | Fast keyboard workflows inside your terminal, SSH/dev boxes, Linux machines, and script-friendly setups | Runs with `gloomberb` on macOS, Linux, and Windows. |
|
|
32
|
+
| Browser app | The shared DOM interface without an install | Open [term.gloom.sh](https://term.gloom.sh). |
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
The desktop app and TUI share the full command language and plugin system. The browser app uses the same official DOM renderer and layout with a reviewed browser plugin catalog.
|
|
35
|
+
|
|
36
|
+
## Browser App
|
|
37
|
+
|
|
38
|
+
[term.gloom.sh](https://term.gloom.sh) works anonymously with configuration, tickers, layouts, session state, and plugin state stored in the browser. Anonymous sessions receive rate-limited, 15-minute-delayed Gloom Cloud market data and read-only chat. Login remains optional and enables sync and chat posting; Pro accounts receive realtime market data. Cloud REST and WebSocket traffic uses the same-origin `/api` path, which the Worker forwards only to `https://api.gloom.sh`; it is not an arbitrary network proxy.
|
|
39
|
+
|
|
40
|
+
The browser build intentionally omits brokers and native integrations, filesystem notes, local AI, external plugins, updater/debug tools, application menus, native window controls, pop-out native windows, and native context menus. Modules that still depend on desktop-only or CORS-blocked feeds are also absent for now: RSS/Substack, prediction markets and polls, market halts/heatmap/movers, dividend/ownership/SEC panes, earnings/IPO, and TV. Public shares open under `/s/:id` in a separate slim bundle. Share creation and owner deletion use the signed-in Gloom Cloud session through the same fixed API path; public reads require no account.
|
|
41
|
+
|
|
42
|
+
Local browser development:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bun run web:build
|
|
46
|
+
bunx wrangler dev
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Validate the public artifacts with `bun run web:audit` and `bun run cloudflare:dry-run`. `wrangler.jsonc` remains generic for local checks. After verification passes on `main`, GitHub Actions deploys `term.gloom.sh` with `wrangler.production.jsonc`. The private Gloom Cloud API is deployed separately.
|
|
34
50
|
|
|
35
51
|
## Install
|
|
36
52
|
|
|
@@ -41,21 +57,21 @@ Install the desktop app and the `gloomberb` terminal command:
|
|
|
41
57
|
```bash
|
|
42
58
|
brew install --cask vincelwt/tap/gloomberb
|
|
43
59
|
# or
|
|
44
|
-
curl -fsSL
|
|
60
|
+
curl -fsSL gloom.sh/install | bash
|
|
45
61
|
```
|
|
46
62
|
|
|
47
63
|
Both install `Gloomberb.app` and a `gloomberb` command that runs the TUI through the app bundle, so the bundled runtime is stored once.
|
|
48
64
|
|
|
49
65
|
Prefer a direct download?
|
|
50
66
|
|
|
51
|
-
- [Download Gloomberb for Mac](https://
|
|
67
|
+
- [Download Gloomberb for Mac](https://gloom.sh/download/desktop)
|
|
52
68
|
|
|
53
69
|
### Linux
|
|
54
70
|
|
|
55
71
|
Install the standalone TUI binary:
|
|
56
72
|
|
|
57
73
|
```bash
|
|
58
|
-
curl -fsSL
|
|
74
|
+
curl -fsSL gloom.sh/install | bash
|
|
59
75
|
```
|
|
60
76
|
|
|
61
77
|
This installs `gloomberb` to `~/.local/bin` by default. A Linux desktop package is not published yet.
|
|
@@ -150,10 +166,9 @@ Human-readable output is the default. Automation can opt into structured output
|
|
|
150
166
|
| `gloomberb portfolio [action]` | Manage manual portfolios |
|
|
151
167
|
| `gloomberb watchlist [action]` | Manage watchlists |
|
|
152
168
|
| `gloomberb notes|alerts [action]` | Manage local notes and alerts |
|
|
153
|
-
| `gloomberb broker|ibkr [action]` | Inspect broker
|
|
154
|
-
| `gloomberb ai providers|ask
|
|
169
|
+
| `gloomberb broker|ibkr [action]` | Inspect broker profiles |
|
|
170
|
+
| `gloomberb ai providers|ask` | Use configured AI providers |
|
|
155
171
|
| `gloomberb rss fetch <url>` | Fetch an RSS feed |
|
|
156
|
-
| `gloomberb buildout|congress|substack|x-feed|tweets` | Access cloud and social data sources when an existing session is available |
|
|
157
172
|
| `gloomberb provider status` | Inspect enabled data providers |
|
|
158
173
|
| `gloomberb config|cache|plugin|layout|pane|debug|doctor|version|changelog` | Inspect and manage local app state |
|
|
159
174
|
| `gloomberb fn [...]` | Run a pane-backed report command |
|
|
@@ -164,8 +179,6 @@ Human-readable output is the default. Automation can opt into structured output
|
|
|
164
179
|
| `gloomberb remove <name>` | Remove an installed plugin |
|
|
165
180
|
| `gloomberb update [name]` | Update plugins |
|
|
166
181
|
|
|
167
|
-
Commands that need a signed-in cloud session may return `auth_required`; sign-in, account management, and chat workflows are still handled in the app UI for now.
|
|
168
|
-
|
|
169
182
|
## Plugins
|
|
170
183
|
|
|
171
184
|
Everything from the portfolio list to broker integrations is a plugin. Plugins can add panes, tabs, columns, command bar commands, CLI commands, status bar widgets, and data providers.
|
|
@@ -190,7 +203,7 @@ See [PLUGINS.md](PLUGINS.md) for the plugin API and the shared UI surface availa
|
|
|
190
203
|
| `Ctrl+Shift+M` | Move focused window (`WIN resize` starts resize mode) |
|
|
191
204
|
| `Ctrl+Shift+D` | Dock or float focused pane |
|
|
192
205
|
| `Ctrl+Shift+L` | Layout actions |
|
|
193
|
-
| `Ctrl+Shift+G` |
|
|
206
|
+
| `Ctrl+Shift+G` | Tidy windows |
|
|
194
207
|
| `Tab` | Switch panes |
|
|
195
208
|
| `j` / `k` | Navigate lists |
|
|
196
209
|
| `h` / `l` | Switch tabs |
|
|
@@ -224,6 +237,7 @@ Use `HELP` inside Gloomberb for the live shortcut list. The common command-bar p
|
|
|
224
237
|
| `CMP <tickers>` | Normalized price comparison |
|
|
225
238
|
| `CORR <tickers>` | Ticker return correlations |
|
|
226
239
|
| `ANR <ticker>` | Analyst targets and ratings |
|
|
240
|
+
| `DIAG <ticker>` | Equity Diagnostic with cited flags and anomalies |
|
|
227
241
|
| `SEC <ticker>` | SEC filings and company disclosures |
|
|
228
242
|
| `OMON <ticker>` | Options monitor |
|
|
229
243
|
| `OVME` | Black-Scholes option calculator with Greeks and implied volatility |
|
|
@@ -272,6 +286,7 @@ The toolbar controls preset or exact date ranges, intervals from one minute thro
|
|
|
272
286
|
| `AUCT` | Treasury auction results: high rate, bid-to-cover, indirect share, and size |
|
|
273
287
|
| `VIX` | VIX 30-day/3-month implied-volatility curve |
|
|
274
288
|
| `CRD` | Credit spreads |
|
|
289
|
+
| `CDS [ticker]` | Single-name corporate CDS activity: most-active issuers, or one issuer's trades |
|
|
275
290
|
| `ERN` | Earnings calendar |
|
|
276
291
|
| `IPO` | Upcoming and recent IPOs |
|
|
277
292
|
| `HALT` | US trading halts with reason and resumption times |
|
|
@@ -301,16 +316,24 @@ The toolbar controls preset or exact date ranges, intervals from one minute thro
|
|
|
301
316
|
| `AW` / `AP <ticker>` | Add a ticker to the active watchlist or portfolio |
|
|
302
317
|
| `RW` / `RP <ticker>` | Remove a ticker from the active watchlist or portfolio |
|
|
303
318
|
| `PS` | Open focused pane settings |
|
|
304
|
-
| `LAY
|
|
319
|
+
| `LAY` | Open the layout browser to switch, publish, or add layouts |
|
|
320
|
+
| `LMA <query>` | Layout and pane arrangement actions |
|
|
305
321
|
| `WIN move\|resize` | Move or resize the focused window |
|
|
306
|
-
| `GL` |
|
|
322
|
+
| `GL` | Tidy all windows |
|
|
307
323
|
| `SB` | Toggle the status bar |
|
|
308
324
|
| `VF` | Toggle quote value flashing |
|
|
309
325
|
| `TH <theme>` | Change color theme |
|
|
326
|
+
| `FONT+` / `FONT-` | Increase or decrease desktop font size |
|
|
327
|
+
| `CONN` | Connection health |
|
|
328
|
+
| `POLL` | Prediction-market polls |
|
|
329
|
+
| `ART` | Loaded article lookup |
|
|
330
|
+
| `UPGRADE` | Account upgrade |
|
|
310
331
|
| `CR` | Cycle chart renderer |
|
|
311
332
|
| `LANG <locale>` | Change interface language (`auto`, `en`, `es`, `zh-CN`, `zh-TW`, `ja`, or `ko`) |
|
|
312
333
|
| `PL <plugin>` | Manage plugins |
|
|
313
334
|
|
|
335
|
+
Published layouts preserve portable pane setup and state, including searches, chart viewport, and drawings. Credentials, accounts, portfolios, and pane fields marked private stay local. Publishing copies a durable `term.gloom.sh/l/...` link for social sharing.
|
|
336
|
+
|
|
314
337
|
## Gloom Cloud sign-in
|
|
315
338
|
|
|
316
339
|
Sign in with email and password, or pick `Log In with QR Code` from the command bar and scan the code with the Gloomberb mobile companion app to sign the terminal in without typing. The onboarding wizard offers the same QR option as the recommended path, with email and password as the alternative.
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="https://
|
|
3
|
+
<img src="https://gloom.sh/gloomberb-logo-grayscale.svg" alt="Gloomberb logo" width="76" />
|
|
4
4
|
|
|
5
5
|
# Gloomberb
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
桌面应用支持 macOS 和 Windows。终端界面(TUI)支持 macOS、Linux 和 Windows。
|
|
10
10
|
|
|
11
|
-
<a href="https://
|
|
11
|
+
<a href="https://gloom.sh/download/desktop"><strong>下载桌面版</strong></a>
|
|
12
12
|
·
|
|
13
13
|
<a href="#安装">安装 TUI</a>
|
|
14
14
|
·
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<br />
|
|
18
18
|
<br />
|
|
19
19
|
|
|
20
|
-
<img src="https://
|
|
20
|
+
<img src="https://gloom.sh/landing-terminal.png" alt="Gloomberb 终端界面,显示投资组合、自选列表、市场数据和图表面板。" width="720" />
|
|
21
21
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
@@ -43,21 +43,21 @@ Gloomberb 有两种使用方式:
|
|
|
43
43
|
```bash
|
|
44
44
|
brew install --cask vincelwt/tap/gloomberb
|
|
45
45
|
# 或
|
|
46
|
-
curl -fsSL
|
|
46
|
+
curl -fsSL gloom.sh/install | bash
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
两种方式都会安装 `Gloomberb.app`,以及一个通过应用内置运行时执行 TUI 的 `gloomberb` 命令,运行时只会存储一份。
|
|
50
50
|
|
|
51
51
|
想直接下载?
|
|
52
52
|
|
|
53
|
-
- [下载 Gloomberb(Mac 版)](https://
|
|
53
|
+
- [下载 Gloomberb(Mac 版)](https://gloom.sh/download/desktop)
|
|
54
54
|
|
|
55
55
|
### Linux
|
|
56
56
|
|
|
57
57
|
安装独立的 TUI 可执行文件:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
|
-
curl -fsSL
|
|
60
|
+
curl -fsSL gloom.sh/install | bash
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
默认会将 `gloomberb` 安装到 `~/.local/bin`。Linux 桌面安装包暂未发布。
|
|
@@ -136,10 +136,9 @@ gloomberb
|
|
|
136
136
|
| `gloomberb portfolio [action]` | 管理手动投资组合 |
|
|
137
137
|
| `gloomberb watchlist [action]` | 管理自选列表 |
|
|
138
138
|
| `gloomberb notes\|alerts [action]` | 管理本地笔记与提醒 |
|
|
139
|
-
| `gloomberb broker\|ibkr [action]` |
|
|
140
|
-
| `gloomberb ai providers\|ask
|
|
139
|
+
| `gloomberb broker\|ibkr [action]` | 查看券商配置 |
|
|
140
|
+
| `gloomberb ai providers\|ask` | 使用已配置的 AI 服务商 |
|
|
141
141
|
| `gloomberb rss fetch <url>` | 抓取 RSS 订阅源 |
|
|
142
|
-
| `gloomberb buildout\|congress\|substack\|x-feed\|tweets` | 在已有会话可用时访问云端与社交数据源 |
|
|
143
142
|
| `gloomberb provider status` | 查看已启用的数据源 |
|
|
144
143
|
| `gloomberb config\|cache\|plugin\|layout\|pane\|debug\|doctor\|version\|changelog` | 查看和管理本地应用状态 |
|
|
145
144
|
| `gloomberb fn [...]` | 运行基于面板的报告命令 |
|
|
@@ -150,8 +149,6 @@ gloomberb
|
|
|
150
149
|
| `gloomberb remove <name>` | 移除已安装插件 |
|
|
151
150
|
| `gloomberb update [name]` | 更新插件 |
|
|
152
151
|
|
|
153
|
-
需要已登录云端会话的命令可能返回 `auth_required`;登录、账户管理与聊天相关操作目前仍需在应用界面中完成。
|
|
154
|
-
|
|
155
152
|
## 插件
|
|
156
153
|
|
|
157
154
|
从投资组合列表到券商集成,一切皆为插件。插件可以添加面板、页签、列、命令栏命令、CLI 命令、状态栏组件与数据源。
|
|
@@ -260,7 +257,8 @@ gloomberb
|
|
|
260
257
|
| `AW` / `AP <ticker>` | 将股票添加到活动自选列表或投资组合 |
|
|
261
258
|
| `RW` / `RP <ticker>` | 从活动自选列表或投资组合中移除股票 |
|
|
262
259
|
| `PS` | 打开聚焦面板的设置 |
|
|
263
|
-
| `LAY
|
|
260
|
+
| `LAY` | 打开布局浏览器以切换、发布或添加布局 |
|
|
261
|
+
| `LMA <query>` | 布局与面板排列操作 |
|
|
264
262
|
| `WIN move\|resize` | 移动或缩放聚焦窗口 |
|
|
265
263
|
| `GL` | 所有可见面板网格对齐 |
|
|
266
264
|
| `SB` | 切换状态栏 |
|
|
@@ -270,6 +268,8 @@ gloomberb
|
|
|
270
268
|
| `LANG <locale>` | 切换界面语言(`auto`、`en`、`es`、`zh-CN`、`zh-TW`、`ja` 或 `ko`) |
|
|
271
269
|
| `PL <plugin>` | 管理插件 |
|
|
272
270
|
|
|
271
|
+
发布的布局会保留可移植的面板设置与状态,包括搜索条件、图表视窗和绘图;凭据、账户、投资组合以及标记为私密的字段始终保留在本地。发布后会自动复制一个长期有效的 `term.gloom.sh/l/...` 社交分享链接。
|
|
272
|
+
|
|
273
273
|
## 本地化界面
|
|
274
274
|
|
|
275
275
|
Gloomberb 内置 English、简体中文、繁體中文、日本語和한국어界面支持;英文仍是默认回退语言。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gloomberb",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"packageManager": "bun@1.3.11",
|
|
5
5
|
"description": "Market research and portfolio tracker for the terminal",
|
|
6
6
|
"module": "src/index.tsx",
|
|
@@ -19,15 +19,21 @@
|
|
|
19
19
|
"build": "bun run scripts/build.ts",
|
|
20
20
|
"build:all": "bun run scripts/build.ts --all",
|
|
21
21
|
"desktop:view:build": "bun run scripts/build-electrobun-view.ts",
|
|
22
|
+
"web:build": "bun run scripts/build-web.ts",
|
|
23
|
+
"web:audit": "bun run web:build && bun run scripts/audit-web-bundle.ts",
|
|
24
|
+
"cloudflare:typecheck": "tsc --project tsconfig.cloudflare.json",
|
|
25
|
+
"cloudflare:dry-run": "bun run web:build && wrangler deploy --dry-run",
|
|
22
26
|
"desktop:dev": "bun run scripts/electrobun-dev.ts",
|
|
23
27
|
"desktop:build": "electrobun build",
|
|
24
28
|
"desktop:release": "electrobun build --env=stable",
|
|
25
29
|
"desktop:release:windows": "electrobun build --env=stable --targets=win-x64",
|
|
26
30
|
"i18n:audit": "bun run scripts/i18n-audit.ts",
|
|
27
|
-
"typecheck": "bun run typecheck:opentui && bun run typecheck:electrobun-bun && bun run typecheck:electrobun-view && bun run typecheck:scripts",
|
|
31
|
+
"typecheck": "bun run typecheck:opentui && bun run typecheck:electrobun-bun && bun run typecheck:electrobun-view && bun run typecheck:browser && bun run typecheck:cloudflare && bun run typecheck:scripts",
|
|
28
32
|
"typecheck:opentui": "tsc --project tsconfig.opentui.json",
|
|
29
33
|
"typecheck:electrobun-bun": "tsc --project tsconfig.electrobun-bun.json",
|
|
30
34
|
"typecheck:electrobun-view": "tsc --project tsconfig.electrobun-view.json",
|
|
35
|
+
"typecheck:browser": "tsc --project tsconfig.browser.json",
|
|
36
|
+
"typecheck:cloudflare": "tsc --project tsconfig.cloudflare.json",
|
|
31
37
|
"typecheck:scripts": "tsc --project tsconfig.scripts.json",
|
|
32
38
|
"test": "bun test",
|
|
33
39
|
"test:global-upgrade": "bun run scripts/smoke-global-upgrade.ts",
|
|
@@ -52,7 +58,8 @@
|
|
|
52
58
|
"electrobun": "^1.18.1",
|
|
53
59
|
"happy-dom": "^20.11.1",
|
|
54
60
|
"png-to-ico": "^2.1.8",
|
|
55
|
-
"rcedit": "^4.0.1"
|
|
61
|
+
"rcedit": "^4.0.1",
|
|
62
|
+
"wrangler": "^4.0.0"
|
|
56
63
|
},
|
|
57
64
|
"peerDependencies": {
|
|
58
65
|
"typescript": "^5.9.2"
|
package/src/api-client/auth.ts
CHANGED
|
@@ -18,6 +18,7 @@ type CloudApiRequest = <T>(path: string, options?: RequestInit) => Promise<T>;
|
|
|
18
18
|
interface CloudAuthApiOptions {
|
|
19
19
|
getCurrentUser(): AuthUser | null;
|
|
20
20
|
getSessionToken(): string | null;
|
|
21
|
+
hasSessionCredential(): boolean;
|
|
21
22
|
request: CloudApiRequest;
|
|
22
23
|
requireCapturedSession(message: string): void;
|
|
23
24
|
setCurrentUser(user: AuthUser | null): void;
|
|
@@ -29,7 +30,7 @@ export class CloudAuthApi {
|
|
|
29
30
|
constructor(private readonly options: CloudAuthApiOptions) {}
|
|
30
31
|
|
|
31
32
|
restoreCachedUser(user: PersistedAuthUser | null): void {
|
|
32
|
-
if (!this.options.
|
|
33
|
+
if (!this.options.hasSessionCredential() || !user?.id) {
|
|
33
34
|
this.options.setCurrentUser(null);
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
@@ -56,15 +57,6 @@ export class CloudAuthApi {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
async ensureVerifiedSession(): Promise<AuthUser | null> {
|
|
60
|
-
if (!this.options.getSessionToken()) return null;
|
|
61
|
-
if (!this.options.getCurrentUser()) {
|
|
62
|
-
await this.getSession();
|
|
63
|
-
}
|
|
64
|
-
const user = this.options.getCurrentUser();
|
|
65
|
-
return user?.emailVerified ? user : null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
60
|
async signUp(email: string, username: string, name: string, password: string): Promise<AuthUser> {
|
|
69
61
|
const result = await this.options.request<{ user: AuthUser }>("/auth/sign-up/email", {
|
|
70
62
|
method: "POST",
|
|
@@ -134,6 +126,18 @@ export class CloudAuthApi {
|
|
|
134
126
|
}
|
|
135
127
|
}
|
|
136
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Emails a password reset link. The reset itself completes on the gloom.sh
|
|
131
|
+
* site, so the app only ever sends the email. The server answers the same
|
|
132
|
+
* way whether or not the address exists.
|
|
133
|
+
*/
|
|
134
|
+
async requestPasswordReset(email: string): Promise<void> {
|
|
135
|
+
await this.options.request("/auth/request-password-reset", {
|
|
136
|
+
method: "POST",
|
|
137
|
+
body: JSON.stringify({ email }),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
137
141
|
async sendVerification(): Promise<CloudVerificationResponse> {
|
|
138
142
|
return this.options.request<CloudVerificationResponse>("/cloud/auth/send-verification", {
|
|
139
143
|
method: "POST",
|
package/src/api-client/data.ts
CHANGED
|
@@ -2,8 +2,13 @@ import type { TickerFinancials } from "../types/financials";
|
|
|
2
2
|
import type { InstrumentSearchResult } from "../types/instrument";
|
|
3
3
|
import { normalizeTweetSearchResponse } from "./normalizers";
|
|
4
4
|
import {
|
|
5
|
+
cloudCdsPath,
|
|
5
6
|
cloudCongressHousePath,
|
|
6
7
|
cloudExchangeRatePath,
|
|
8
|
+
cloudSec13FPath,
|
|
9
|
+
cloudSecFilingContentPath,
|
|
10
|
+
cloudSecFilingDocumentsPath,
|
|
11
|
+
cloudSecFilingsPath,
|
|
7
12
|
cloudFredSeriesPath,
|
|
8
13
|
cloudHistoryPath,
|
|
9
14
|
cloudMarketSearchPath,
|
|
@@ -13,20 +18,26 @@ import {
|
|
|
13
18
|
cloudStatementsPath,
|
|
14
19
|
cloudTickerTweetsPath,
|
|
15
20
|
cloudTweetSearchPath,
|
|
21
|
+
type CloudCdsParams,
|
|
16
22
|
type CloudCongressHouseParams,
|
|
17
23
|
type CloudFredSeriesParams,
|
|
18
24
|
type CloudHistoryParams,
|
|
19
25
|
type CloudNewsParams,
|
|
26
|
+
type CloudSecFilingParams,
|
|
27
|
+
type CloudSecFilingsParams,
|
|
20
28
|
type CloudTickerTweetsParams,
|
|
21
29
|
type CloudTweetSearchParams,
|
|
22
30
|
} from "./paths";
|
|
23
31
|
import type {
|
|
24
32
|
CloudAnalystResearchPayload,
|
|
25
33
|
CloudShortInterestPayload,
|
|
34
|
+
CloudCdsResponse,
|
|
26
35
|
CloudCompanyProfile,
|
|
27
36
|
CloudCongressHousePayload,
|
|
28
37
|
CloudCorporateActionsPayload,
|
|
29
38
|
CloudEconEventPayload,
|
|
39
|
+
CloudEquityDiagnosticMode,
|
|
40
|
+
CloudEquityDiagnosticResult,
|
|
30
41
|
CloudFredSeriesPayload,
|
|
31
42
|
CloudFundamentals,
|
|
32
43
|
CloudHoldersPayload,
|
|
@@ -37,6 +48,9 @@ import type {
|
|
|
37
48
|
CloudMarketScreenerPayload,
|
|
38
49
|
CloudNewsListResponse,
|
|
39
50
|
CloudNewsPayload,
|
|
51
|
+
CloudSecContentResponse,
|
|
52
|
+
CloudSecDocumentsResponse,
|
|
53
|
+
CloudSecFilingsResponse,
|
|
40
54
|
CloudOptionsChainPayload,
|
|
41
55
|
CloudPricePointPayload,
|
|
42
56
|
CloudQuotePayload,
|
|
@@ -163,6 +177,26 @@ export class CloudDataApi {
|
|
|
163
177
|
return this.request<CloudMarketResponse<{ rate: number }>>(cloudExchangeRatePath(fromCurrency));
|
|
164
178
|
}
|
|
165
179
|
|
|
180
|
+
/**
|
|
181
|
+
* On-demand single-company evidence review. This is a cloud product endpoint,
|
|
182
|
+
* not a market-data capability, so it is called directly instead of routed
|
|
183
|
+
* through the asset-data provider.
|
|
184
|
+
*/
|
|
185
|
+
async getCloudEquityDiagnostic(
|
|
186
|
+
symbol: string,
|
|
187
|
+
exchange?: string,
|
|
188
|
+
mode: CloudEquityDiagnosticMode = "cache-first",
|
|
189
|
+
): Promise<CloudEquityDiagnosticResult> {
|
|
190
|
+
return this.request<CloudEquityDiagnosticResult>("/research/equity-diagnostic", {
|
|
191
|
+
method: "POST",
|
|
192
|
+
body: JSON.stringify({
|
|
193
|
+
symbol: symbol.trim().toUpperCase(),
|
|
194
|
+
...(exchange ? { exchange } : {}),
|
|
195
|
+
mode,
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
166
200
|
async getCloudEconomicCalendar(): Promise<CloudEconEventPayload[]> {
|
|
167
201
|
return this.request<CloudEconEventPayload[]>("/cloud/econ/calendar");
|
|
168
202
|
}
|
|
@@ -178,10 +212,30 @@ export class CloudDataApi {
|
|
|
178
212
|
return this.request<CloudYieldPointPayload[]>("/cloud/econ/yield-curve");
|
|
179
213
|
}
|
|
180
214
|
|
|
215
|
+
async getCloudCds(params: CloudCdsParams = {}): Promise<CloudCdsResponse> {
|
|
216
|
+
return this.request<CloudCdsResponse>(cloudCdsPath(params));
|
|
217
|
+
}
|
|
218
|
+
|
|
181
219
|
async getCloudCongressHouse(params: CloudCongressHouseParams = {}): Promise<CloudCongressHousePayload> {
|
|
182
220
|
return this.request<CloudCongressHousePayload>(cloudCongressHousePath(params));
|
|
183
221
|
}
|
|
184
222
|
|
|
223
|
+
async getCloudSecFilings(params: CloudSecFilingsParams): Promise<CloudSecFilingsResponse> {
|
|
224
|
+
return this.request<CloudSecFilingsResponse>(cloudSecFilingsPath(params));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async getCloudSecFilingDocuments(params: CloudSecFilingParams): Promise<CloudSecDocumentsResponse> {
|
|
228
|
+
return this.request<CloudSecDocumentsResponse>(cloudSecFilingDocumentsPath(params));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async getCloudSecFilingContent(params: CloudSecFilingParams): Promise<CloudSecContentResponse> {
|
|
232
|
+
return this.request<CloudSecContentResponse>(cloudSecFilingContentPath(params));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async getCloudSec13F(path: string, params: Record<string, string | number | undefined> = {}): Promise<unknown> {
|
|
236
|
+
return this.request<unknown>(cloudSec13FPath(path, params));
|
|
237
|
+
}
|
|
238
|
+
|
|
185
239
|
async getCloudNews(params: CloudNewsParams = {}): Promise<CloudNewsListResponse> {
|
|
186
240
|
return this.request<CloudNewsListResponse>(cloudNewsPath(params));
|
|
187
241
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { afterEach, describe, expect, jest, test } from "bun:test";
|
|
2
2
|
import type { AuthUser } from "./index";
|
|
3
3
|
import { apiClient, setCloudApiFetchTransport } from "./index";
|
|
4
|
+
import { publishableMarketplaceLayout } from "../layout-marketplace/payload";
|
|
5
|
+
import { createDefaultConfig } from "../types/config";
|
|
6
|
+
import type { PaneDef } from "../types/plugin";
|
|
4
7
|
|
|
5
8
|
const originalFetch = globalThis.fetch;
|
|
6
9
|
const originalWebSocket = globalThis.WebSocket;
|
|
@@ -104,10 +107,97 @@ afterEach(() => {
|
|
|
104
107
|
setCloudApiFetchTransport(null);
|
|
105
108
|
apiClient.setSessionToken(null);
|
|
106
109
|
apiClient.setWebSocketToken(null);
|
|
110
|
+
apiClient.setCookieSessionMode(false);
|
|
107
111
|
jest.useRealTimers();
|
|
108
112
|
});
|
|
109
113
|
|
|
114
|
+
describe("apiClient layout marketplace", () => {
|
|
115
|
+
test("lists and publishes validated layouts through authenticated transport", async () => {
|
|
116
|
+
const config = createDefaultConfig("/tmp/api-layout-marketplace-test");
|
|
117
|
+
const panes = new Map(config.layout.instances.map((instance) => [instance.paneId, {
|
|
118
|
+
id: instance.paneId,
|
|
119
|
+
name: instance.paneId,
|
|
120
|
+
component: () => null,
|
|
121
|
+
defaultPosition: "right" as const,
|
|
122
|
+
} satisfies PaneDef]));
|
|
123
|
+
const payload = publishableMarketplaceLayout(config.layout, {}, panes);
|
|
124
|
+
const entry = {
|
|
125
|
+
id: "0123456789abcdef0123456789abcdef",
|
|
126
|
+
name: "Research Desk",
|
|
127
|
+
...payload,
|
|
128
|
+
author: { username: "analyst", displayName: "Analyst" },
|
|
129
|
+
publishedAt: "2026-08-26T00:00:00.000Z",
|
|
130
|
+
};
|
|
131
|
+
const calls: Array<{ url: string; method: string; body?: unknown }> = [];
|
|
132
|
+
apiClient.setSessionToken("marketplace-session");
|
|
133
|
+
setCloudApiFetchTransport(async (url, init) => {
|
|
134
|
+
calls.push({
|
|
135
|
+
url,
|
|
136
|
+
method: init?.method ?? "GET",
|
|
137
|
+
...(typeof init?.body === "string" ? { body: JSON.parse(init.body) } : {}),
|
|
138
|
+
});
|
|
139
|
+
const path = new URL(url).pathname;
|
|
140
|
+
return createResponse(path === `/layouts/${entry.id}` || init?.method === "POST"
|
|
141
|
+
? entry
|
|
142
|
+
: { items: [entry] });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await expect(apiClient.listMarketplaceLayouts()).resolves.toEqual([entry]);
|
|
146
|
+
await expect(apiClient.getMarketplaceLayout(entry.id)).resolves.toEqual(entry);
|
|
147
|
+
await expect(apiClient.publishMarketplaceLayout(entry.name, payload)).resolves.toEqual(entry);
|
|
148
|
+
|
|
149
|
+
expect(calls.map((call) => [new URL(call.url).pathname, call.method])).toEqual([
|
|
150
|
+
["/layouts", "GET"],
|
|
151
|
+
[`/layouts/${entry.id}`, "GET"],
|
|
152
|
+
["/layouts", "POST"],
|
|
153
|
+
]);
|
|
154
|
+
expect(calls[2]?.body).toMatchObject({ name: "Research Desk", schemaVersion: 2, paneState: {} });
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
110
158
|
describe("apiClient auth cookies", () => {
|
|
159
|
+
test("accepts a browser-managed api.gloom.sh cookie without exposing its value", async () => {
|
|
160
|
+
apiClient.setCookieSessionMode(true);
|
|
161
|
+
setCloudApiFetchTransport(mockFetch(() => createResponse({ user: verifiedUser })));
|
|
162
|
+
|
|
163
|
+
await expect(apiClient.signIn("test@example.com", "password")).resolves.toEqual(verifiedUser);
|
|
164
|
+
expect(apiClient.getSessionToken()).toBeNull();
|
|
165
|
+
expect(apiClient.isVerified()).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("reports signed-in from the restored user when the cookie hides the raw token", async () => {
|
|
169
|
+
apiClient.setCookieSessionMode(true);
|
|
170
|
+
setCloudApiFetchTransport(mockFetch(() => createResponse({ user: verifiedUser })));
|
|
171
|
+
|
|
172
|
+
expect(apiClient.isSignedIn()).toBe(false);
|
|
173
|
+
await apiClient.signIn("test@example.com", "password");
|
|
174
|
+
expect(apiClient.getSessionToken()).toBeNull();
|
|
175
|
+
expect(apiClient.isSignedIn()).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("coalesces anonymous browser session checks and remembers the result", async () => {
|
|
179
|
+
apiClient.setCookieSessionMode(true);
|
|
180
|
+
let requests = 0;
|
|
181
|
+
let finishRequest!: () => void;
|
|
182
|
+
setCloudApiFetchTransport(async () => {
|
|
183
|
+
requests += 1;
|
|
184
|
+
await new Promise<void>((resolve) => { finishRequest = resolve; });
|
|
185
|
+
return createResponse({ user: null });
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const checks = [
|
|
189
|
+
apiClient.ensureVerifiedSession(),
|
|
190
|
+
apiClient.ensureVerifiedSession(),
|
|
191
|
+
apiClient.ensureVerifiedSession(),
|
|
192
|
+
];
|
|
193
|
+
expect(requests).toBe(1);
|
|
194
|
+
finishRequest();
|
|
195
|
+
|
|
196
|
+
await expect(Promise.all(checks)).resolves.toEqual([null, null, null]);
|
|
197
|
+
await expect(apiClient.ensureVerifiedSession()).resolves.toBeNull();
|
|
198
|
+
expect(requests).toBe(1);
|
|
199
|
+
});
|
|
200
|
+
|
|
111
201
|
test("captures secure session cookies after login and reuses them on session refresh", async () => {
|
|
112
202
|
const seenCookies: Array<string | null> = [];
|
|
113
203
|
|
|
@@ -1039,3 +1129,37 @@ describe("apiClient cloud news", () => {
|
|
|
1039
1129
|
expect(story.id).toBe("story-1");
|
|
1040
1130
|
});
|
|
1041
1131
|
});
|
|
1132
|
+
|
|
1133
|
+
describe("apiClient equity diagnostic", () => {
|
|
1134
|
+
test("posts the symbol, exchange, and cache mode to the research route", async () => {
|
|
1135
|
+
let seenUrl = "";
|
|
1136
|
+
let seenInit: RequestInit | undefined;
|
|
1137
|
+
globalThis.fetch = mockFetch(async (input: Request | string | URL, init?: RequestInit) => {
|
|
1138
|
+
seenUrl = String(input);
|
|
1139
|
+
seenInit = init;
|
|
1140
|
+
return createResponse({ symbol: "AAPL", status: "complete" });
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
await apiClient.getCloudEquityDiagnostic(" aapl ", "NASDAQ", "refresh");
|
|
1144
|
+
|
|
1145
|
+
expect(new URL(seenUrl).pathname).toBe("/research/equity-diagnostic");
|
|
1146
|
+
expect(seenInit?.method).toBe("POST");
|
|
1147
|
+
expect(JSON.parse(String(seenInit?.body))).toEqual({
|
|
1148
|
+
symbol: "AAPL",
|
|
1149
|
+
exchange: "NASDAQ",
|
|
1150
|
+
mode: "refresh",
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
test("omits an unknown exchange and defaults to the cached answer", async () => {
|
|
1155
|
+
let seenInit: RequestInit | undefined;
|
|
1156
|
+
globalThis.fetch = mockFetch(async (_input: Request | string | URL, init?: RequestInit) => {
|
|
1157
|
+
seenInit = init;
|
|
1158
|
+
return createResponse({ symbol: "AAPL", status: "complete" });
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
await apiClient.getCloudEquityDiagnostic("AAPL");
|
|
1162
|
+
|
|
1163
|
+
expect(JSON.parse(String(seenInit?.body))).toEqual({ symbol: "AAPL", mode: "cache-first" });
|
|
1164
|
+
});
|
|
1165
|
+
});
|