gloomberb 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +44 -11
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +5 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/members.ts +26 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +41 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +9 -1
- package/src/app/global-shortcuts.ts +14 -6
- package/src/app/keybindings/actions.ts +1 -1
- package/src/app/runtime/update.ts +38 -2
- package/src/app.tsx +10 -6
- package/src/brokers/account-cache.ts +24 -0
- package/src/cli/commands/command-utils.ts +8 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +414 -106
- package/src/cli/commands/overview.ts +77 -32
- package/src/cli/commands/ticker.ts +101 -43
- package/src/cli/desktop-pane-shot.ts +34 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +1 -0
- package/src/cli/helpers.ts +4 -8
- package/src/cli/index.ts +12 -2
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +20 -2
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +36 -22
- package/src/cli/pane-functions/headless.ts +39 -11
- package/src/cli/pane-functions/index.ts +15 -4
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +35 -7
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +7 -3
- package/src/cli/result.ts +41 -27
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/commands/collection.ts +5 -1
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/root/command-items.ts +9 -2
- package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
- package/src/components/command-bar/routes/root/provider-search.ts +19 -5
- package/src/components/command-bar/routes/root/runtime.ts +14 -5
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
- package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
- package/src/components/command-bar/routing/actions.ts +2 -0
- package/src/components/command-bar/selection-runtime.ts +38 -0
- package/src/components/command-bar/surface/index.tsx +7 -2
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/view.tsx +29 -10
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/index.ts +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/floating-pane.tsx +6 -0
- package/src/components/layout/header.tsx +24 -7
- package/src/components/layout/missing-pane.tsx +2 -2
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +61 -28
- package/src/components/layout/pane/index.tsx +6 -0
- package/src/components/layout/pane/title.ts +31 -7
- package/src/components/layout/shell/drag/index.ts +6 -5
- package/src/components/layout/shell/drag/runtime.ts +3 -0
- package/src/components/layout/shell/index.tsx +6 -0
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +29 -10
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
- package/src/components/layout/shell/ticker-link-menu.ts +23 -9
- package/src/components/metric-treemap/heat-surface.tsx +745 -0
- package/src/components/metric-treemap/heat-tiles.ts +228 -0
- package/src/components/metric-treemap/index.tsx +2 -0
- package/src/components/metric-treemap/layout.ts +8 -0
- package/src/components/metric-treemap/scene.ts +432 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/toggle-list.tsx +38 -12
- package/src/components/ui/country-flag-art.tsx +449 -0
- package/src/components/ui/country-flag.tsx +41 -0
- package/src/components/ui/data-table/types.ts +13 -0
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/icon.tsx +2 -0
- package/src/components/ui/index.ts +4 -0
- package/src/components/ui/multi-select/dialog.tsx +108 -22
- package/src/components/ui/range-track.tsx +53 -0
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +11 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/core/state/app/types.ts +10 -1
- package/src/data/config/store/normalize.ts +17 -1
- package/src/i18n/es.ts +24 -4
- package/src/i18n/ja.ts +24 -4
- package/src/i18n/ko.ts +24 -4
- package/src/i18n/zh-cn.ts +24 -4
- package/src/i18n/zh-tw.ts +24 -4
- package/src/layout/ticker-navigation.ts +28 -2
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +78 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +8 -0
- package/src/market-data/quotes/freshness.ts +36 -0
- package/src/market-data/quotes/resolution.ts +24 -8
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/market-data/quotes/time.ts +16 -0
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/risk-client.ts +330 -79
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
- package/src/plugins/builtin/analytics/risk-math.ts +33 -13
- package/src/plugins/builtin/analytics/risk-model.ts +282 -64
- package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
- package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +1 -1
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/cells.tsx +15 -12
- package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
- package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
- package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
- package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
- package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/catalysts/index.tsx +2 -2
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/cds/index.tsx +1 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +1 -1
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
- package/src/plugins/builtin/dividend-yield/client.ts +4 -2
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/client.ts +2 -2
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
- package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
- package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
- package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/headless.ts +139 -5
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +20 -3
- package/src/plugins/builtin/holders/report-header.ts +95 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +30 -2
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
- package/src/plugins/builtin/market-heatmap/live.ts +88 -0
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
- package/src/plugins/builtin/market-movers/client.ts +3 -2
- package/src/plugins/builtin/market-movers/headless.ts +10 -1
- package/src/plugins/builtin/market-movers/screener.ts +18 -5
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +53 -0
- package/src/plugins/builtin/members/headless.ts +35 -0
- package/src/plugins/builtin/members/index.tsx +20 -0
- package/src/plugins/builtin/members/model.ts +68 -0
- package/src/plugins/builtin/members/pane.tsx +175 -0
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/mna/index.tsx +2 -1
- package/src/plugins/builtin/mna/pane.tsx +5 -2
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +2 -1
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +74 -2
- package/src/plugins/builtin/pe-band/headless.ts +26 -8
- package/src/plugins/builtin/pe-band/model.ts +102 -22
- package/src/plugins/builtin/pe-band/pane.tsx +34 -16
- package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
- package/src/plugins/builtin/perps/client.ts +66 -5
- package/src/plugins/builtin/perps/equity-identity.ts +16 -0
- package/src/plugins/builtin/perps/equity-row.tsx +6 -4
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +248 -47
- package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
- package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
- package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
- package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/index.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/index.tsx +2 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
- package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +67 -4
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
- package/src/plugins/builtin/world-venue-map/model.ts +7 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/catalog-browser.ts +2 -0
- package/src/plugins/catalog-manifest.ts +1 -0
- package/src/plugins/catalog-ui.ts +3 -1
- package/src/plugins/catalog.ts +1 -1
- package/src/plugins/host-link.ts +33 -1
- package/src/plugins/installer.ts +48 -12
- package/src/plugins/loader.ts +30 -3
- package/src/plugins/manager-node.ts +15 -5
- package/src/plugins/registry/index.ts +1 -1
- package/src/plugins/registry/pane-settings.ts +26 -7
- package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/row.tsx +52 -16
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/icons.tsx +1 -0
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +69 -26
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/tabs.tsx +37 -1
- package/src/renderers/dom/styles.css +41 -7
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
- package/src/renderers/electrobun/bun/index.ts +73 -6
- package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
- package/src/renderers/electrobun/shared/protocol.ts +3 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
- package/src/renderers/electrobun/view/main.tsx +7 -1
- package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/update-host.ts +45 -21
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financials.ts +11 -8
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/benign-window-error.ts +7 -0
- package/src/telemetry/crash-reports-dom.ts +2 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/daily-nav.ts +25 -0
- package/src/theme/heat-colors.ts +357 -2
- package/src/tickers/instrument-kind.ts +34 -7
- package/src/tickers/search/asset-classes.ts +24 -9
- package/src/tickers/search/index.ts +44 -11
- package/src/tickers/search/ranking.ts +23 -3
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +5 -0
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +38 -6
- package/src/types/ticker.ts +15 -0
- package/src/ui/context-menu.tsx +1 -0
- package/src/ui/host.tsx +16 -0
- package/src/updater/index.ts +38 -13
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +14 -0
- package/src/utils/depositary-receipt.ts +26 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -15,6 +15,7 @@ import type { RemoteUiNodeSnapshot } from "../remote/types";
|
|
|
15
15
|
import type { DatedObservation } from "../plugins/builtin/market-valuation/series";
|
|
16
16
|
import type { DesktopExternalPluginBundle } from "../renderers/electrobun/shared/protocol";
|
|
17
17
|
import type { HttpProxyRequestEnvelope, HttpProxyResponseEnvelope } from "../utils/http-proxy-response";
|
|
18
|
+
import type { PaneAccessGate } from "./pane-functions/access-gate";
|
|
18
19
|
import { readVisibleKeyValues } from "./visible-key-values";
|
|
19
20
|
import { SHOT_API_PROXY_PREFIX, SHOT_HTTP_BRIDGE_PATH, SHOT_MARKET_BRIDGE_PATH } from "./desktop-pane-shot-routes";
|
|
20
21
|
import { SESSION_COOKIE_NAMES } from "../api-client/session-cookie";
|
|
@@ -93,6 +94,8 @@ interface DesktopPaneShotRenderedCell {
|
|
|
93
94
|
columnId?: string;
|
|
94
95
|
columnLabel: string;
|
|
95
96
|
text: string;
|
|
97
|
+
/** The ISO instant behind a cell whose text shortens a time ("Wed 11:27"), from the table cell's export value. */
|
|
98
|
+
instant?: string;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
export interface DesktopPaneShotRenderedRow {
|
|
@@ -105,6 +108,8 @@ export interface DesktopPaneShotRenderedRow {
|
|
|
105
108
|
|
|
106
109
|
export interface DesktopPaneShotRenderResult {
|
|
107
110
|
visibleText: string;
|
|
111
|
+
/** Text of the pane footers, where a pane says whether its data is live, delayed or stale. */
|
|
112
|
+
footerText?: string;
|
|
108
113
|
visibleKeyValues?: Array<{ label: string; text: string }>;
|
|
109
114
|
rows: DesktopPaneShotRenderedRow[];
|
|
110
115
|
truncated: boolean;
|
|
@@ -114,6 +119,8 @@ export interface DesktopPaneShotRenderResult {
|
|
|
114
119
|
errorStateMarkers: string[];
|
|
115
120
|
emptyStateDetected: boolean;
|
|
116
121
|
emptyStateMarkers: string[];
|
|
122
|
+
/** A wall that needs an account, or a Pro lock on part of the pane. */
|
|
123
|
+
accessGate?: PaneAccessGate | null;
|
|
117
124
|
semanticUi: RemoteUiNodeSnapshot[];
|
|
118
125
|
}
|
|
119
126
|
|
|
@@ -472,14 +479,22 @@ const LOADING_STATE_PATTERNS = [
|
|
|
472
479
|
/\bRendering pane\.{3}/gi,
|
|
473
480
|
];
|
|
474
481
|
|
|
475
|
-
const
|
|
476
|
-
/\b[^.]{1,100} unavailable\./gi,
|
|
477
|
-
/\bFailed to fetch\b/gi,
|
|
478
|
-
/\bCould not load\b/gi,
|
|
482
|
+
const SIGN_IN_WALL_PATTERNS = [
|
|
479
483
|
/\bSign in to\b/gi,
|
|
480
484
|
/\bVerify your email\b/gi,
|
|
481
485
|
/\brequires signup and email verification\b/gi,
|
|
486
|
+
];
|
|
487
|
+
|
|
488
|
+
const PRO_WALL_PATTERNS = [
|
|
482
489
|
/\bpart of Gloom Cloud Pro\b/gi,
|
|
490
|
+
];
|
|
491
|
+
|
|
492
|
+
const ERROR_STATE_PATTERNS = [
|
|
493
|
+
/\b[^.]{1,100} unavailable\./gi,
|
|
494
|
+
/\bFailed to fetch\b/gi,
|
|
495
|
+
/\bCould not load\b/gi,
|
|
496
|
+
...SIGN_IN_WALL_PATTERNS,
|
|
497
|
+
...PRO_WALL_PATTERNS,
|
|
483
498
|
/\bCloud API request failed\b/gi,
|
|
484
499
|
];
|
|
485
500
|
|
|
@@ -569,12 +584,14 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
569
584
|
) {
|
|
570
585
|
truncationReasons.add("one or more cells are visibly clipped");
|
|
571
586
|
}
|
|
587
|
+
const instant = cell.getAttribute("data-gloom-cell-instant");
|
|
572
588
|
return {
|
|
573
589
|
...(typeof semanticColumn.id === "string" ? { columnId: semanticColumn.id } : {}),
|
|
574
590
|
columnLabel: typeof semanticColumn.label === "string"
|
|
575
591
|
? semanticColumn.label
|
|
576
592
|
: headers[cellIndex] || (values.length === 1 ? "Row" : String(cellIndex + 1)),
|
|
577
593
|
text,
|
|
594
|
+
...(instant ? { instant } : {}),
|
|
578
595
|
};
|
|
579
596
|
}).filter((cell) => cell.text.length > 0);
|
|
580
597
|
if (cells.length === 0) return;
|
|
@@ -605,6 +622,10 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
605
622
|
}
|
|
606
623
|
return {
|
|
607
624
|
visibleText: root.innerText || root.textContent || "",
|
|
625
|
+
footerText: [...root.querySelectorAll('[data-gloom-role="pane-footer"]')]
|
|
626
|
+
.map((footer) => normalize(footer.innerText || footer.textContent))
|
|
627
|
+
.filter(Boolean)
|
|
628
|
+
.join(" "),
|
|
608
629
|
visibleKeyValues: (${readVisibleKeyValues.toString()})(root),
|
|
609
630
|
error: window.__GLOOM_CLI_SHOT_ERROR__ || "",
|
|
610
631
|
loadingStateDetected: root.querySelector('[data-gloom-status="loading"]') !== null,
|
|
@@ -612,6 +633,9 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
612
633
|
// An empty sub-section off screen, such as a ticker's news list below
|
|
613
634
|
// the fold, does not make the captured view empty.
|
|
614
635
|
emptyStateDetected: [...root.querySelectorAll('[data-gloom-status="empty"]')].some(isVisible),
|
|
636
|
+
// The shared sign-in wall and the Pro lock prompt every gated pane draws.
|
|
637
|
+
accessGate: [...root.querySelectorAll('[data-gloom-ui="sign-in-wall"]')].some(isVisible) ? "sign-in"
|
|
638
|
+
: [...root.querySelectorAll('[data-gloom-ui="pro-lock"]')].some(isVisible) ? "pro" : "",
|
|
615
639
|
rows,
|
|
616
640
|
truncated: truncationReasons.size > 0,
|
|
617
641
|
truncationReasons: [...truncationReasons],
|
|
@@ -623,11 +647,13 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
623
647
|
result?: {
|
|
624
648
|
value?: {
|
|
625
649
|
visibleText?: string;
|
|
650
|
+
footerText?: string;
|
|
626
651
|
visibleKeyValues?: Array<{ label: string; text: string }>;
|
|
627
652
|
error?: string;
|
|
628
653
|
loadingStateDetected?: boolean;
|
|
629
654
|
errorStateDetected?: boolean;
|
|
630
655
|
emptyStateDetected?: boolean;
|
|
656
|
+
accessGate?: string;
|
|
631
657
|
rows?: DesktopPaneShotRenderedRow[];
|
|
632
658
|
truncated?: boolean;
|
|
633
659
|
truncationReasons?: string[];
|
|
@@ -641,6 +667,8 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
641
667
|
const loadingStateMarkers = stateMarkers(visibleText, LOADING_STATE_PATTERNS);
|
|
642
668
|
const errorStateMarkers = stateMarkers(visibleText, ERROR_STATE_PATTERNS);
|
|
643
669
|
const emptyStateMarkers = stateMarkers(visibleText, EMPTY_STATE_PATTERNS);
|
|
670
|
+
const accessGate: PaneAccessGate | null = value?.accessGate === "sign-in" || stateMarkers(visibleText, SIGN_IN_WALL_PATTERNS).length > 0 ? "sign-in"
|
|
671
|
+
: value?.accessGate === "pro" || stateMarkers(visibleText, PRO_WALL_PATTERNS).length > 0 ? "pro" : null;
|
|
644
672
|
const rows = Array.isArray(value?.rows) ? value.rows : [];
|
|
645
673
|
const textShowsEllipsis = rows.some((row) => row.cells.some((cell) => /\u2026|\.\.\./.test(cell.text)));
|
|
646
674
|
const truncationReasons = Array.isArray(value?.truncationReasons)
|
|
@@ -651,6 +679,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
651
679
|
}
|
|
652
680
|
return {
|
|
653
681
|
visibleText,
|
|
682
|
+
footerText: typeof value?.footerText === "string" ? value.footerText : "",
|
|
654
683
|
visibleKeyValues: Array.isArray(value?.visibleKeyValues) ? value.visibleKeyValues : [],
|
|
655
684
|
rows,
|
|
656
685
|
truncated: value?.truncated === true || textShowsEllipsis,
|
|
@@ -660,6 +689,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
|
|
|
660
689
|
errorStateMarkers,
|
|
661
690
|
emptyStateDetected: value?.emptyStateDetected === true || emptyStateMarkers.length > 0,
|
|
662
691
|
emptyStateMarkers,
|
|
692
|
+
accessGate,
|
|
663
693
|
semanticUi: Array.isArray(value?.semanticUi) ? value.semanticUi : [],
|
|
664
694
|
};
|
|
665
695
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { FinancialStatement, Quote, TickerFinancials } from "../types/financials";
|
|
2
|
+
import type { HeadlessPaneFreshness, HeadlessPaneRow } from "../types/headless";
|
|
3
|
+
import { deriveHeadlessFreshness, type ReportFreshness } from "./pane-functions/freshness";
|
|
4
|
+
import { quoteFreshnessFields, REPORTED_DATA } from "../plugins/builtin/shared/report-freshness";
|
|
5
|
+
import { latestFinancialPeriod } from "../utils/latest-financial-period";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The source, as-of and status line of a plain CLI command, derived exactly as
|
|
9
|
+
* an `fn` report derives it: rows read like a headless report's rows (quote
|
|
10
|
+
* `dataSource`, `delayMinutes`, `stale` flags, observation times, worst of
|
|
11
|
+
* across rows) under what the command declares about them. Nothing to cite, no line.
|
|
12
|
+
*/
|
|
13
|
+
export function rowsFreshness(
|
|
14
|
+
rows: readonly object[],
|
|
15
|
+
declared?: HeadlessPaneFreshness,
|
|
16
|
+
metadata?: Record<string, unknown>,
|
|
17
|
+
now = Date.now(),
|
|
18
|
+
): ReportFreshness | undefined {
|
|
19
|
+
if (rows.length === 0 && !metadata && !declared) return undefined;
|
|
20
|
+
return deriveHeadlessFreshness(
|
|
21
|
+
{ shape: "rows", freshness: declared },
|
|
22
|
+
{ rows: rows as HeadlessPaneRow[], ...(metadata ? { metadata } : {}) },
|
|
23
|
+
now,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** One row per quote shown, as `fn` quote reports carry them: live, delayed or stale for its session. */
|
|
28
|
+
function quoteFreshnessRow(quote: Quote): HeadlessPaneRow {
|
|
29
|
+
return { ...quoteFreshnessFields(quote), updatedAt: quote.lastUpdated };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Worst of across the quotes shown, dated by the newest. Quotes that failed to load say nothing. */
|
|
33
|
+
export function quotesFreshness(
|
|
34
|
+
quotes: Iterable<Quote | null | undefined>,
|
|
35
|
+
declared?: HeadlessPaneFreshness,
|
|
36
|
+
now = Date.now(),
|
|
37
|
+
): ReportFreshness | undefined {
|
|
38
|
+
const rows = [...quotes].filter((quote): quote is Quote => quote != null).map(quoteFreshnessRow);
|
|
39
|
+
return rows.length > 0 ? rowsFreshness(rows, declared, undefined, now) : undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The newest reported period end in the statements, the period the trailing figures run through. */
|
|
43
|
+
function latestReportedPeriod(financials: Pick<TickerFinancials, "annualStatements" | "quarterlyStatements">): string | null {
|
|
44
|
+
const rows: FinancialStatement[] = [...financials.annualStatements, ...financials.quarterlyStatements];
|
|
45
|
+
return latestFinancialPeriod(rows, (row) => row.date)?.date ?? null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Fundamentals and valuation: reported figures, not a feed. Dated by when the
|
|
50
|
+
* statistics block was observed, with the newest statement period they run
|
|
51
|
+
* through named in the status; stale only when the block says so.
|
|
52
|
+
*/
|
|
53
|
+
export function fundamentalsFreshness(financials: TickerFinancials, now = Date.now()): ReportFreshness {
|
|
54
|
+
const fundamentals = financials.fundamentals;
|
|
55
|
+
const period = latestReportedPeriod(financials);
|
|
56
|
+
return rowsFreshness([], {
|
|
57
|
+
...REPORTED_DATA,
|
|
58
|
+
basis: period ? `reported through ${period}` : REPORTED_DATA.basis,
|
|
59
|
+
asOf: fundamentals?.fetchedAt ?? null,
|
|
60
|
+
}, { stale: fundamentals?.stale === true }, now)!;
|
|
61
|
+
}
|
package/src/cli/help.ts
CHANGED
|
@@ -95,6 +95,7 @@ export function renderCliHelp(entries: CliHelpEntry[], version: string, descript
|
|
|
95
95
|
["gloomberb", "Open the terminal UI"],
|
|
96
96
|
["gloomberb <command> [args]", "Run a command and print the result"],
|
|
97
97
|
["gloomberb help <command>", "Show a command's usage, options, and examples"],
|
|
98
|
+
["gloomberb ticker SAN:EPA", "Name the listing of a symbol that trades in several places (or --exchange EPA)"],
|
|
98
99
|
], { width }),
|
|
99
100
|
];
|
|
100
101
|
|
package/src/cli/helpers.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { cliStyles, colorBySign } from "../utils/cli-output";
|
|
|
9
9
|
import type { AppConfig } from "../types/config";
|
|
10
10
|
import type { Watchlist, TickerRecord } from "../types/ticker";
|
|
11
11
|
import { isFiniteNumber } from "../utils/guards";
|
|
12
|
+
import { formatUtcTime } from "../utils/utc-time";
|
|
12
13
|
|
|
13
14
|
export function formatSignedCurrency(value: number, currency: string): string {
|
|
14
15
|
return value > 0 ? `+${formatCurrency(value, currency)}` : formatCurrency(value, currency);
|
|
@@ -87,15 +88,10 @@ export function formatPriceRange(
|
|
|
87
88
|
return `${format(low, { fixedFractionDigits: digits })}${separator}${format(high, { fixedFractionDigits: digits })}`;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
/** A timestamp in CLI text: UTC with the zone named, the same on every machine. */
|
|
90
92
|
export function formatTimestamp(timestamp: number | undefined): string {
|
|
91
|
-
if (!timestamp) return "—";
|
|
92
|
-
return new Date(timestamp)
|
|
93
|
-
month: "short",
|
|
94
|
-
day: "numeric",
|
|
95
|
-
year: "numeric",
|
|
96
|
-
hour: "numeric",
|
|
97
|
-
minute: "2-digit",
|
|
98
|
-
});
|
|
93
|
+
if (!timestamp || !Number.isFinite(timestamp)) return "—";
|
|
94
|
+
return formatUtcTime(new Date(timestamp)) || "—";
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
export function formatBidAsk(
|
package/src/cli/index.ts
CHANGED
|
@@ -23,6 +23,8 @@ import { fail, inferCliErrorOptions, printCliError } from "./errors";
|
|
|
23
23
|
import { setCliColorEnabledOverride } from "../utils/cli-output";
|
|
24
24
|
import { search, searchCandidatesForCli, buildSearchReport } from "./commands/search";
|
|
25
25
|
import { ticker } from "./commands/ticker";
|
|
26
|
+
import { takeOption } from "./commands/command-utils";
|
|
27
|
+
import { EXCHANGE_OPTION } from "./listing-arg";
|
|
26
28
|
import { apiCliCommand } from "./commands/api";
|
|
27
29
|
import { marketDataCliCommands } from "./commands/market";
|
|
28
30
|
import { overviewCliCommands } from "./commands/overview";
|
|
@@ -99,14 +101,18 @@ function createCoreCliCommands(
|
|
|
99
101
|
help: {
|
|
100
102
|
group: CLI_COMMAND_GROUPS.research,
|
|
101
103
|
usage: ["ticker <symbol>"],
|
|
102
|
-
|
|
104
|
+
options: [EXCHANGE_OPTION],
|
|
105
|
+
examples: ["ticker AAPL", "ticker SAN:EPA", "ticker 7203.T", "ticker AAPL --json"],
|
|
103
106
|
},
|
|
104
|
-
execute: async (
|
|
107
|
+
execute: async (rawArgs, ctx) => {
|
|
108
|
+
const args = [...rawArgs];
|
|
109
|
+
const exchange = takeOption(args, "--exchange");
|
|
105
110
|
const symbol = args[0];
|
|
106
111
|
if (!symbol) {
|
|
107
112
|
ctx.fail("Usage: gloomberb ticker <symbol>");
|
|
108
113
|
}
|
|
109
114
|
await ticker(symbol!, {
|
|
115
|
+
exchange,
|
|
110
116
|
initMarketData: ctx.initMarketData,
|
|
111
117
|
fail: ctx.fail,
|
|
112
118
|
...(ctx.cliOptions.format === "text" ? {} : { printResult: ctx.printResult }),
|
|
@@ -140,9 +146,11 @@ function createCoreCliCommands(
|
|
|
140
146
|
options: [
|
|
141
147
|
{ flags: "--<option> <value>", description: "A function setting; gloomberb catalog <function> lists them" },
|
|
142
148
|
{ flags: "--require-bot-safe", description: "Fail unless the function has a verified, complete report" },
|
|
149
|
+
EXCHANGE_OPTION,
|
|
143
150
|
],
|
|
144
151
|
examples: [
|
|
145
152
|
"fn HP AAPL",
|
|
153
|
+
"fn ANR SAN:EPA",
|
|
146
154
|
"fn CBR --json",
|
|
147
155
|
"fn 13F AAPL --view=ticker-holdings",
|
|
148
156
|
"fn OVME --spot 100 --strike 100 --days 30 --volatility 25",
|
|
@@ -168,9 +176,11 @@ function createCoreCliCommands(
|
|
|
168
176
|
{ flags: "--scale <n>", description: "Text scale from 0.5 to 4 (default 1)" },
|
|
169
177
|
{ flags: "--watermark <label>", description: "Label drawn in the pane title bar" },
|
|
170
178
|
{ flags: "--<option> <value>", description: "A function setting; gloomberb catalog <function> lists them" },
|
|
179
|
+
EXCHANGE_OPTION,
|
|
171
180
|
],
|
|
172
181
|
examples: [
|
|
173
182
|
"shot TAS AAPL --output tape.png",
|
|
183
|
+
"shot HP BHP:ASX",
|
|
174
184
|
"shot DDIS MSFT --tab history",
|
|
175
185
|
"shot HP NVDA --width 1600 --theme green",
|
|
176
186
|
],
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type { DataProvider } from "../types/data-provider";
|
|
2
|
+
import type { Quote } from "../types/financials";
|
|
3
|
+
import type { CliCommandContext } from "../types/plugin";
|
|
4
|
+
import type { TickerRecord } from "../types/ticker";
|
|
5
|
+
import { AmbiguousContractError, AmbiguousTickerError, listingChoiceQuery, resolveTickerSearch } from "../tickers/search";
|
|
6
|
+
import { cliStyles } from "../utils/cli-output";
|
|
7
|
+
import {
|
|
8
|
+
canonicalExchange,
|
|
9
|
+
exchangeLabel,
|
|
10
|
+
isKnownExchangeCode,
|
|
11
|
+
parsePublicTickerKey,
|
|
12
|
+
publicTickerKey,
|
|
13
|
+
} from "../utils/exchanges";
|
|
14
|
+
import { withMarketData } from "./scoped-context";
|
|
15
|
+
|
|
16
|
+
/** The `--exchange` option of every command that takes a ticker. */
|
|
17
|
+
export const EXCHANGE_OPTION = {
|
|
18
|
+
flags: "--exchange <code>",
|
|
19
|
+
description: "Listing exchange, for a symbol that trades in several places (same as SYMBOL:CODE)",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export class ListingArgError extends Error {
|
|
23
|
+
constructor(message: string, readonly details?: string) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "ListingArgError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ListingArg {
|
|
30
|
+
/** The symbol without a venue: SAN. */
|
|
31
|
+
symbol: string;
|
|
32
|
+
/** The canonical code of the exchange the user named, or "" when none was. */
|
|
33
|
+
exchange: string;
|
|
34
|
+
/** SAN:EPA, or SAN when no exchange was named. */
|
|
35
|
+
key: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* `SAN:EPA` and `SAN --exchange EPA` name the same listing. Both spellings of
|
|
40
|
+
* an exchange go through the app's alias table, so `SAN:XPAR` is `SAN:EPA`.
|
|
41
|
+
* A symbol's own exchange and `--exchange` that disagree are an error, unless
|
|
42
|
+
* the command takes several symbols and `--exchange` only fills in the ones
|
|
43
|
+
* without an exchange of their own.
|
|
44
|
+
*/
|
|
45
|
+
export function parseListingArg(
|
|
46
|
+
raw: string,
|
|
47
|
+
exchangeOption?: string | null,
|
|
48
|
+
{ ownExchangeWins = false }: { ownExchangeWins?: boolean } = {},
|
|
49
|
+
): ListingArg {
|
|
50
|
+
const option = canonicalExchange(exchangeOption ?? "");
|
|
51
|
+
let typed = raw.trim().replace(/^\$/, "").toUpperCase();
|
|
52
|
+
// `SAN:` asks which listing; with --exchange it has its answer.
|
|
53
|
+
if (option && typed.endsWith(":")) typed = typed.slice(0, -1);
|
|
54
|
+
const parsed = parsePublicTickerKey(typed);
|
|
55
|
+
if (parsed.exchange && option && parsed.exchange !== option && !ownExchangeWins) {
|
|
56
|
+
throw new ListingArgError(
|
|
57
|
+
`${typed} names exchange ${parsed.exchange}, but --exchange names ${option}.`,
|
|
58
|
+
`Name the exchange once, as ${parsed.symbol}:${parsed.exchange} or ${parsed.symbol} --exchange ${option}.`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
const exchange = parsed.exchange ?? option;
|
|
62
|
+
return { symbol: parsed.symbol, exchange, key: exchange ? `${parsed.symbol}:${exchange}` : parsed.symbol };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface ListingStore {
|
|
66
|
+
loadTicker(symbol: string): Promise<TickerRecord | null>;
|
|
67
|
+
loadAllTickers(): Promise<TickerRecord[]>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ListingDeps {
|
|
71
|
+
store: ListingStore;
|
|
72
|
+
dataProvider: DataProvider;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ListingVenue {
|
|
76
|
+
/** Canonical code. */
|
|
77
|
+
exchange: string;
|
|
78
|
+
name: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The venues a symbol trades on and the company on each, from the same
|
|
83
|
+
* listing picker the command bar opens for `SAN:`.
|
|
84
|
+
*/
|
|
85
|
+
export async function listingVenues(symbol: string, { store, dataProvider }: ListingDeps): Promise<ListingVenue[]> {
|
|
86
|
+
const query = `${symbol}:`;
|
|
87
|
+
if (!listingChoiceQuery(query)) return [];
|
|
88
|
+
const tickers = new Map((await store.loadAllTickers()).map((ticker) => [ticker.metadata.ticker.toUpperCase(), ticker] as const));
|
|
89
|
+
let venues: ListingVenue[];
|
|
90
|
+
try {
|
|
91
|
+
const resolved = await resolveTickerSearch({ query, activeTicker: null, tickers, dataProvider });
|
|
92
|
+
const only = !resolved ? null
|
|
93
|
+
: resolved.kind === "local" ? { exchange: resolved.ticker.metadata.exchange, name: resolved.ticker.metadata.name }
|
|
94
|
+
: {
|
|
95
|
+
exchange: resolved.result.exchange === "SMART" ? resolved.result.primaryExchange ?? "" : resolved.result.exchange || resolved.result.primaryExchange || "",
|
|
96
|
+
name: resolved.result.name,
|
|
97
|
+
};
|
|
98
|
+
venues = only?.exchange ? [{ exchange: canonicalExchange(only.exchange), name: only.name }] : [];
|
|
99
|
+
} catch (error) {
|
|
100
|
+
// One listing settles the picker; several are its choices.
|
|
101
|
+
if (!(error instanceof AmbiguousTickerError) || error instanceof AmbiguousContractError) return [];
|
|
102
|
+
venues = error.listings.flatMap((listing) => {
|
|
103
|
+
const exchange = parsePublicTickerKey(listing).exchange;
|
|
104
|
+
return exchange ? [{ exchange, name: error.listingNames[listing] ?? "" }] : [];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return venues.filter((venue, index) => venues.findIndex((other) => other.exchange === venue.exchange) === index);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function tradesOn(symbol: string, venues: readonly ListingVenue[]): string {
|
|
111
|
+
return venues.length > 0 ? ` ${symbol} trades on: ${venues.map((venue) => venue.exchange).join(", ")}.` : "";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* An exchange code the app does not know is accepted only when the symbol is
|
|
116
|
+
* listed there, so a typo never falls back to another venue's line.
|
|
117
|
+
*/
|
|
118
|
+
async function checkListingExchange(listing: ListingArg, deps: ListingDeps): Promise<void> {
|
|
119
|
+
if (listing.symbol.endsWith(":")) {
|
|
120
|
+
const symbol = listing.symbol.slice(0, -1);
|
|
121
|
+
throw new ListingArgError(`Choose an exchange for ${symbol}.${tradesOn(symbol, await listingVenues(symbol, deps))}`);
|
|
122
|
+
}
|
|
123
|
+
if (!listing.exchange || isKnownExchangeCode(listing.exchange)) return;
|
|
124
|
+
const venues = await listingVenues(listing.symbol, deps);
|
|
125
|
+
if (venues.some((venue) => venue.exchange === listing.exchange)) return;
|
|
126
|
+
throw new ListingArgError(
|
|
127
|
+
`Unknown exchange ${listing.exchange} for ${listing.symbol}.${tradesOn(listing.symbol, venues)}`,
|
|
128
|
+
venues.length > 0 ? undefined : `No listings of ${listing.symbol} were found.`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* "SAN does not trade on TSX. SAN trades on: NYSE, EPA." for a listing whose
|
|
134
|
+
* exchange the symbol is not listed on, from the same picker `SAN:` opens.
|
|
135
|
+
* Null when no exchange was named, when the symbol is listed there, or when its
|
|
136
|
+
* venues cannot be found, so the request's own failure stands. It searches, so
|
|
137
|
+
* ask only after a request came back empty.
|
|
138
|
+
*/
|
|
139
|
+
export async function notTradedMessage(
|
|
140
|
+
listing: Pick<ListingArg, "symbol" | "exchange">,
|
|
141
|
+
deps: ListingDeps,
|
|
142
|
+
): Promise<string | null> {
|
|
143
|
+
if (!listing.exchange) return null;
|
|
144
|
+
const venues = await listingVenues(listing.symbol, deps).catch(() => []);
|
|
145
|
+
if (venues.length === 0 || venues.some((venue) => venue.exchange === listing.exchange)) return null;
|
|
146
|
+
return `${listing.symbol} does not trade on ${listing.exchange}.${tradesOn(listing.symbol, venues)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Fails the command with `notTradedMessage`; returns when the symbol does trade there. */
|
|
150
|
+
export async function failIfNotTraded(
|
|
151
|
+
listing: Pick<ListingArg, "symbol" | "exchange">,
|
|
152
|
+
deps: ListingDeps,
|
|
153
|
+
ctx: Pick<CliCommandContext, "fail">,
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
const message = await notTradedMessage(listing, deps);
|
|
156
|
+
if (message) ctx.fail(message);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A data request for the listings a command named. When it throws, or `isMiss`
|
|
161
|
+
* calls what it returned empty, and a listing's exchange is one its symbol does
|
|
162
|
+
* not trade on, the command ends in that message instead of the request's own
|
|
163
|
+
* "unavailable". A request that succeeds costs no extra lookup.
|
|
164
|
+
*/
|
|
165
|
+
export async function loadForListing<T>(
|
|
166
|
+
listings: Pick<ListingArg, "symbol" | "exchange"> | readonly Pick<ListingArg, "symbol" | "exchange">[],
|
|
167
|
+
deps: ListingDeps,
|
|
168
|
+
ctx: Pick<CliCommandContext, "fail">,
|
|
169
|
+
load: () => Promise<T>,
|
|
170
|
+
isMiss?: (value: T) => boolean,
|
|
171
|
+
): Promise<T> {
|
|
172
|
+
const named = ("symbol" in listings ? [listings] : listings).filter((listing) => listing.exchange);
|
|
173
|
+
const checkVenues = () => Promise.all(named.map((listing) => failIfNotTraded(listing, deps, ctx)));
|
|
174
|
+
let value: T;
|
|
175
|
+
try {
|
|
176
|
+
value = await load();
|
|
177
|
+
} catch (error) {
|
|
178
|
+
await checkVenues();
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
if (isMiss?.(value)) await checkVenues();
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The saved ticker for a listing: under its own key, or a saved symbol whose venue it is. */
|
|
186
|
+
export async function loadSavedListing(store: ListingStore, listing: ListingArg): Promise<TickerRecord | null> {
|
|
187
|
+
if (!listing.exchange) return store.loadTicker(listing.symbol);
|
|
188
|
+
for (const key of new Set([listing.key, publicTickerKey(listing.symbol, listing.exchange), listing.symbol])) {
|
|
189
|
+
const ticker = await store.loadTicker(key);
|
|
190
|
+
if (ticker && (key === listing.key || canonicalExchange(ticker.metadata.exchange) === listing.exchange)) return ticker;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface CliListing extends ListingArg {
|
|
196
|
+
saved: TickerRecord | null;
|
|
197
|
+
/**
|
|
198
|
+
* What data requests take: a named listing goes by its key (SAN:EPA), never
|
|
199
|
+
* the bare symbol's cache; a bare symbol goes on its saved venue, as the
|
|
200
|
+
* command bar opens it.
|
|
201
|
+
*/
|
|
202
|
+
request: { symbol: string; exchange: string };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export async function resolveCliListing(
|
|
206
|
+
raw: string,
|
|
207
|
+
exchangeOption: string | null | undefined,
|
|
208
|
+
deps: ListingDeps,
|
|
209
|
+
options: { ownExchangeWins?: boolean } = {},
|
|
210
|
+
): Promise<CliListing> {
|
|
211
|
+
const listing = parseListingArg(raw, exchangeOption, options);
|
|
212
|
+
if (!listing.symbol) throw new ListingArgError("Ticker symbol is required.");
|
|
213
|
+
await checkListingExchange(listing, deps);
|
|
214
|
+
const saved = await loadSavedListing(deps.store, listing);
|
|
215
|
+
return {
|
|
216
|
+
...listing,
|
|
217
|
+
saved,
|
|
218
|
+
request: listing.exchange
|
|
219
|
+
? { symbol: listing.key, exchange: listing.exchange }
|
|
220
|
+
: { symbol: listing.symbol, exchange: saved?.metadata.exchange ?? "" },
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** `resolveCliListing` for a command: a bad exchange fails the command with its message. */
|
|
225
|
+
export async function requireCliListing(
|
|
226
|
+
raw: string,
|
|
227
|
+
exchangeOption: string | null | undefined,
|
|
228
|
+
deps: ListingDeps,
|
|
229
|
+
ctx: Pick<CliCommandContext, "fail">,
|
|
230
|
+
options: { ownExchangeWins?: boolean } = {},
|
|
231
|
+
): Promise<CliListing> {
|
|
232
|
+
try {
|
|
233
|
+
return await resolveCliListing(raw, exchangeOption, deps, options);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
if (error instanceof ListingArgError) ctx.fail(error.message, error.details);
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The listing for commands that store things by symbol (notes, alerts). The
|
|
242
|
+
* data sources are only opened to check an exchange the app does not know.
|
|
243
|
+
*/
|
|
244
|
+
export async function requireListingArg(
|
|
245
|
+
raw: string,
|
|
246
|
+
exchangeOption: string | null | undefined,
|
|
247
|
+
ctx: Pick<CliCommandContext, "fail" | "initMarketData">,
|
|
248
|
+
): Promise<ListingArg> {
|
|
249
|
+
try {
|
|
250
|
+
const listing = parseListingArg(raw, exchangeOption);
|
|
251
|
+
if (listing.symbol.endsWith(":") || (listing.exchange && !isKnownExchangeCode(listing.exchange))) {
|
|
252
|
+
await withMarketData(ctx, (market) => checkListingExchange(listing, market));
|
|
253
|
+
}
|
|
254
|
+
return listing;
|
|
255
|
+
} catch (error) {
|
|
256
|
+
if (error instanceof ListingArgError) ctx.fail(error.message, error.details);
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface ListingIdentity {
|
|
262
|
+
symbol: string;
|
|
263
|
+
/** Canonical code of the venue the data is for. */
|
|
264
|
+
exchange: string;
|
|
265
|
+
/** The listing's company, from its own quote. */
|
|
266
|
+
name: string | null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function listingIdentity(
|
|
270
|
+
listing: CliListing,
|
|
271
|
+
quote?: Pick<Quote, "name" | "listingExchangeName" | "exchangeName"> | null,
|
|
272
|
+
): ListingIdentity {
|
|
273
|
+
const quoteExchange = canonicalExchange(quote?.listingExchangeName || quote?.exchangeName);
|
|
274
|
+
const exchange = listing.exchange || quoteExchange || canonicalExchange(listing.saved?.metadata.exchange);
|
|
275
|
+
// A quote that prices another venue names another listing's company.
|
|
276
|
+
const quoteName = !quoteExchange || quoteExchange === exchange ? quote?.name?.trim() : undefined;
|
|
277
|
+
return { symbol: listing.symbol, exchange, name: quoteName || listing.saved?.metadata.name?.trim() || null };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** The listing's own quote, for its company name and venue; null when it has none. */
|
|
281
|
+
export async function loadListingQuote(dataProvider: DataProvider, listing: CliListing): Promise<Quote | null> {
|
|
282
|
+
try {
|
|
283
|
+
return await dataProvider.getQuote(listing.request.symbol, listing.request.exchange);
|
|
284
|
+
} catch {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** One line above a table naming what it is about: "Sanofi · Euronext Paris (EPA)". */
|
|
290
|
+
export function listingHeading(identity: ListingIdentity): string {
|
|
291
|
+
const venue = identity.exchange ? cliStyles.muted(` · ${exchangeLabel(identity.exchange)}`) : "";
|
|
292
|
+
return `${cliStyles.bold(identity.name || identity.symbol)}${venue}`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** "Sanofi (EPA)", for sentences. */
|
|
296
|
+
export function listingTitle(identity: ListingIdentity): string {
|
|
297
|
+
const name = identity.name || identity.symbol;
|
|
298
|
+
return identity.exchange ? `${name} (${identity.exchange})` : name;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export interface SavedListingName {
|
|
302
|
+
symbol: string;
|
|
303
|
+
/** Canonical code of the venue the row is saved for, or "" when it has none. */
|
|
304
|
+
exchange: string;
|
|
305
|
+
/** SAN:EPA, whichever way the row is stored (SAN, SAN:XNYS). */
|
|
306
|
+
key: string;
|
|
307
|
+
name: string | null;
|
|
308
|
+
/** "SAN:EPA (Sanofi)", for sentences. */
|
|
309
|
+
label: string;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** The listing a saved ticker row is, as a collection command names it after adding or removing it. */
|
|
313
|
+
export function savedListingName(ticker: TickerRecord): SavedListingName {
|
|
314
|
+
const { symbol } = parsePublicTickerKey(ticker.metadata.ticker);
|
|
315
|
+
const exchange = canonicalExchange(ticker.metadata.exchange);
|
|
316
|
+
const key = exchange ? `${symbol}:${exchange}` : symbol;
|
|
317
|
+
// A row saved without a company carries its symbol as the name.
|
|
318
|
+
const typed = ticker.metadata.name?.trim();
|
|
319
|
+
const name = typed && typed !== symbol && typed !== ticker.metadata.ticker ? typed : null;
|
|
320
|
+
return { symbol, exchange, key, name, label: name ? `${key} (${name})` : key };
|
|
321
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What keeps a pane from showing everything it has: a Pro lock on part of it,
|
|
3
|
+
* or a wall that needs an account. Reports and screenshots name it, so a
|
|
4
|
+
* failure says "locked" instead of a generic incomplete or empty.
|
|
5
|
+
*/
|
|
6
|
+
export type PaneAccessGate = "pro" | "sign-in";
|
|
7
|
+
|
|
8
|
+
// A Pro-gated loader reports what is locked in its errors ("Full history requires Gloom Pro").
|
|
9
|
+
const SIGN_IN_ERROR = /\bsign(?:ed)?[ -]?in\b|\bsignup\b|\bemail verification\b|\bverify your email\b/i;
|
|
10
|
+
const PRO_ERROR = /\bGloom (?:Cloud )?Pro\b|\b(?:requires?|needs?) Pro\b|\bPro access\b/;
|
|
11
|
+
|
|
12
|
+
function errorMessages(errors: unknown): string[] {
|
|
13
|
+
return Array.isArray(errors) ? errors.filter((error): error is string => typeof error === "string") : [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Why the output cannot be used as it is, as a clause: "some values need Gloom Cloud Pro (locked)". */
|
|
17
|
+
function accessGateReason(gate: PaneAccessGate): string {
|
|
18
|
+
return gate === "pro" ? "some values need Gloom Cloud Pro (locked)" : "it needs a Gloom Cloud sign-in";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** The reason as a sentence, for a screenshot's "Reason" row. */
|
|
22
|
+
export function accessGateSentence(gate: PaneAccessGate): string {
|
|
23
|
+
const reason = accessGateReason(gate);
|
|
24
|
+
return `${reason.charAt(0).toUpperCase()}${reason.slice(1)}.`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** The word a screenshot's status line uses in place of "empty" for a gated pane. */
|
|
28
|
+
export function accessGateStatus(gate: PaneAccessGate): string {
|
|
29
|
+
return gate === "pro" ? "locked" : "needs sign-in";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The failure for an incomplete report whose own errors name a gate, with
|
|
34
|
+
* those errors saying which values; null when they name none.
|
|
35
|
+
*/
|
|
36
|
+
export function incompleteReportGateMessage(token: string, errors: unknown): string | null {
|
|
37
|
+
const messages = errorMessages(errors);
|
|
38
|
+
const gate = messages.some((message) => SIGN_IN_ERROR.test(message)) ? "sign-in"
|
|
39
|
+
: messages.some((message) => PRO_ERROR.test(message)) ? "pro" : null;
|
|
40
|
+
const detail = messages.map((message) => message.replace(/\.+$/, "")).join(". ");
|
|
41
|
+
return gate ? `${token} is not bot-safe: ${accessGateReason(gate)}. ${detail}.` : null;
|
|
42
|
+
}
|