gloomberb 0.16.1 → 0.16.3
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 +26 -8
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +2 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +37 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +2 -0
- package/src/brokers/account-cache.ts +69 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +37 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +560 -136
- package/src/cli/commands/overview.ts +136 -48
- package/src/cli/commands/ticker.ts +220 -67
- package/src/cli/desktop-pane-shot.ts +37 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +27 -6
- package/src/cli/helpers.ts +4 -8
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index.ts +23 -8
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/options.ts +5 -1
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/capabilities.ts +5 -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 +87 -16
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +31 -22
- package/src/cli/pane-functions/headless.ts +201 -41
- package/src/cli/pane-functions/index.ts +24 -6
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +63 -9
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +11 -3
- package/src/cli/registry.ts +6 -3
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +53 -29
- 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/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/ticker-search/actions.ts +5 -0
- 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/export.ts +6 -51
- package/src/components/data-table/view.tsx +32 -11
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- 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 +11 -11
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +12 -7
- package/src/components/layout/shell/drag/live.ts +122 -0
- package/src/components/layout/shell/drag/overlays.tsx +179 -35
- package/src/components/layout/shell/drag/runtime.ts +62 -50
- package/src/components/layout/shell/drag/slide.ts +10 -0
- package/src/components/layout/shell/index.tsx +37 -51
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
- package/src/components/layout/shell/native/surfaces.ts +30 -14
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +419 -168
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/metric-treemap/heat-surface.tsx +43 -16
- package/src/components/metric-treemap/heat-tiles.ts +18 -0
- package/src/components/metric-treemap/layout.ts +2 -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/ticker/list-table-view.tsx +13 -1
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/range-track.tsx +10 -3
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +7 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/data/config/store/normalize.ts +17 -1
- package/src/data/json-persistence.ts +17 -3
- package/src/data/json-storage.ts +2 -0
- package/src/data/memory-resource-store.ts +46 -0
- package/src/i18n/es.ts +19 -1
- package/src/i18n/ja.ts +19 -1
- package/src/i18n/ko.ts +19 -1
- package/src/i18n/zh-cn.ts +19 -1
- package/src/i18n/zh-tw.ts +19 -1
- 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 +123 -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 +2 -0
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- 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/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-client.ts +191 -66
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
- package/src/plugins/builtin/analytics/risk-model.ts +45 -17
- package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
- package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
- 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 +2 -2
- 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/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -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 +2 -2
- 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/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/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +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/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/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +161 -6
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +42 -16
- package/src/plugins/builtin/holders/report-header.ts +136 -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/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -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 +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
- package/src/plugins/builtin/market-movers/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +20 -3
- package/src/plugins/builtin/members/headless.ts +5 -3
- package/src/plugins/builtin/members/model.ts +10 -2
- package/src/plugins/builtin/members/pane.tsx +23 -6
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- 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-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 +48 -3
- package/src/plugins/builtin/pe-band/headless.ts +25 -7
- package/src/plugins/builtin/pe-band/model.ts +92 -16
- package/src/plugins/builtin/pe-band/pane.tsx +33 -16
- package/src/plugins/builtin/perps/client.ts +50 -3
- 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 +249 -48
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -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 +232 -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 +100 -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 +53 -16
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -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 +18 -6
- 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/reverse-dcf/model.ts +2 -1
- 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/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/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/members-menu.tsx +260 -0
- 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/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/pane.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/themes/pane.tsx +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- 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 +159 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -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 +448 -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 +69 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
- package/src/plugins/builtin/world-venue-map/model.ts +23 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -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 +35 -44
- 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/loader.ts +13 -1
- package/src/plugins/registry/pane-settings.ts +1 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/data-table/row.tsx +2 -0
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- 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 +113 -17
- package/src/renderers/dom/host/drag-shield.ts +24 -0
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/live-frame.ts +54 -0
- package/src/renderers/dom/host/mouse.ts +8 -1
- package/src/renderers/dom/host/scroll-box.tsx +6 -5
- package/src/renderers/dom/host/tabs.tsx +3 -2
- package/src/renderers/dom/styles.css +16 -9
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -1
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
- package/src/renderers/electrobun/view/host/native.ts +0 -10
- package/src/renderers/electrobun/view/host/window-move.ts +28 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financial-routes.ts +2 -2
- package/src/sources/provider-router/financials.ts +76 -12
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/provider-router/primary.ts +2 -2
- 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/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/margin-account.ts +108 -0
- package/src/theme/heat-colors.ts +266 -84
- package/src/time-series/resolution.ts +15 -0
- 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 +35 -3
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +20 -1
- package/src/types/ticker.ts +15 -0
- package/src/ui/host.tsx +26 -0
- package/src/ui/index.tsx +8 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/updater/index.ts +9 -11
- 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 +19 -0
- package/src/utils/depositary-receipt.ts +70 -0
- package/src/utils/display-number.ts +63 -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/fundamentals.ts +17 -1
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history-integrity.ts +19 -6
- 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
|
@@ -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
|
+
}
|
package/src/cli/options.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface ParsedCliArgs {
|
|
|
15
15
|
options: CliGlobalOptions;
|
|
16
16
|
/** `--help` or `-h` appeared before `--`. The flag is removed from args. */
|
|
17
17
|
help: boolean;
|
|
18
|
+
/** Index in `args` where the arguments after a bare `--` begin; they are never options. */
|
|
19
|
+
literalStart: number;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export function isCliHelpFlag(arg: string): boolean {
|
|
@@ -43,10 +45,12 @@ export function parseCliGlobalArgs(rawArgs: string[]): ParsedCliArgs {
|
|
|
43
45
|
const options: CliGlobalOptions = { ...DEFAULT_CLI_OPTIONS };
|
|
44
46
|
const args: string[] = [];
|
|
45
47
|
let help = false;
|
|
48
|
+
let literalStart: number | null = null;
|
|
46
49
|
|
|
47
50
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
48
51
|
const arg = rawArgs[index]!;
|
|
49
52
|
if (arg === "--") {
|
|
53
|
+
literalStart = args.length;
|
|
50
54
|
args.push(...rawArgs.slice(index + 1));
|
|
51
55
|
break;
|
|
52
56
|
}
|
|
@@ -102,5 +106,5 @@ export function parseCliGlobalArgs(rawArgs: string[]): ParsedCliArgs {
|
|
|
102
106
|
args.push(arg);
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
return { args, options, help };
|
|
109
|
+
return { args, options, help, literalStart: literalStart ?? args.length };
|
|
106
110
|
}
|
|
@@ -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
|
+
}
|
|
@@ -134,6 +134,11 @@ function resolveOptionDef(
|
|
|
134
134
|
));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
/** Whether the function has an option of its own under this name or an alias. */
|
|
138
|
+
export function capabilityHasOption(capability: PaneFunctionCapability, key: string): boolean {
|
|
139
|
+
return resolveOptionDef(capability, key) !== undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
137
142
|
function normalizeEnumValue(option: PaneFunctionOptionDef, rawValue: string): string {
|
|
138
143
|
const token = optionToken(rawValue);
|
|
139
144
|
const match = option.values?.find((candidate) => (
|
|
@@ -199,6 +199,30 @@ export async function buildPaneCatalogEntries(
|
|
|
199
199
|
return entries.sort((left, right) => left.token.localeCompare(right.token));
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/** The phrase starting a word of the text, so "funding rate" finds "funding rates" but "rate" is not found in "separate". */
|
|
203
|
+
function containsPhrase(text: string, phrase: string): boolean {
|
|
204
|
+
for (let at = text.indexOf(phrase); at >= 0; at = text.indexOf(phrase, at + 1)) {
|
|
205
|
+
if (at === 0 || !/[a-z0-9]/.test(text[at - 1]!)) return true;
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// A multi-word query ranks a function carrying the whole phrase in its name or keywords first, then in its
|
|
211
|
+
// description, then one matching every word somewhere; the rest rank by how many words they match.
|
|
212
|
+
const PHRASE_IN_NAME_BAND = 4000;
|
|
213
|
+
const PHRASE_IN_DESCRIPTION_BAND = 3000;
|
|
214
|
+
const ALL_WORDS_BAND = 2000;
|
|
215
|
+
const PER_MATCHED_WORD = 100;
|
|
216
|
+
|
|
217
|
+
function phraseBand(entry: PaneCatalogEntry, phrase: string): number {
|
|
218
|
+
const lower = (values: Array<string | undefined>) => values
|
|
219
|
+
.filter((value): value is string => !!value).map((value) => value.toLowerCase().replace(/\s+/g, " "));
|
|
220
|
+
const names = lower([entry.token, entry.label, entry.paneName, entry.shortcut, ...entry.aliases, ...entry.keywords, ...entry.capability.aliases]);
|
|
221
|
+
if (names.some((name) => containsPhrase(name, phrase))) return PHRASE_IN_NAME_BAND;
|
|
222
|
+
const descriptions = lower([entry.description, ...entry.capability.intents]);
|
|
223
|
+
return descriptions.some((description) => containsPhrase(description, phrase)) ? PHRASE_IN_DESCRIPTION_BAND : 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
202
226
|
function paneCatalogSearchScore(entry: PaneCatalogEntry, query: string): number {
|
|
203
227
|
const terms = query.toLowerCase().split(/\s+/).map((term) => term.trim()).filter(Boolean);
|
|
204
228
|
if (terms.length === 0) return 1;
|
|
@@ -253,7 +277,10 @@ function paneCatalogSearchScore(entry: PaneCatalogEntry, query: string): number
|
|
|
253
277
|
if (matchedTerms === 0) return 0;
|
|
254
278
|
score += Math.round((matchedTerms / terms.length) * 8);
|
|
255
279
|
if (entry.capability.botSafe) score += 2;
|
|
256
|
-
|
|
280
|
+
// One word has no phrase to prefer: it keeps the plain term scores.
|
|
281
|
+
if (terms.length === 1) return score;
|
|
282
|
+
const band = phraseBand(entry, terms.join(" "));
|
|
283
|
+
return score + matchedTerms * PER_MATCHED_WORD + (band || (matchedTerms === terms.length ? ALL_WORDS_BAND : 0));
|
|
257
284
|
}
|
|
258
285
|
|
|
259
286
|
export function filterPaneCatalogEntries(entries: PaneCatalogEntry[], query: string): PaneCatalogEntry[] {
|
|
@@ -182,5 +182,7 @@ export function collectShotSymbols(resolved: ResolvedPaneFunction, rawArg: strin
|
|
|
182
182
|
if (resolved.capability.id === "security-relationship" && symbols.length === 1) {
|
|
183
183
|
symbols = [...symbols, "SPY"];
|
|
184
184
|
}
|
|
185
|
-
|
|
185
|
+
// Entries a ticker list keeps as typed (CORR's GEO:HORMUZ) are not tickers to fetch.
|
|
186
|
+
const keep = resolved.template?.shortcut?.keepArgToken;
|
|
187
|
+
return [...new Set(symbols.filter((symbol) => !keep?.(symbol)).map(cleanTickerInput).filter(Boolean))];
|
|
186
188
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { DesktopPaneShotRenderedRow } from "../desktop-pane-shot";
|
|
2
|
-
import { renderSection, renderTable } from "../../utils/cli-output";
|
|
2
|
+
import { cliStyles, renderSection, renderTable } from "../../utils/cli-output";
|
|
3
|
+
import { formatUtcTime } from "../../utils/utc-time";
|
|
3
4
|
import type { MarketContext } from "../types";
|
|
4
5
|
import type { PaneFunctionReport } from "./report";
|
|
5
6
|
import type { ResolvedPaneFunction } from "./resolver";
|
|
6
7
|
import { collectShotSymbols } from "./data";
|
|
7
8
|
import { renderDesktopShot, type PaneScreenshotResult } from "./screenshot";
|
|
9
|
+
import { deriveRenderedFreshness, formatFreshnessLine, type ReportFreshness } from "./freshness";
|
|
10
|
+
import { exportTextTable, reportFooterLines, type CliReportTables } from "../report-tables";
|
|
8
11
|
|
|
9
12
|
const DOM_REPORT_WIDTH = 1280;
|
|
10
13
|
const DOM_REPORT_HEIGHT = 720;
|
|
@@ -32,7 +35,21 @@ function domCellKeys(row: DesktopPaneShotRenderedRow): string[] {
|
|
|
32
35
|
});
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
/**
|
|
39
|
+
* A pane may shorten a time to fit ("Wed 11:27", "Oct 2"); the report prints
|
|
40
|
+
* the instant behind it with its date and zone instead.
|
|
41
|
+
*/
|
|
42
|
+
function cellText(cell: DesktopPaneShotRenderedRow["cells"][number]): string {
|
|
43
|
+
return cell.instant ? formatUtcTime(cell.instant) || cell.text : cell.text;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface DomTable {
|
|
47
|
+
tableIndex: number;
|
|
48
|
+
columns: Array<{ key: string; header: string }>;
|
|
49
|
+
rows: Array<Map<string, DesktopPaneShotRenderedRow["cells"][number]>>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function domTables(rows: DesktopPaneShotRenderedRow[]): DomTable[] {
|
|
36
53
|
const byTable = new Map<number, DesktopPaneShotRenderedRow[]>();
|
|
37
54
|
for (const row of rows) {
|
|
38
55
|
const tableRows = byTable.get(row.tableIndex) ?? [];
|
|
@@ -40,7 +57,7 @@ function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
|
40
57
|
byTable.set(row.tableIndex, tableRows);
|
|
41
58
|
}
|
|
42
59
|
|
|
43
|
-
return [...byTable.entries()].
|
|
60
|
+
return [...byTable.entries()].map(([tableIndex, tableRows]) => {
|
|
44
61
|
// Captured rows omit blank cells, so a cell's position is not its column.
|
|
45
62
|
const columns: Array<{ key: string; header: string }> = [];
|
|
46
63
|
for (const row of tableRows) {
|
|
@@ -56,22 +73,54 @@ function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
|
56
73
|
previous = position;
|
|
57
74
|
}
|
|
58
75
|
}
|
|
59
|
-
|
|
76
|
+
return {
|
|
77
|
+
tableIndex,
|
|
60
78
|
columns,
|
|
61
|
-
tableRows.map((row) => {
|
|
79
|
+
rows: tableRows.map((row) => {
|
|
62
80
|
const keys = domCellKeys(row);
|
|
63
|
-
|
|
64
|
-
return columns.map((column) => textByKey.get(column.key) ?? "");
|
|
81
|
+
return new Map(row.cells.map((cell, cellIndex) => [keys[cellIndex]!, cell]));
|
|
65
82
|
}),
|
|
66
|
-
|
|
67
|
-
return [
|
|
68
|
-
...(index > 0 ? [""] : []),
|
|
69
|
-
...(byTable.size > 1 ? [renderSection(`Rendered table ${tableIndex + 1}`)] : []),
|
|
70
|
-
output,
|
|
71
|
-
];
|
|
83
|
+
};
|
|
72
84
|
});
|
|
73
85
|
}
|
|
74
86
|
|
|
87
|
+
function domTableTitle(table: DomTable): string {
|
|
88
|
+
return `Rendered table ${table.tableIndex + 1}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
92
|
+
const tables = domTables(rows);
|
|
93
|
+
return tables.flatMap((table, index) => [
|
|
94
|
+
...(index > 0 ? [""] : []),
|
|
95
|
+
...(tables.length > 1 ? [renderSection(domTableTitle(table))] : []),
|
|
96
|
+
renderTable(
|
|
97
|
+
table.columns,
|
|
98
|
+
table.rows.map((cells) => table.columns.map((column) => {
|
|
99
|
+
const cell = cells.get(column.key);
|
|
100
|
+
return cell ? cellText(cell) : "";
|
|
101
|
+
})),
|
|
102
|
+
),
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** The rendered tables as `--csv` writes them, with the instant behind a shortened time. */
|
|
107
|
+
function domReportTables(
|
|
108
|
+
rows: DesktopPaneShotRenderedRow[],
|
|
109
|
+
title: string,
|
|
110
|
+
freshness: ReportFreshness,
|
|
111
|
+
incomplete: boolean | string,
|
|
112
|
+
): CliReportTables {
|
|
113
|
+
const tables = domTables(rows);
|
|
114
|
+
return {
|
|
115
|
+
tables: tables.map((table) => exportTextTable(
|
|
116
|
+
tables.length > 1 ? domTableTitle(table) : title,
|
|
117
|
+
table.columns.map((column) => column.header),
|
|
118
|
+
table.rows.map((cells) => table.columns.map((column) => cells.get(column.key))),
|
|
119
|
+
)),
|
|
120
|
+
footer: reportFooterLines({ freshness, incomplete }),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
75
124
|
function renderedFailureReason(
|
|
76
125
|
result: PaneScreenshotResult,
|
|
77
126
|
rows: DesktopPaneShotRenderedRow[],
|
|
@@ -129,7 +178,12 @@ export function buildDomPaneReportFromRender(
|
|
|
129
178
|
textLines.push(failureReason ?? "No rendered values were available.");
|
|
130
179
|
}
|
|
131
180
|
if (failureReason && rows.length > 0) textLines.push("", failureReason);
|
|
181
|
+
const freshness = deriveRenderedFreshness(resolved.pane.reportFreshness, {
|
|
182
|
+
footerText: result.render.footerText ?? "",
|
|
183
|
+
cellTimes: rows.flatMap((row) => row.cells.flatMap((cell) => cell.instant ?? [])),
|
|
184
|
+
});
|
|
132
185
|
|
|
186
|
+
const complete = failureReason === null && !truncated;
|
|
133
187
|
return {
|
|
134
188
|
data: {
|
|
135
189
|
kind: "rendered-view",
|
|
@@ -139,7 +193,7 @@ export function buildDomPaneReportFromRender(
|
|
|
139
193
|
options: resolved.options,
|
|
140
194
|
rowCount: rows.length,
|
|
141
195
|
empty: rows.length === 0,
|
|
142
|
-
complete
|
|
196
|
+
complete,
|
|
143
197
|
unavailableSymbols,
|
|
144
198
|
rows,
|
|
145
199
|
visibleText: result.render.visibleText,
|
|
@@ -147,8 +201,15 @@ export function buildDomPaneReportFromRender(
|
|
|
147
201
|
truncationReasons,
|
|
148
202
|
limitation: DOM_LIMITATION,
|
|
149
203
|
...(failureReason ? { reason: failureReason } : {}),
|
|
204
|
+
freshness,
|
|
150
205
|
},
|
|
151
206
|
text: textLines.join("\n").trimEnd(),
|
|
207
|
+
tables: domReportTables(
|
|
208
|
+
rows,
|
|
209
|
+
resolved.label,
|
|
210
|
+
freshness,
|
|
211
|
+
!complete && (failureReason ?? (truncationReasons.length > 0 ? truncationReasons.join("; ") : true)),
|
|
212
|
+
),
|
|
152
213
|
};
|
|
153
214
|
}
|
|
154
215
|
|
|
@@ -156,15 +217,22 @@ export function appendDomReportFooter(
|
|
|
156
217
|
text: string,
|
|
157
218
|
elapsedMs: number,
|
|
158
219
|
truncated: boolean,
|
|
220
|
+
freshness: ReportFreshness,
|
|
159
221
|
): string {
|
|
160
|
-
const clipping = truncated ? "The rendered view is clipped." : "The rendered view may be clipped.";
|
|
161
222
|
return [
|
|
162
223
|
text,
|
|
163
224
|
"",
|
|
164
|
-
|
|
225
|
+
domReportNote(elapsedMs, truncated),
|
|
226
|
+
cliStyles.muted(formatFreshnessLine(freshness)),
|
|
165
227
|
].join("\n");
|
|
166
228
|
}
|
|
167
229
|
|
|
230
|
+
/** What a rendered-view report says about where its values come from. */
|
|
231
|
+
export function domReportNote(elapsedMs: number, truncated: boolean): string {
|
|
232
|
+
const clipping = truncated ? "The rendered view is clipped." : "The rendered view may be clipped.";
|
|
233
|
+
return `Rendered view: values come from the visible pane. ${clipping} Render time: ${elapsedMs} ms.`;
|
|
234
|
+
}
|
|
235
|
+
|
|
168
236
|
function failedDomReport(
|
|
169
237
|
resolved: ResolvedPaneFunction,
|
|
170
238
|
rawArg: string,
|
|
@@ -176,6 +244,7 @@ function failedDomReport(
|
|
|
176
244
|
.trim();
|
|
177
245
|
const reason = `The rendered view could not be read: ${message || "unknown renderer error"}`;
|
|
178
246
|
const symbols = collectShotSymbols(resolved, rawArg);
|
|
247
|
+
const freshness = deriveRenderedFreshness(resolved.pane.reportFreshness, { footerText: "", cellTimes: [] });
|
|
179
248
|
return {
|
|
180
249
|
data: {
|
|
181
250
|
kind: "rendered-view",
|
|
@@ -193,8 +262,10 @@ function failedDomReport(
|
|
|
193
262
|
truncationReasons: [],
|
|
194
263
|
limitation: DOM_LIMITATION,
|
|
195
264
|
reason,
|
|
265
|
+
freshness,
|
|
196
266
|
},
|
|
197
267
|
text: [resolved.label, "", reason].join("\n"),
|
|
268
|
+
tables: { tables: [], footer: reportFooterLines({ freshness, incomplete: reason }) },
|
|
198
269
|
};
|
|
199
270
|
}
|
|
200
271
|
|