gloomberb 0.18.2 → 0.18.4
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 +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/patches/electrobun@1.18.1.patch +106 -5
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +99 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +24 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +26 -7
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/telemetry.ts +17 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/global-shortcuts.ts +1 -16
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/runtime/update.ts +28 -8
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1189 -296
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +272 -70
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +20 -14
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +32 -18
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +315 -43
- package/src/cli/name-entries.ts +73 -22
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +77 -20
- package/src/cli/pane-functions/catalog.ts +40 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +12 -8
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +48 -16
- package/src/cli/pane-functions/index.ts +82 -21
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +65 -14
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +190 -27
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +122 -25
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +226 -60
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +387 -21
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/interactions.ts +9 -3
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +316 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +19 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/command-items.ts +32 -6
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/data-table/view.tsx +23 -3
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +13 -6
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +234 -60
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +3 -1
- package/src/core/app-services.ts +4 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +51 -12
- package/src/i18n/ja.ts +51 -12
- package/src/i18n/ko.ts +51 -12
- package/src/i18n/zh-cn.ts +51 -12
- package/src/i18n/zh-tw.ts +51 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +108 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +77 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
- package/src/plugins/builtin/attention/pane.tsx +22 -16
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +12 -9
- package/src/plugins/builtin/backtest/export.ts +1 -1
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/client.ts +2 -2
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +9 -11
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
- package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +89 -31
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +7 -4
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +7 -5
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +19 -12
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +77 -5
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +34 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +16 -10
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +15 -2
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +48 -8
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/base-values.ts +11 -7
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +20 -7
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +3 -3
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +14 -8
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +36 -21
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +33 -11
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +50 -15
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +51 -23
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +142 -29
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +49 -21
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +6 -3
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +44 -32
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/seasonality/client.ts +2 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +6 -4
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +23 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/volatility/options.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/social-mentions/client.ts +2 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +28 -7
- package/src/plugins/builtin/vol-surface/headless.ts +43 -15
- package/src/plugins/builtin/vol-surface/model.ts +34 -12
- package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/desktop/controls.tsx +1 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/tabs.tsx +16 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +115 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +9 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +8 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +39 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/index.ts +16 -0
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +21 -4
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +215 -36
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-fate.ts +30 -0
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +20 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +83 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/issuer-listings.ts +28 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/failure.ts +163 -0
- package/src/updater/index.ts +97 -28
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-pair.ts +26 -0
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +71 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
type PaneHint,
|
|
23
23
|
} from "../../../components";
|
|
24
24
|
import { loadingErrorFooterInfo } from "../../../components/data-table/table-pane";
|
|
25
|
+
import { useRowNotes } from "../../../components/ui/row-notes";
|
|
25
26
|
import { colors } from "../../../theme/colors";
|
|
26
27
|
import { t, tf } from "../../../i18n";
|
|
27
28
|
import type { PaneProps } from "../../../types/plugin";
|
|
@@ -31,6 +32,7 @@ import { isPlainKeyboardEvent } from "../../../utils/keyboard";
|
|
|
31
32
|
import { formatRelativeAge } from "../../../utils/datetime-format";
|
|
32
33
|
import { displayWidth } from "../../../utils/format";
|
|
33
34
|
import { requiredGloomberb } from "../../../utils/semver";
|
|
35
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
34
36
|
import { VERSION } from "../../../version";
|
|
35
37
|
import { getCurrentPluginTarget, runsExternalPlugins } from "../../current-target";
|
|
36
38
|
import { pluginSetupCommandId } from "../../registry/setup-command";
|
|
@@ -67,6 +69,7 @@ import {
|
|
|
67
69
|
versionLabel,
|
|
68
70
|
type MarketplaceEntry,
|
|
69
71
|
type MarketplaceRow,
|
|
72
|
+
type MarketplaceStatus,
|
|
70
73
|
type MarketplaceStatusKind,
|
|
71
74
|
type RegistryPlugin,
|
|
72
75
|
} from "../../marketplace/model";
|
|
@@ -164,7 +167,7 @@ function renderCell(
|
|
|
164
167
|
row: MarketplaceRow,
|
|
165
168
|
column: Column,
|
|
166
169
|
rowState: { selected: boolean },
|
|
167
|
-
|
|
170
|
+
rowStatus: (entry: MarketplaceEntry) => MarketplaceStatus,
|
|
168
171
|
facts: (entry: MarketplaceEntry) => EntryFacts,
|
|
169
172
|
): DataTableCell {
|
|
170
173
|
if (row.type === "header") return { text: "" };
|
|
@@ -191,8 +194,7 @@ function renderCell(
|
|
|
191
194
|
case "tagline":
|
|
192
195
|
return { text: entry.tagline, color: selected ?? colors.textDim };
|
|
193
196
|
case "status": {
|
|
194
|
-
|
|
195
|
-
const status = statusOf(entry);
|
|
197
|
+
const status = rowStatus(entry);
|
|
196
198
|
return { text: status.text, color: selected ?? STATUS_COLORS[status.kind] };
|
|
197
199
|
}
|
|
198
200
|
}
|
|
@@ -211,14 +213,21 @@ function describeContributions(entry: MarketplaceEntry, host: MarketplaceHost |
|
|
|
211
213
|
return parts;
|
|
212
214
|
}
|
|
213
215
|
|
|
214
|
-
function EntryDetail({ entry, width, host
|
|
216
|
+
function EntryDetail({ entry, width, host, status, failure }: {
|
|
217
|
+
entry: MarketplaceEntry;
|
|
218
|
+
width: number;
|
|
219
|
+
host: MarketplaceHost | null;
|
|
220
|
+
/** The row's STATUS. */
|
|
221
|
+
status: MarketplaceStatus;
|
|
222
|
+
/** What the last action on this plugin ran into, said in full. */
|
|
223
|
+
failure: ActionFailure | null;
|
|
224
|
+
}) {
|
|
215
225
|
const contributes = describeContributions(entry, host);
|
|
216
226
|
const live = entry.installed && host ? host.contributions(entry.id) : null;
|
|
217
227
|
const opensWith = live
|
|
218
228
|
? live.templates.map((template) => template.prefix ?? template.label).filter(Boolean)
|
|
219
229
|
: [];
|
|
220
230
|
const rowWidth = Math.max(1, width - 2);
|
|
221
|
-
const status = statusOf(entry);
|
|
222
231
|
|
|
223
232
|
return (
|
|
224
233
|
<ScrollBox flexDirection="column" width={width} flexGrow={1} flexBasis={0} minHeight={0} paddingLeft={1} paddingRight={1} scrollY focusable={false}>
|
|
@@ -235,6 +244,12 @@ function EntryDetail({ entry, width, host }: { entry: MarketplaceEntry; width: n
|
|
|
235
244
|
</Box>
|
|
236
245
|
) : null}
|
|
237
246
|
|
|
247
|
+
{failure ? (
|
|
248
|
+
<Box paddingTop={1} flexDirection="column">
|
|
249
|
+
<Text fg={STATUS_COLORS[failure.kind ?? "failed"]} wrapText>{failure.text}</Text>
|
|
250
|
+
</Box>
|
|
251
|
+
) : null}
|
|
252
|
+
|
|
238
253
|
<Box paddingTop={1} flexDirection="column">
|
|
239
254
|
{contributes.length > 0 ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Adds" value={contributes.join(", ")} /> : null}
|
|
240
255
|
{opensWith.length > 0 ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Opens with" value={opensWith.join(", ")} /> : null}
|
|
@@ -245,7 +260,7 @@ function EntryDetail({ entry, width, host }: { entry: MarketplaceEntry; width: n
|
|
|
245
260
|
*/}
|
|
246
261
|
{entry.hosts.length > 0 ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Declares" value={entry.hosts.join(", ")} /> : null}
|
|
247
262
|
{entry.repo ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Source" value={`github.com/${entry.repo}`} /> : null}
|
|
248
|
-
{entry.minGloomberb ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Requires" value={requiredGloomberb(entry.minGloomberb) ? `
|
|
263
|
+
{entry.minGloomberb ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Requires" value={requiredGloomberb(entry.minGloomberb) ? `Gloom ${entry.minGloomberb}, this is ${VERSION}` : `Gloom ${entry.minGloomberb}`} /> : null}
|
|
249
264
|
{entry.linked ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Linked" value={entry.directory ?? "local checkout"} /> : null}
|
|
250
265
|
{entry.installedCommit ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Commit" value={entry.installedCommit.slice(0, 7)} /> : null}
|
|
251
266
|
{!entry.installed && entry.availableCommit ? <KeyValueRow labelWidth={10} width={rowWidth} emphasis={false} label="Pinned" value={`${entry.availableVersion ?? ""} ${entry.availableCommit.slice(0, 7)}`.trim()} /> : null}
|
|
@@ -258,7 +273,7 @@ function EntryDetail({ entry, width, host }: { entry: MarketplaceEntry; width: n
|
|
|
258
273
|
runsExternalPlugins() ? (
|
|
259
274
|
<Box paddingTop={1} flexDirection="column">
|
|
260
275
|
<Text fg={colors.textDim}>Runs with your full permissions. Read the source first.</Text>
|
|
261
|
-
<Text fg={colors.textBright}>{`
|
|
276
|
+
<Text fg={colors.textBright}>{`gloom install ${entry.repo}`}</Text>
|
|
262
277
|
</Box>
|
|
263
278
|
) : (
|
|
264
279
|
// No shell here, so the install command would be a dead end. Say
|
|
@@ -320,7 +335,7 @@ function BuiltinDetail({ entry, width, facts, scrollRef }: {
|
|
|
320
335
|
<RemoteImage
|
|
321
336
|
key={code}
|
|
322
337
|
src={functionShotUrl(code)}
|
|
323
|
-
alt={`${code} in
|
|
338
|
+
alt={`${code} in Gloom`}
|
|
324
339
|
label={code}
|
|
325
340
|
width={shotWidth}
|
|
326
341
|
height={Math.max(8, Math.floor(shotWidth * 0.3))}
|
|
@@ -399,6 +414,25 @@ function PackChangeBody({ change, name }: { change: PackChange; name: (id: strin
|
|
|
399
414
|
|
|
400
415
|
type Busy = { id: string; verb: "installing" | "updating" | "removing" } | null;
|
|
401
416
|
|
|
417
|
+
/**
|
|
418
|
+
* What the last action on one plugin ran into, said on its row: `status` in
|
|
419
|
+
* STATUS, `text` in its detail. It stands while the row's own status is what
|
|
420
|
+
* it was when the failure first showed, and goes when that moves: a toggle,
|
|
421
|
+
* a restart, a later install.
|
|
422
|
+
*/
|
|
423
|
+
interface ActionFailure {
|
|
424
|
+
status: string;
|
|
425
|
+
text: string;
|
|
426
|
+
/** STATUS's tone; a failure by default. */
|
|
427
|
+
kind?: MarketplaceStatusKind;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function statusKey(entry: MarketplaceEntry): string {
|
|
431
|
+
const status = statusOf(entry);
|
|
432
|
+
return `${status.kind}:${status.text}`;
|
|
433
|
+
}
|
|
434
|
+
const entryId = (entry: MarketplaceEntry) => entry.id;
|
|
435
|
+
|
|
402
436
|
export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
403
437
|
const dialog = useDialog();
|
|
404
438
|
const { createPaneFromTemplate, showPane, openPluginCommandWorkflow, notify } = usePluginAppActions();
|
|
@@ -418,14 +452,15 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
418
452
|
// Bumped after any local change so the list is re-read from the host.
|
|
419
453
|
const [localRevision, setLocalRevision] = useState(0);
|
|
420
454
|
const [busy, setBusy] = useState<Busy>(null);
|
|
421
|
-
const [lastError, setLastError] = useState<string | null>(null);
|
|
422
455
|
// Remote heads for plugins the registry does not pin, so a private or
|
|
423
456
|
// side-loaded install can report an update like every other row.
|
|
424
457
|
const [remoteHeads, setRemoteHeads] = useState<Record<string, string>>({});
|
|
425
458
|
const [checkingRemotes, setCheckingRemotes] = useState(false);
|
|
426
|
-
const
|
|
459
|
+
const [remoteCheckError, setRemoteCheckError] = useState<string | null>(null);
|
|
460
|
+
const [remoteRevision, setRemoteRevision] = useState(0);
|
|
427
461
|
|
|
428
462
|
const refresh = useCallback((force: boolean) => {
|
|
463
|
+
if (force) setRemoteRevision((value) => value + 1);
|
|
429
464
|
setStatus((current) => (current === "ready" ? current : "loading"));
|
|
430
465
|
void loadRegistry({ force }).then((result) => {
|
|
431
466
|
setRegistry(result.plugins);
|
|
@@ -460,12 +495,22 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
460
495
|
return facts;
|
|
461
496
|
};
|
|
462
497
|
}, [entries, host]);
|
|
498
|
+
// By plugin id, until the next action on the plugin. A failure takes the
|
|
499
|
+
// row's status as the list shows it after the action, and goes once that
|
|
500
|
+
// status moves on.
|
|
501
|
+
const { noteFor: failureFor, setNote: setFailure } = useRowNotes<MarketplaceEntry, ActionFailure>(entries, { key: entryId, signature: statusKey });
|
|
502
|
+
// What an action on one plugin is doing, or ran into, is said on its row.
|
|
503
|
+
const rowStatus = useCallback((entry: MarketplaceEntry): MarketplaceStatus => {
|
|
504
|
+
if (busy?.id === entry.id) return { kind: "none", text: busy.verb };
|
|
505
|
+
const failure = failureFor(entry);
|
|
506
|
+
return failure ? { kind: failure.kind ?? "failed", text: failure.status } : statusOf(entry);
|
|
507
|
+
}, [busy, failureFor]);
|
|
463
508
|
const renderRow = useCallback((
|
|
464
509
|
row: MarketplaceRow,
|
|
465
510
|
column: Column,
|
|
466
511
|
_index: number,
|
|
467
512
|
rowState: { selected: boolean },
|
|
468
|
-
) => renderCell(row, column, rowState,
|
|
513
|
+
) => renderCell(row, column, rowState, rowStatus, factsFor), [factsFor, rowStatus]);
|
|
469
514
|
|
|
470
515
|
// Keyed by the folders themselves: the entries array is rebuilt whenever an
|
|
471
516
|
// answer lands, and re-running the check on its own result would never stop.
|
|
@@ -476,24 +521,42 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
476
521
|
const unlistedKey = unlistedDirectories.join(",");
|
|
477
522
|
|
|
478
523
|
useEffect(() => {
|
|
524
|
+
const directories = unlistedKey ? unlistedKey.split(",") : [];
|
|
525
|
+
const eligible = new Set(directories);
|
|
526
|
+
// Forget removed or newly pinned/linked installs, including the last one.
|
|
527
|
+
setRemoteHeads((previous) => {
|
|
528
|
+
const retained = Object.entries(previous).filter(([directory]) => eligible.has(directory));
|
|
529
|
+
return retained.length === Object.keys(previous).length ? previous : Object.fromEntries(retained);
|
|
530
|
+
});
|
|
531
|
+
setRemoteCheckError(null);
|
|
479
532
|
const check = manager?.remoteHeads;
|
|
480
|
-
if (!check ||
|
|
533
|
+
if (!check || directories.length === 0) {
|
|
534
|
+
setCheckingRemotes(false);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
481
537
|
let cancelled = false;
|
|
482
538
|
setCheckingRemotes(true);
|
|
483
|
-
void
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
.catch(() => ({}))
|
|
487
|
-
.then((heads) => {
|
|
539
|
+
void (async () => {
|
|
540
|
+
try {
|
|
541
|
+
const heads = await check(directories);
|
|
488
542
|
if (cancelled) return;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
543
|
+
// An omitted folder is unanswered, not proof that it is up to date.
|
|
544
|
+
const answers = directories.filter((directory) => !!heads[directory]);
|
|
545
|
+
setRemoteHeads((previous) => ({
|
|
546
|
+
...previous,
|
|
547
|
+
...Object.fromEntries(answers.map((directory) => [directory, heads[directory]!])),
|
|
548
|
+
}));
|
|
549
|
+
setRemoteCheckError(answers.length < directories.length ? "Update check incomplete" : null);
|
|
550
|
+
} catch (error) {
|
|
551
|
+
if (cancelled) return;
|
|
552
|
+
logFailure("plugin-marketplace.pane", "Check installed plugin remote heads failed")(error);
|
|
553
|
+
setRemoteCheckError("Plugin update check failed");
|
|
554
|
+
} finally {
|
|
555
|
+
if (!cancelled) setCheckingRemotes(false);
|
|
556
|
+
}
|
|
557
|
+
})();
|
|
558
|
+
return () => { cancelled = true; };
|
|
559
|
+
}, [manager, unlistedKey, localRevision, remoteRevision]);
|
|
497
560
|
|
|
498
561
|
const visible = useMemo(
|
|
499
562
|
() => filterEntries(entries, { query, category, showBuiltin }),
|
|
@@ -545,16 +608,23 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
545
608
|
/**
|
|
546
609
|
* The registry's code for this plugin needs a newer Gloomberb. Installing or
|
|
547
610
|
* updating would land it anyway and it would then fail to compile, so say
|
|
548
|
-
* what to do instead
|
|
549
|
-
*
|
|
550
|
-
*
|
|
611
|
+
* what to do instead, on the row: its STATUS already says `needs …` unless
|
|
612
|
+
* something outranks it there (`failed`, `needs restart`). Also leaves a
|
|
613
|
+
* working older checkout alone, and does not update one that already needs
|
|
614
|
+
* a newer Gloomberb: updates only move forward, so that would not help either.
|
|
551
615
|
*/
|
|
552
616
|
const refuseTooNew = useCallback((entry: MarketplaceEntry): boolean => {
|
|
553
617
|
const required = requiredGloomberb(entry.minGloomberb) ?? entry.needsGloomberb;
|
|
554
618
|
if (!required) return false;
|
|
555
|
-
|
|
619
|
+
if (statusOf(entry).kind !== "needs-gloomberb") {
|
|
620
|
+
setFailure(entry.id, {
|
|
621
|
+
kind: "needs-gloomberb",
|
|
622
|
+
status: `needs ${required}`,
|
|
623
|
+
text: `${entry.name} needs Gloom ${required}. Update Gloom first.`,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
556
626
|
return true;
|
|
557
|
-
}, [
|
|
627
|
+
}, [setFailure]);
|
|
558
628
|
|
|
559
629
|
const installSelected = useCallback(async () => {
|
|
560
630
|
if (!selected || !isInstallable(selected) || !manager || !host || busy) return;
|
|
@@ -576,12 +646,11 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
576
646
|
|
|
577
647
|
const entry = selected;
|
|
578
648
|
setBusy({ id: entry.id, verb: "installing" });
|
|
579
|
-
|
|
649
|
+
setFailure(entry.id, null);
|
|
580
650
|
const result = await manager.install(repo, pin);
|
|
581
651
|
if (!result.ok) {
|
|
582
652
|
setBusy(null);
|
|
583
|
-
|
|
584
|
-
notify({ body: `Could not install ${entry.name}: ${result.error}`, type: "error" });
|
|
653
|
+
setFailure(entry.id, { status: "install failed", text: `Could not install ${entry.name}: ${result.error}` });
|
|
585
654
|
return;
|
|
586
655
|
}
|
|
587
656
|
const activated = await activateInstall(result, host, manager);
|
|
@@ -589,8 +658,8 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
589
658
|
bump();
|
|
590
659
|
if (activated.ok && activated.restart) notify({ body: `Restart to finish installing ${entry.name}.`, type: "info" });
|
|
591
660
|
else if (activated.ok) announceAdded(activated.pluginId, activated.name, "Installed", host);
|
|
592
|
-
else
|
|
593
|
-
}, [announceAdded, bump, busy, confirmWidth, dialog, host, manager, notify, refuseTooNew, selected]);
|
|
661
|
+
else setFailure(entry.id, { status: "load failed", text: `${entry.name} installed but did not load: ${activated.error}` });
|
|
662
|
+
}, [announceAdded, bump, busy, confirmWidth, dialog, host, manager, notify, refuseTooNew, selected, setFailure]);
|
|
594
663
|
|
|
595
664
|
const updateSelected = useCallback(async () => {
|
|
596
665
|
if (!selected || !isManaged(selected) || !manager || !host || busy || selected.linked) return;
|
|
@@ -599,12 +668,11 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
599
668
|
const entry = selected;
|
|
600
669
|
const reinstall = !!entry.loadError;
|
|
601
670
|
setBusy({ id: entry.id, verb: "updating" });
|
|
602
|
-
|
|
671
|
+
setFailure(entry.id, null);
|
|
603
672
|
const result = await manager.update(directory, registryPin(entry));
|
|
604
673
|
if (!result.ok) {
|
|
605
674
|
setBusy(null);
|
|
606
|
-
|
|
607
|
-
notify({ body: `Could not update ${entry.name}: ${result.error}`, type: "error" });
|
|
675
|
+
setFailure(entry.id, { status: "update failed", text: `Could not update ${entry.name}: ${result.error}` });
|
|
608
676
|
return;
|
|
609
677
|
}
|
|
610
678
|
if (result.kept) {
|
|
@@ -620,9 +688,21 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
620
688
|
} else if (activated.ok) {
|
|
621
689
|
announceAdded(activated.pluginId, activated.name, reinstall ? "Reloaded" : "Updated", host);
|
|
622
690
|
} else {
|
|
623
|
-
|
|
691
|
+
setFailure(entry.id, { status: "load failed", text: `${entry.name} updated but did not load: ${activated.error}` });
|
|
624
692
|
}
|
|
625
|
-
}, [announceAdded, bump, busy, host, manager, notify, refuseTooNew, selected]);
|
|
693
|
+
}, [announceAdded, bump, busy, host, manager, notify, refuseTooNew, selected, setFailure]);
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* A removal that failed is said on the plugin's row while the list still
|
|
697
|
+
* has one. A stopped plugin can leave the list, files and all; then only a
|
|
698
|
+
* toast is left to say it.
|
|
699
|
+
*/
|
|
700
|
+
const failRemoval = useCallback((entry: MarketplaceEntry, failure: ActionFailure) => {
|
|
701
|
+
const installed = host?.listInstalled() ?? [];
|
|
702
|
+
const listed = mergeCatalog({ registry, installed, target, remoteHeads }).some((candidate) => candidate.id === entry.id);
|
|
703
|
+
if (listed) setFailure(entry.id, failure);
|
|
704
|
+
else notify({ body: failure.text, type: "error" });
|
|
705
|
+
}, [host, notify, registry, remoteHeads, setFailure, target]);
|
|
626
706
|
|
|
627
707
|
const removeSelected = useCallback(async () => {
|
|
628
708
|
if (!selected || !isManaged(selected) || !manager || !host || busy) return;
|
|
@@ -637,18 +717,27 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
637
717
|
});
|
|
638
718
|
if (!confirmed) return;
|
|
639
719
|
setBusy({ id: entry.id, verb: "removing" });
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
notify({ body: `
|
|
720
|
+
setFailure(entry.id, null);
|
|
721
|
+
let removalStarted = false;
|
|
722
|
+
try {
|
|
723
|
+
// Stop the native side first: a successful view stop drops its catalog
|
|
724
|
+
// entry, so it must remain available if the native stop fails.
|
|
725
|
+
await manager.deactivate?.(entry.id);
|
|
726
|
+
await host.deactivate(entry.id, entry.directory);
|
|
727
|
+
removalStarted = true;
|
|
728
|
+
const result = await manager.remove(entry.directory!);
|
|
729
|
+
if (result.ok) notify({ body: `Removed ${entry.name}.`, type: "success" });
|
|
730
|
+
else failRemoval(entry, { status: "remove failed", text: `Could not remove ${entry.name}: ${result.error}` });
|
|
731
|
+
} catch (error) {
|
|
732
|
+
logFailure("plugin-marketplace.pane", "Remove plugin failed")(error);
|
|
733
|
+
failRemoval(entry, removalStarted
|
|
734
|
+
? { status: "remove failed", text: `Could not remove ${entry.name}. Removal failed. Restart and try again.` }
|
|
735
|
+
: { status: "stop failed", text: `Could not remove ${entry.name}. Plugin could not be stopped. Files kept. Restart before removing it.` });
|
|
736
|
+
} finally {
|
|
737
|
+
setBusy(null);
|
|
738
|
+
bump();
|
|
650
739
|
}
|
|
651
|
-
}, [bump, busy, confirmWidth, dialog, host, manager, notify, selected]);
|
|
740
|
+
}, [bump, busy, confirmWidth, dialog, failRemoval, host, manager, notify, selected]);
|
|
652
741
|
|
|
653
742
|
const toggleSelected = useCallback(async () => {
|
|
654
743
|
if (!host || !selected || !selected.installed || !selected.toggleable || selected.loadError) return;
|
|
@@ -735,7 +824,7 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
735
824
|
}))}
|
|
736
825
|
/>
|
|
737
826
|
),
|
|
738
|
-
}).catch((
|
|
827
|
+
}).catch(logFailure("plugin-marketplace.pane", "Choose starter pack failed", null));
|
|
739
828
|
const pack = STARTER_PACKS.find((candidate) => candidate.id === id);
|
|
740
829
|
if (pack) await applyPack(pack);
|
|
741
830
|
}, [applyPack, currentPack, dialog, disabledPlugins, host]);
|
|
@@ -827,11 +916,7 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
827
916
|
const info = loadingErrorFooterInfo(status === "loading", status === "error" ? "catalog unavailable" : null);
|
|
828
917
|
if (stale) info.push({ id: "stale", parts: [{ text: "stale catalog", tone: "warning" }] });
|
|
829
918
|
if (checkingRemotes) info.push({ id: "remote-check", parts: [{ text: "checking unlisted plugins", tone: "muted" }] });
|
|
830
|
-
if (
|
|
831
|
-
const name = entries.find((entry) => entry.id === busy.id)?.name ?? busy.id;
|
|
832
|
-
info.push({ id: "busy", parts: [{ text: `${busy.verb} ${name}`, tone: "muted" }] });
|
|
833
|
-
}
|
|
834
|
-
if (lastError && !busy) info.push({ id: "op-error", parts: [{ text: lastError, tone: "warning" }] });
|
|
919
|
+
if (remoteCheckError) info.push({ id: "remote-error", parts: [{ text: remoteCheckError, tone: "warning" }] });
|
|
835
920
|
const restartCount = entries.filter((entry) => entry.needsRestart).length;
|
|
836
921
|
if (restartCount > 0 && !busy) {
|
|
837
922
|
info.push({ id: "restart", parts: [{ text: "restart to finish loading", tone: "warning" }] });
|
|
@@ -868,8 +953,8 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
868
953
|
|
|
869
954
|
const fit = useMemo(() => ({
|
|
870
955
|
functions: Math.min(16, Math.max(9, ...visible.map((entry) => factsFor(entry).codes.join(" ").length))),
|
|
871
|
-
status: Math.min(14, Math.max(7, ...visible.map((entry) =>
|
|
872
|
-
}), [factsFor, visible]);
|
|
956
|
+
status: Math.min(14, Math.max(7, ...visible.map((entry) => rowStatus(entry).text.length))),
|
|
957
|
+
}), [factsFor, rowStatus, visible]);
|
|
873
958
|
const columns = useMemo(() => buildColumns(width, fit), [fit, width]);
|
|
874
959
|
// The pick is saved with the pane, so keep it listed (and resettable) even
|
|
875
960
|
// when the catalog no longer has plugins in it.
|
|
@@ -917,7 +1002,7 @@ export function PluginMarketplacePane({ focused, width, height }: PaneProps) {
|
|
|
917
1002
|
detailContent={selected
|
|
918
1003
|
? selected.bundled
|
|
919
1004
|
? <BuiltinDetail entry={selected} width={width} facts={factsFor(selected)} scrollRef={detailScrollRef} />
|
|
920
|
-
: <EntryDetail entry={selected} width={width} host={host} />
|
|
1005
|
+
: <EntryDetail entry={selected} width={width} host={host} status={rowStatus(selected)} failure={failureFor(selected)} />
|
|
921
1006
|
: null}
|
|
922
1007
|
detailTitle={selected?.name}
|
|
923
1008
|
rootBefore={(
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { CliCommandContext } from "../../../../types/plugin";
|
|
2
2
|
import type { TickerRecord } from "../../../../types/ticker";
|
|
3
3
|
import type { MarketContext } from "../../../../cli/types";
|
|
4
|
-
import { listingFields,
|
|
4
|
+
import { listingFields, loadSavedListingOf, savedListingCandidates, savedListingName } from "../../../../cli/listing-arg";
|
|
5
5
|
import { withSuggestion } from "../../../../cli/listing-suggestion";
|
|
6
6
|
import { StagedTickerRepository } from "../../../../cli/staged-tickers";
|
|
7
|
-
import { splitSymbolWords, symbolInputKey } from "../../../../cli/symbol-args";
|
|
7
|
+
import { splitSymbolArgs, splitSymbolWords, symbolInputKey } from "../../../../cli/symbol-args";
|
|
8
|
+
import { notASymbolError } from "../../../../cli/symbol-cells";
|
|
8
9
|
import { readSymbolList, SymbolListError } from "../../../../cli/symbol-list";
|
|
9
10
|
import { cliStyles } from "../../../../utils/cli-output";
|
|
10
11
|
import { dryRunNote } from "../../../../cli/helpers";
|
|
@@ -37,23 +38,35 @@ export const FILE_OPTION = {
|
|
|
37
38
|
export const SYMBOL_LIST_HELP = {
|
|
38
39
|
title: "Several symbols",
|
|
39
40
|
lines: [
|
|
40
|
-
"add and remove take any number of symbols split by spaces, commas or newlines, a --file, or piped input (or -). An entry of a list with commas or newlines that has spaces in it is a company's name when search finds one, read as its US listing first with a line under it saying which,
|
|
41
|
-
"Each symbol gets a line, then a summary. Exit status 0 when at least one symbol was added (or removed) or already was, 1 when none resolved or the usage is wrong.",
|
|
42
|
-
"A bare US-style symbol is not added when the listing it matched stopped trading, is abroad (DFS as DFS:LSE) or was taken by another company in the last two years (BRKL), or when nothing lists under it now and its company trades as another. Those are listed under Needs a choice, with the add for what their company trades as now and the listing that matched, which naming keeps; one symbol alone fails with the same. A symbol another company took longer ago says so under its line.",
|
|
41
|
+
"add and remove take any number of symbols split by spaces, commas or newlines, a --file, or piped input (or -). An entry of a list with commas, semicolons or newlines that has spaces in it is a company's name when search finds one (philip morris intl is PM), read as its US listing first with a line under it saying which, else the symbols it holds when each is written as a symbol or has a quote (AAPL MSFT), and otherwise a name not found. A file or piped list reads each line as such an entry. A CSV is read from its Symbol, Ticker or Code column, else its Name or Company column as names. Without that header every cell is a symbol, unless names, prices or weights sit beside them: then the first column is read and the cells left out are named. Each line is split by its own tab, semicolon, comma or spaces, and a price is never a symbol, written either way (2.582,52 or 1,899.21). A comma between plain digits (0700,25) splits them unless the line also has a tab, a semicolon or spaces between cells. Quote a list name with spaces.",
|
|
42
|
+
"Each symbol gets a line, then a summary. An entry that cannot be a symbol (N/A, $$$, --, a price alone) is named as not a symbol without a lookup. Symbols Gloom Cloud did not answer for are listed together with one command that adds them again. Exit status 0 when at least one symbol was added (or removed) or already was, 1 when none resolved or the usage is wrong.",
|
|
43
|
+
"A bare US-style symbol is not added when the listing it matched stopped trading, is abroad while the symbol also names a US listing (DFS as DFS:LSE, Discover's old symbol) or was taken by another company in the last two years (BRKL), or when nothing lists under it now and its company trades as another. Those are listed under Needs a choice, with the add for what their company trades as now and the listing that matched, which naming keeps; one symbol alone fails with the same. A symbol another company took longer ago says so under its line, and one listed only abroad (GARAN) is added with a line naming its venue and currency.",
|
|
44
|
+
"A vendor's suffix is the venue it names: GARAN.IS is stored as GARAN:BIST, the same row GARAN:BIST and GARAN add to.",
|
|
43
45
|
"add --dry-run looks every symbol up and prints the same lines without saving.",
|
|
44
46
|
],
|
|
45
47
|
};
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* One word of a command line as a shell reads it back: as written when it
|
|
51
|
+
* holds nothing a shell treats specially (`NVDA`, `SAN:EPA`, `BRK.B`), else
|
|
52
|
+
* in single quotes (`'Altria Group'`, `'$nvda'`, `'AT&T'`).
|
|
53
|
+
*/
|
|
54
|
+
export function shellWord(word: string): string {
|
|
55
|
+
return /^[\p{L}\p{N}._:@%+,/][\p{L}\p{N}._:@%+,/=-]*$/u.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`;
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
/**
|
|
48
59
|
* A row's line, and under it the listing a company's name was read as, the
|
|
49
|
-
* company that had the symbol before the listing added,
|
|
50
|
-
*
|
|
60
|
+
* company that had the symbol before the listing added, the venue and
|
|
61
|
+
* currency of a bare symbol added on its only listing, abroad, and the coin
|
|
62
|
+
* hint when a bare coin ticker was read as something else.
|
|
51
63
|
*/
|
|
52
64
|
function rowLines(row: SymbolRow, verb: Verb): string {
|
|
53
65
|
return [
|
|
54
66
|
rowLine(row, verb),
|
|
55
67
|
...row.readAs ? [` ${cliStyles.muted(row.readAs)}`] : [],
|
|
56
68
|
...row.changeNote ? [` ${cliStyles.warning(row.changeNote)}`] : [],
|
|
69
|
+
...row.abroad ? [` ${cliStyles.warning(row.abroad)}`] : [],
|
|
57
70
|
...row.hint ? [` ${cliStyles.warning(row.hint)}`] : [],
|
|
58
71
|
].join("\n");
|
|
59
72
|
}
|
|
@@ -71,9 +84,28 @@ function rowLine(row: SymbolRow, verb: Verb): string {
|
|
|
71
84
|
case "not_found": return cliStyles.danger(`Not found: ${typed}${row.message && !NO_MATCH.test(row.message) ? ` (${reason(row.message, typed)})` : ""}${row.suggestion ? `; did you mean ${row.suggestion}?` : ""}`);
|
|
72
85
|
case "needs_choice": return cliStyles.warning(` ${row.message ?? typed}`);
|
|
73
86
|
case "failed": return cliStyles.danger(`Not ${verb === "add" ? "added" : "removed"}: ${typed} (${failedReason(row, typed)})`);
|
|
87
|
+
// Named as written (`$$$`), and a figure says it is one.
|
|
88
|
+
case "not_a_symbol": return cliStyles.warning(`Not a symbol: ${row.input.trim()}${row.message?.includes("a number") ? " (a number)" : ""}`);
|
|
89
|
+
case "not_looked_up": return cliStyles.danger(`Not looked up: ${typed}`);
|
|
74
90
|
}
|
|
75
91
|
}
|
|
76
92
|
|
|
93
|
+
/**
|
|
94
|
+
* The symbols of an add Gloom Cloud did not answer for, after the other
|
|
95
|
+
* lines: one line naming them as they were written, and one command that adds
|
|
96
|
+
* them all again, each entry one shell word (`'philip morris intl'`).
|
|
97
|
+
*/
|
|
98
|
+
function unansweredLines(rows: readonly SymbolRow[], retry: ((keys: string) => string) | undefined): string[] {
|
|
99
|
+
const unanswered = rows.filter((row) => row.status === "not_looked_up").map((row) => row.input.trim());
|
|
100
|
+
if (unanswered.length === 0) return [];
|
|
101
|
+
const count = unanswered.length === 1 ? "1 symbol" : `${unanswered.length} symbols`;
|
|
102
|
+
return [
|
|
103
|
+
"",
|
|
104
|
+
cliStyles.danger(`Gloom Cloud did not answer for ${count}, so ${unanswered.length === 1 ? "it was" : "they were"} not looked up: ${unanswered.join(", ")}`),
|
|
105
|
+
...retry ? [`Try again in a minute: ${retry(unanswered.map(shellWord).join(" "))}`] : [],
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
|
|
77
109
|
/**
|
|
78
110
|
* What symbols that need a choice offer: the add that takes the companies
|
|
79
111
|
* they trade as now, and the add that keeps each match as it is by naming its
|
|
@@ -82,7 +114,7 @@ function rowLine(row: SymbolRow, verb: Verb): string {
|
|
|
82
114
|
function choiceOffers(choices: readonly SymbolRow[], retry: ((keys: string) => string) | undefined): { successors: string | null; matches: string | null } {
|
|
83
115
|
const successors = [...new Set(choices.flatMap((row) => row.tradesAs ? [row.tradesAs] : []))];
|
|
84
116
|
const matches = [...new Set(choices.flatMap((row) => row.listing ? [row.listing] : []))];
|
|
85
|
-
const command = (keys: string[]) => retry ? retry(keys.join(" ")) : keys.join(" ");
|
|
117
|
+
const command = (keys: string[]) => retry ? retry(keys.map(shellWord).join(" ")) : keys.join(" ");
|
|
86
118
|
const one = choices.length === 1;
|
|
87
119
|
return {
|
|
88
120
|
successors: successors.length > 0 ? `Add what ${one ? "it trades" : "they trade"} as now: ${command(successors)}` : null,
|
|
@@ -131,18 +163,21 @@ export function printSymbolRows(
|
|
|
131
163
|
): void {
|
|
132
164
|
const summary = `${collection.kind === "watchlist" ? "Watchlist" : "Portfolio"} "${collection.name}": ${summarizeSymbolRows(rows, verb, repeated)}`;
|
|
133
165
|
const count = (status: SymbolStatus) => rows.filter((row) => row.status === status).length;
|
|
166
|
+
const extra = (key: string, status: SymbolStatus) => count(status) > 0 ? { [key]: count(status) } : {};
|
|
134
167
|
const counts = verb === "add"
|
|
135
168
|
? { added: count("added"), alreadyListed: count("already_listed"), notFound: count("not_found"), notAdded: count("failed"),
|
|
136
|
-
...
|
|
137
|
-
: { removed: count("removed"), notListed: count("not_listed"), notFound: count("not_found"), notRemoved: count("failed")
|
|
169
|
+
...extra("needsChoice", "needs_choice"), ...extra("notLookedUp", "not_looked_up"), ...extra("notASymbol", "not_a_symbol") }
|
|
170
|
+
: { removed: count("removed"), notListed: count("not_listed"), notFound: count("not_found"), notRemoved: count("failed"),
|
|
171
|
+
...extra("notASymbol", "not_a_symbol") };
|
|
138
172
|
ctx.printResult({
|
|
139
173
|
data: rows,
|
|
140
174
|
metadata: { [collection.kind]: collection.name, ...counts, repeated, summary, ...dryRun ? { dryRun } : {} },
|
|
141
175
|
...notes.length > 0 ? { warnings: [...notes] } : {},
|
|
142
176
|
}, {
|
|
143
177
|
text: () => [
|
|
144
|
-
...rows.filter((row) => row.status !== "needs_choice").map((row) => rowLines(row, verb)),
|
|
178
|
+
...rows.filter((row) => row.status !== "needs_choice" && row.status !== "not_looked_up").map((row) => rowLines(row, verb)),
|
|
145
179
|
...choiceLines(rows, retry),
|
|
180
|
+
...unansweredLines(rows, retry),
|
|
146
181
|
"",
|
|
147
182
|
`${summary}${dryRunNote(dryRun)}`,
|
|
148
183
|
].join("\n"),
|
|
@@ -155,16 +190,18 @@ export function printSymbolRows(
|
|
|
155
190
|
/**
|
|
156
191
|
* `watchlist add` and `portfolio add` given one symbol: added as a symbol of a
|
|
157
192
|
* list is (`addSymbol`), and said as one listing, added or already there with
|
|
158
|
-
* its notes as warnings
|
|
193
|
+
* its notes as warnings, after `notes` on what was left out of the input (the
|
|
194
|
+
* price of `ED 2.582,52`). A symbol a list would leave for a choice fails the
|
|
159
195
|
* command, saying why, with what a list offers under the error; any other
|
|
160
196
|
* failure fails it as the lookup's error, a busy service's to retry.
|
|
161
197
|
*/
|
|
162
198
|
export async function addOneSymbol(
|
|
163
199
|
ctx: CliCommandContext,
|
|
164
200
|
market: MarketContext,
|
|
165
|
-
{ symbol, exchange, collection, retry, reject, add }: {
|
|
201
|
+
{ symbol, exchange, collection, notes: inputNotes = [], retry, reject, add }: {
|
|
166
202
|
symbol: string;
|
|
167
203
|
exchange: string | undefined;
|
|
204
|
+
notes?: readonly string[];
|
|
168
205
|
collection: CollectionRef;
|
|
169
206
|
/** The add of one listing, for the choices a failure names. */
|
|
170
207
|
retry: (key: string) => string;
|
|
@@ -189,7 +226,8 @@ export async function addOneSymbol(
|
|
|
189
226
|
const { change, formerIssuer, notes } = lookup;
|
|
190
227
|
const data = { changed, ...listingFields(saved), [collection.kind]: collection.name,
|
|
191
228
|
...change ? { tickerChange: change } : {}, ...formerIssuer ? { formerIssuer } : {}, ...dryRun ? { dryRun } : {} };
|
|
192
|
-
const
|
|
229
|
+
const said = [...inputNotes, ...notes, ...row.abroad ? [row.abroad] : []];
|
|
230
|
+
const warnings = said.length > 0 ? said : undefined;
|
|
193
231
|
ctx.printResult({ data, warnings }, {
|
|
194
232
|
text: () => changed
|
|
195
233
|
? `${cliStyles.success(`Added ${saved.label} to "${collection.name}".`)}${dryRunNote(dryRun)}`
|
|
@@ -208,7 +246,9 @@ export function retryNotice(ctx: CliCommandContext): (count: number, waitMs: num
|
|
|
208
246
|
/**
|
|
209
247
|
* The symbols an add or remove was given, failing the command when there are
|
|
210
248
|
* none or the file cannot be read. An add reads a typed company's name with
|
|
211
|
-
* `readNameEntries`; without it (a remove) every entry is its words.
|
|
249
|
+
* `readNameEntries`; without it (a remove) every entry is its words. `single`
|
|
250
|
+
* is the one symbol typed alone, and `notes` what the single command says
|
|
251
|
+
* beside it: none when it goes as typed, else what was left out of it.
|
|
212
252
|
*/
|
|
213
253
|
export async function requireSymbolList(
|
|
214
254
|
ctx: CliCommandContext,
|
|
@@ -218,16 +258,23 @@ export async function requireSymbolList(
|
|
|
218
258
|
readEntries?: (entries: string[]) => Promise<string[]>,
|
|
219
259
|
): Promise<{ symbols: string[]; repeated: number; notes: string[]; single: string | null }> {
|
|
220
260
|
try {
|
|
221
|
-
|
|
261
|
+
// The first entries read are what was typed; a file's and standard input's come after.
|
|
262
|
+
let typed: string[] | null = null;
|
|
222
263
|
const list = await readSymbolList({ args, file, readEntries: async (entries) => {
|
|
223
|
-
|
|
224
|
-
|
|
264
|
+
const read = readEntries ? await readEntries(entries) : splitSymbolWords(entries);
|
|
265
|
+
typed ??= read;
|
|
266
|
+
return read;
|
|
225
267
|
} });
|
|
226
|
-
|
|
268
|
+
// Only numbers or strays says what it left out, not only how to call the command.
|
|
269
|
+
if (list.symbols.length === 0) ctx.fail(list.notes.length > 0 ? ["No symbols.", ...list.notes].join(" ") : usage, list.notes.length > 0 ? usage : undefined);
|
|
227
270
|
// One symbol typed alone keeps the single-symbol output and errors. It goes as typed, so a separator
|
|
228
|
-
// left on it (`UPST;`) is named by the listing it resolves to
|
|
229
|
-
|
|
230
|
-
|
|
271
|
+
// left on it (`UPST;`) is named by the listing it resolves to; without the figure typed beside it
|
|
272
|
+
// (`ED 2.582,52`), which the notes name.
|
|
273
|
+
const entries: string[] = typed ?? [];
|
|
274
|
+
const split = splitSymbolArgs(args);
|
|
275
|
+
const asTyped = args.length === 1 && split.length === 1 && split[0] === entries[0];
|
|
276
|
+
const single = file == null && !args.includes("-") && entries.length === 1 ? (asTyped ? args[0]!.trim() : entries[0]!) : null;
|
|
277
|
+
return { ...list, single, notes: single && asTyped ? [] : list.notes };
|
|
231
278
|
} catch (error) {
|
|
232
279
|
if (error instanceof SymbolListError) ctx.fail(error.message, usage);
|
|
233
280
|
throw error;
|
|
@@ -245,29 +292,33 @@ export async function removeSymbols({
|
|
|
245
292
|
exchange,
|
|
246
293
|
store,
|
|
247
294
|
reject,
|
|
295
|
+
holds,
|
|
248
296
|
remove,
|
|
249
297
|
}: BulkSymbolsOptions & {
|
|
250
298
|
reject?: (input: string) => Error | null;
|
|
299
|
+
/** Whether the list being changed holds the row: of two a symbol may be saved as (GARAN:BIST and GARAN.IS), the one it holds. */
|
|
300
|
+
holds?: (ticker: TickerRecord) => boolean;
|
|
251
301
|
remove: (ticker: TickerRecord) => { changed: boolean; ticker: TickerRecord; extra?: Record<string, unknown> };
|
|
252
302
|
}): Promise<SymbolRow[]> {
|
|
253
303
|
const staged = new StagedTickerRepository(store);
|
|
254
304
|
const rows: SymbolRow[] = [];
|
|
255
305
|
for (const input of symbols) {
|
|
256
|
-
const refusal = reject?.(input);
|
|
306
|
+
const refusal = notASymbolError(input) ?? reject?.(input);
|
|
257
307
|
if (refusal) {
|
|
258
308
|
rows.push(failedRow(input, refusal));
|
|
259
309
|
continue;
|
|
260
310
|
}
|
|
261
|
-
let
|
|
311
|
+
let listings;
|
|
262
312
|
try {
|
|
263
|
-
|
|
313
|
+
// GARAN.IS is the row of GARAN:BIST, else a row still saved under that key (a broker's).
|
|
314
|
+
listings = savedListingCandidates(input, exchange, { ownExchangeWins: true });
|
|
264
315
|
} catch (error) {
|
|
265
316
|
rows.push(failedRow(input, error instanceof Error ? error : new Error(String(error))));
|
|
266
317
|
continue;
|
|
267
318
|
}
|
|
268
|
-
const ticker =
|
|
319
|
+
const ticker = listings[0]!.symbol ? (await loadSavedListingOf(staged, listings, holds))?.ticker : null;
|
|
269
320
|
if (!ticker) {
|
|
270
|
-
rows.push(failedRow(input, new Error(`Ticker "${
|
|
321
|
+
rows.push(failedRow(input, new Error(`Ticker "${listings[0]!.key}" was not found in your local data.`), "not_found"));
|
|
271
322
|
continue;
|
|
272
323
|
}
|
|
273
324
|
const result = remove(ticker);
|