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
package/src/utils/exchanges.ts
CHANGED
|
@@ -225,6 +225,78 @@ export const EXCHANGE_TIME_ZONES: Record<string, string> = {
|
|
|
225
225
|
CCC: "UTC",
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Venue names by canonical code, for output that names the listing a command
|
|
230
|
+
* resolved ("Euronext Paris (EPA)"). Codes whose name is the code itself
|
|
231
|
+
* (NASDAQ, BSE) are left out.
|
|
232
|
+
*/
|
|
233
|
+
const EXCHANGE_NAMES: Record<string, string> = {
|
|
234
|
+
NYSE: "New York Stock Exchange",
|
|
235
|
+
AMEX: "NYSE American",
|
|
236
|
+
ARCA: "NYSE Arca",
|
|
237
|
+
BATS: "Cboe BZX",
|
|
238
|
+
OTC: "OTC Markets",
|
|
239
|
+
JPX: "Tokyo Stock Exchange",
|
|
240
|
+
HKEX: "Hong Kong Stock Exchange",
|
|
241
|
+
LSE: "London Stock Exchange",
|
|
242
|
+
TSX: "Toronto Stock Exchange",
|
|
243
|
+
TSXV: "TSX Venture Exchange",
|
|
244
|
+
CSE: "Canadian Securities Exchange",
|
|
245
|
+
NEO: "Cboe Canada",
|
|
246
|
+
ASX: "Australian Securities Exchange",
|
|
247
|
+
CXA: "Cboe Australia",
|
|
248
|
+
NZX: "New Zealand Exchange",
|
|
249
|
+
SWX: "SIX Swiss Exchange",
|
|
250
|
+
XETRA: "Xetra",
|
|
251
|
+
FWB2: "Frankfurt Stock Exchange",
|
|
252
|
+
EPA: "Euronext Paris",
|
|
253
|
+
AMS: "Euronext Amsterdam",
|
|
254
|
+
BRU: "Euronext Brussels",
|
|
255
|
+
LIS: "Euronext Lisbon",
|
|
256
|
+
BIT: "Borsa Italiana",
|
|
257
|
+
MCE: "Bolsa de Madrid",
|
|
258
|
+
SFB: "Nasdaq Stockholm",
|
|
259
|
+
HEL: "Nasdaq Helsinki",
|
|
260
|
+
CPH: "Nasdaq Copenhagen",
|
|
261
|
+
OSL: "Euronext Oslo",
|
|
262
|
+
ICEX: "Nasdaq Iceland",
|
|
263
|
+
WSE: "Warsaw Stock Exchange",
|
|
264
|
+
PSE: "Prague Stock Exchange",
|
|
265
|
+
VIE: "Vienna Stock Exchange",
|
|
266
|
+
TWSE: "Taiwan Stock Exchange",
|
|
267
|
+
TPEX: "Taipei Exchange",
|
|
268
|
+
NSE: "National Stock Exchange of India",
|
|
269
|
+
BSE: "BSE India",
|
|
270
|
+
SSE: "Shanghai Stock Exchange",
|
|
271
|
+
SZSE: "Shenzhen Stock Exchange",
|
|
272
|
+
KRX: "Korea Exchange",
|
|
273
|
+
SGX: "Singapore Exchange",
|
|
274
|
+
BMV: "Mexican Stock Exchange",
|
|
275
|
+
BYMA: "Bolsas y Mercados Argentinos",
|
|
276
|
+
JSE: "Johannesburg Stock Exchange",
|
|
277
|
+
TASE: "Tel Aviv Stock Exchange",
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const KNOWN_EXCHANGE_CODES: ReadonlySet<string> = new Set([
|
|
281
|
+
...Object.keys(CANONICAL_EXCHANGE_ALIASES),
|
|
282
|
+
...Object.values(CANONICAL_EXCHANGE_ALIASES),
|
|
283
|
+
...Object.keys(EXCHANGE_TIME_ZONES),
|
|
284
|
+
...Object.keys(EXCHANGE_NAMES),
|
|
285
|
+
]);
|
|
286
|
+
|
|
287
|
+
/** Whether a code (any spelling the alias table takes) names a venue the app knows. */
|
|
288
|
+
export function isKnownExchangeCode(value?: string): boolean {
|
|
289
|
+
const normalized = normalizeExchange(value);
|
|
290
|
+
return !!normalized && KNOWN_EXCHANGE_CODES.has(normalized);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** "Euronext Paris (EPA)" for a venue with a name, the canonical code otherwise. */
|
|
294
|
+
export function exchangeLabel(value?: string): string {
|
|
295
|
+
const code = canonicalExchange(value);
|
|
296
|
+
const name = EXCHANGE_NAMES[code];
|
|
297
|
+
return name ? `${name} (${code})` : code;
|
|
298
|
+
}
|
|
299
|
+
|
|
228
300
|
export function normalizeSymbol(value: string): string {
|
|
229
301
|
return value.trim().toUpperCase();
|
|
230
302
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { reportCrash } from "../telemetry/crash-reports";
|
|
2
|
+
import { debugLog } from "./debug-log";
|
|
3
|
+
import { RpcTimeoutError } from "./rpc-timeout-error";
|
|
4
|
+
|
|
5
|
+
const log = debugLog.createLogger("desktop-rpc");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Starts a desktop bridge call nobody awaits without leaving its rejection
|
|
9
|
+
* unhandled. A timed-out request is logged and reported once per session
|
|
10
|
+
* (never as a crash when the machine slept, see `reportCrash`) and swallowed:
|
|
11
|
+
* the next state change sends a fresh snapshot anyway. Any other error is
|
|
12
|
+
* rethrown, so a programming error still surfaces as an unhandled rejection.
|
|
13
|
+
*
|
|
14
|
+
* `onFailure` runs for every failure, so a caller that remembers what it
|
|
15
|
+
* already sent can forget it and send again.
|
|
16
|
+
*/
|
|
17
|
+
export function fireAndForget(request: Promise<unknown> | undefined, label: string, onFailure?: () => void): void {
|
|
18
|
+
request?.catch((error: unknown) => {
|
|
19
|
+
onFailure?.();
|
|
20
|
+
if (!(error instanceof RpcTimeoutError)) throw error;
|
|
21
|
+
log.warn(`${label} did not complete: ${error.message}`);
|
|
22
|
+
reportCrash(error, { kind: "unhandled-rejection" });
|
|
23
|
+
});
|
|
24
|
+
}
|
package/src/utils/format.ts
CHANGED
|
@@ -130,6 +130,19 @@ export function formatNumber(value: number | undefined, decimals = 2): string {
|
|
|
130
130
|
return getNumberFormatter(decimals).format(value);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
/**
|
|
134
|
+
* A value to a count of significant digits, so a small ratio keeps its leading
|
|
135
|
+
* digits (0.0005664, not 0.0006) while a large one reads as a plain number
|
|
136
|
+
* (1,235). Decimals follow the rounded value, so 9.9996 reads 10.00.
|
|
137
|
+
*/
|
|
138
|
+
export function formatSignificant(value: number | undefined, digits = 4): string {
|
|
139
|
+
if (value == null || !Number.isFinite(value)) return formatNumber(undefined);
|
|
140
|
+
if (value === 0) return getNumberFormatter(0).format(0);
|
|
141
|
+
const rounded = Number(value.toPrecision(digits));
|
|
142
|
+
const decimals = Math.min(12, Math.max(0, digits - 1 - Math.floor(Math.log10(Math.abs(rounded)))));
|
|
143
|
+
return getNumberFormatter(decimals).format(rounded);
|
|
144
|
+
}
|
|
145
|
+
|
|
133
146
|
/** A percentile rank with its window: "73 pctl 1Y", "-- pctl 1Y" when unranked, "73 pctl" without a window. */
|
|
134
147
|
export function formatPercentileRank(value: number | null | undefined, window?: string): string {
|
|
135
148
|
const rank = value == null || !Number.isFinite(value) ? "--" : value.toFixed(0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Fundamentals } from "../types/financials";
|
|
1
|
+
import type { Fundamentals, TickerFinancials } from "../types/financials";
|
|
2
2
|
|
|
3
3
|
export const RETRACTABLE_VALUATION_FIELDS = ["enterpriseValue", "enterpriseToRevenue"] as const;
|
|
4
4
|
|
|
@@ -13,3 +13,19 @@ export function redactUnavailableFundamentals(value: Fundamentals | undefined):
|
|
|
13
13
|
for (const field of unavailableFields) delete result[field];
|
|
14
14
|
return result;
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
/** A source's enterprise value, or undefined when it has none: banks and insurers come back as 0, which is a gap, not a value. */
|
|
18
|
+
export function reportedEnterpriseValue(fundamentals: Pick<Fundamentals, "enterpriseValue"> | undefined): number | undefined {
|
|
19
|
+
const value = fundamentals?.enterpriseValue;
|
|
20
|
+
return typeof value === "number" && Number.isFinite(value) && value !== 0 ? value : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The currency of the trailing EPS, revenue, income and cash flows: the one the fundamentals declare, else the
|
|
25
|
+
* one the statements report in. Never the quote's, which a depositary receipt can differ from (USD quote, TWD books).
|
|
26
|
+
*/
|
|
27
|
+
export function fundamentalsCurrency(
|
|
28
|
+
financials: Pick<TickerFinancials, "fundamentals" | "financialCurrency"> | null | undefined,
|
|
29
|
+
): string | undefined {
|
|
30
|
+
return financials?.fundamentals?.financialCurrency?.trim() || financials?.financialCurrency?.trim() || undefined;
|
|
31
|
+
}
|
|
@@ -1,13 +1,80 @@
|
|
|
1
|
+
import type { Fundamentals } from "../types/financials";
|
|
1
2
|
import { formatNumber } from "./format";
|
|
2
3
|
|
|
3
4
|
export const PRICE_EARNINGS_NOTICE = "N/M = not meaningful. Non-positive P/E values are excluded from ranking.";
|
|
4
5
|
|
|
6
|
+
/** A multiple over a loss or zero base: there is no number to show, rank or export. */
|
|
7
|
+
export const NOT_MEANINGFUL = "not-meaningful";
|
|
8
|
+
export type PriceEarnings = number | typeof NOT_MEANINGFUL;
|
|
9
|
+
|
|
10
|
+
function nonPositive(value: number | null | undefined): boolean {
|
|
11
|
+
return typeof value === "number" && Number.isFinite(value) && value <= 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A P/E checked against the earnings it divides by. Zero or negative earnings
|
|
16
|
+
* make it not meaningful whatever multiple a source served beside them: a
|
|
17
|
+
* source P/E priced at an older, profitable period stays positive after the
|
|
18
|
+
* trailing EPS turns into a loss (MSTR's 5.47 beside EPS -99.08). Unknown
|
|
19
|
+
* earnings leave the multiple as served.
|
|
20
|
+
*/
|
|
21
|
+
export function priceEarningsOnEarnings(
|
|
22
|
+
multiple: number | null | undefined,
|
|
23
|
+
earnings: number | null | undefined,
|
|
24
|
+
): PriceEarnings | undefined {
|
|
25
|
+
if (nonPositive(earnings)) return NOT_MEANINGFUL;
|
|
26
|
+
return typeof multiple === "number" && Number.isFinite(multiple) ? multiple : undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
5
29
|
/** Negative earnings do not make a security cheaper than a profitable peer. */
|
|
6
|
-
export function comparablePriceEarnings(value:
|
|
7
|
-
return value
|
|
30
|
+
export function comparablePriceEarnings(value: PriceEarnings | null | undefined): number | null {
|
|
31
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
8
32
|
}
|
|
9
33
|
|
|
10
|
-
|
|
34
|
+
/** P/E, forward P/E or PEG: N/M below zero, as the multiple says nothing there. */
|
|
35
|
+
export function formatPriceEarnings(value: PriceEarnings | null | undefined, precision = 1): string {
|
|
36
|
+
if (value === NOT_MEANINGFUL) return "N/M";
|
|
11
37
|
if (value == null || !Number.isFinite(value)) return "—";
|
|
12
38
|
return value <= 0 ? "N/M" : formatNumber(value, precision);
|
|
13
39
|
}
|
|
40
|
+
|
|
41
|
+
type PriceEarningsField = "trailingPE" | "forwardPE" | "pegRatio";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Why each earnings multiple of a fundamentals block is not meaningful, if it
|
|
45
|
+
* is not: a trailing or forward EPS at or below zero, or a multiple that is
|
|
46
|
+
* itself at or below zero. Forward P/E is judged on its own estimate only, so
|
|
47
|
+
* a trailing loss leaves a positive forward multiple alone.
|
|
48
|
+
*/
|
|
49
|
+
export function notMeaningfulMultiples(
|
|
50
|
+
fundamentals: Pick<Fundamentals, PriceEarningsField | "eps" | "forwardEps"> | undefined,
|
|
51
|
+
): Partial<Record<PriceEarningsField, string>> {
|
|
52
|
+
const reasons: Partial<Record<PriceEarningsField, string>> = {};
|
|
53
|
+
if (!fundamentals) return reasons;
|
|
54
|
+
if (nonPositive(fundamentals.eps)) reasons.trailingPE = "trailing EPS is not positive";
|
|
55
|
+
else if (nonPositive(fundamentals.trailingPE)) reasons.trailingPE = "trailing earnings are not positive";
|
|
56
|
+
if (nonPositive(fundamentals.forwardEps)) reasons.forwardPE = "forward EPS is not positive";
|
|
57
|
+
else if (nonPositive(fundamentals.forwardPE)) reasons.forwardPE = "forward earnings are not positive";
|
|
58
|
+
if (nonPositive(fundamentals.pegRatio)) reasons.pegRatio = "P/E or expected growth is not positive";
|
|
59
|
+
return reasons;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The fundamentals block as JSON exports it: a multiple that is not meaningful
|
|
64
|
+
* reads null, with the reason under `notMeaningful`, never as a number.
|
|
65
|
+
*/
|
|
66
|
+
export function exportedFundamentals<T extends Fundamentals>(
|
|
67
|
+
fundamentals: T | undefined,
|
|
68
|
+
): (Omit<T, PriceEarningsField> & Partial<Record<PriceEarningsField, number | null>> & {
|
|
69
|
+
notMeaningful?: Partial<Record<PriceEarningsField, string>>;
|
|
70
|
+
}) | undefined {
|
|
71
|
+
if (!fundamentals) return fundamentals;
|
|
72
|
+
const reasons = notMeaningfulMultiples(fundamentals);
|
|
73
|
+
const fields = Object.keys(reasons) as PriceEarningsField[];
|
|
74
|
+
if (fields.length === 0) return fundamentals;
|
|
75
|
+
return {
|
|
76
|
+
...fundamentals,
|
|
77
|
+
...Object.fromEntries(fields.map((field) => [field, null])),
|
|
78
|
+
notMeaningful: reasons,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -27,13 +27,26 @@ function above(left: number, right: number): boolean {
|
|
|
27
27
|
return left - right > 8 * Number.EPSILON * Math.max(Math.abs(left), Math.abs(right));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Each way a bar's prices contradict each other, as short codes such as
|
|
32
|
+
* `high<open` or `low>close`; empty when they agree. Missing OHLC fields are
|
|
33
|
+
* not contradictory: close-only histories remain usable.
|
|
34
|
+
*/
|
|
35
|
+
export function pricePointIntegrityFlags(point: PricePoint): string[] {
|
|
32
36
|
const { open, high, low, close } = point;
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
const flags: string[] = [];
|
|
38
|
+
for (const [name, value] of [["open", open], ["close", close]] as const) {
|
|
39
|
+
if (isFiniteNumber(value) && isFiniteNumber(high) && above(value, high)) flags.push(`high<${name}`);
|
|
40
|
+
}
|
|
41
|
+
for (const [name, value] of [["open", open], ["close", close]] as const) {
|
|
42
|
+
if (isFiniteNumber(value) && isFiniteNumber(low) && above(low, value)) flags.push(`low>${name}`);
|
|
43
|
+
}
|
|
44
|
+
if (isFiniteNumber(high) && isFiniteNumber(low) && above(low, high)) flags.push("low>high");
|
|
45
|
+
return flags;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function pricePointIntegrity(point: PricePoint): PriceHistoryIntegrity | undefined {
|
|
49
|
+
if (pricePointIntegrityFlags(point).length === 0) return undefined;
|
|
37
50
|
const date = new Date(point.date);
|
|
38
51
|
return Object.freeze({
|
|
39
52
|
reason: "inconsistent-ohlc",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PricePoint, TickerFinancials } from "../types/financials";
|
|
2
2
|
import { canonicalExchange, resolveExchangeTimeZone } from "./exchanges";
|
|
3
|
+
import { isRoundTheClockCoin } from "./crypto-pair";
|
|
3
4
|
import { hasPublishedSessionCalendar, isRegularSessionTime, isTimestampStaleForExchangeSession, latestRegularSessionClose, latestRegularSessionOpen, sessionCalendarTimeZone } from "../market-data/market/freshness";
|
|
4
5
|
import { zonedDateTimeParts } from "./zoned-date-time";
|
|
5
6
|
import { regularHistorySessionStaleness } from "../market-data/history-session";
|
|
@@ -10,9 +11,20 @@ const MAX_CURRENT_INTRADAY_HISTORY_LAG_MS = 18 * 60 * 60 * 1000;
|
|
|
10
11
|
const MAX_SAME_SESSION_HISTORY_LAG_MS = 30 * 60 * 1000;
|
|
11
12
|
const DELAYED_HISTORY_ALLOWANCE_MS = 15 * 60 * 1000;
|
|
12
13
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
14
|
+
// A series that never closes must reach the present without a break: no hole
|
|
15
|
+
// this long (or three bars, if larger) in the stretch before now that a
|
|
16
|
+
// current window is read over.
|
|
17
|
+
const ROUND_THE_CLOCK_RECENT_MS = 6 * 60 * 60 * 1000;
|
|
18
|
+
const ROUND_THE_CLOCK_GAP_MS = 2 * 60 * 60 * 1000;
|
|
13
19
|
|
|
14
20
|
interface PriceHistoryFreshnessOptions {
|
|
15
21
|
exchange?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The listing's symbol. A coin quoted in dollars (BTC-USD) trades around the
|
|
24
|
+
* clock whether or not the exchange says CCC; without the symbol a bare
|
|
25
|
+
* pair is read as a US listing and judged on the NYSE session.
|
|
26
|
+
*/
|
|
27
|
+
symbol?: string;
|
|
16
28
|
intervalMs?: number | null;
|
|
17
29
|
session?: HistorySession;
|
|
18
30
|
}
|
|
@@ -140,6 +152,29 @@ function normalizePriceHistoryUncached(points: PricePoint[]): PricePoint[] {
|
|
|
140
152
|
return validPoints.length === points.length ? points : validPoints;
|
|
141
153
|
}
|
|
142
154
|
|
|
155
|
+
/**
|
|
156
|
+
* A round-the-clock series is current while its latest bar is within two bars
|
|
157
|
+
* and the publishing allowance of now, with no hole in the last hours. Cloud
|
|
158
|
+
* applies the same rule to the bars it serves.
|
|
159
|
+
*/
|
|
160
|
+
function isRoundTheClockHistoryBehind(
|
|
161
|
+
points: PricePoint[], latestTime: number, now: number, intervalMs: number | null,
|
|
162
|
+
): boolean {
|
|
163
|
+
const allowedLag = intervalMs != null ? 2 * intervalMs + DELAYED_HISTORY_ALLOWANCE_MS : MAX_SAME_SESSION_HISTORY_LAG_MS;
|
|
164
|
+
if (now - latestTime > allowedLag) return true;
|
|
165
|
+
const maxGap = Math.max(3 * (intervalMs ?? 0), ROUND_THE_CLOCK_GAP_MS);
|
|
166
|
+
let later = latestTime;
|
|
167
|
+
for (let index = points.length - 1; index >= 0 && later >= now - ROUND_THE_CLOCK_RECENT_MS; index--) {
|
|
168
|
+
const point = points[index]!;
|
|
169
|
+
if (!hasFiniteClose(point)) continue;
|
|
170
|
+
const time = getPricePointTimestamp(point);
|
|
171
|
+
if (!(time < later)) continue;
|
|
172
|
+
if (later - time > maxGap) return true;
|
|
173
|
+
later = time;
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
|
|
143
178
|
export function isPriceHistoryStaleForCurrentWindow(
|
|
144
179
|
points: PricePoint[],
|
|
145
180
|
now = Date.now(),
|
|
@@ -149,7 +184,9 @@ export function isPriceHistoryStaleForCurrentWindow(
|
|
|
149
184
|
const latest = normalized.findLast(hasFiniteClose);
|
|
150
185
|
if (!latest) return false;
|
|
151
186
|
|
|
152
|
-
const
|
|
187
|
+
const coin = isRoundTheClockCoin(options.symbol, options.exchange);
|
|
188
|
+
// A coin has no session to read its bars against.
|
|
189
|
+
const session = !coin && options.session?.exchange === canonicalExchange(options.exchange)
|
|
153
190
|
? options.session : undefined;
|
|
154
191
|
const sessionInterval = session ? priceHistoryIntervalMs(session.interval) : null;
|
|
155
192
|
const intervalMs = options.intervalMs ?? sessionInterval ?? inferredHistoryIntervalMs(normalized);
|
|
@@ -159,6 +196,9 @@ export function isPriceHistoryStaleForCurrentWindow(
|
|
|
159
196
|
|
|
160
197
|
const latestTime = getPricePointTimestamp(latest);
|
|
161
198
|
if (!Number.isFinite(latestTime)) return false;
|
|
199
|
+
// Before any exchange logic: a bare BTC-USD is not a US listing, and the
|
|
200
|
+
// always-open venue's own rule lets a bar up to two hours old stand.
|
|
201
|
+
if (coin) return isRoundTheClockHistoryBehind(normalized, latestTime, now, intervalMs);
|
|
162
202
|
if (session && (options.intervalMs == null || options.intervalMs === sessionInterval)) {
|
|
163
203
|
const regularStale = regularHistorySessionStaleness(latestTime, now, session);
|
|
164
204
|
if (regularStale !== null) return regularStale;
|
|
@@ -171,15 +211,12 @@ export function isPriceHistoryStaleForCurrentWindow(
|
|
|
171
211
|
intervalMs != null ? 2 * intervalMs + DELAYED_HISTORY_ALLOWANCE_MS : 0);
|
|
172
212
|
if (age <= allowedLag) return false;
|
|
173
213
|
const exchange = options.exchange || "NASDAQ";
|
|
174
|
-
if (
|
|
175
|
-
resolveExchangeTimeZone(exchange)
|
|
176
|
-
&& isTimestampStaleForExchangeSession(latestTime, exchange, now)
|
|
177
|
-
) {
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
214
|
// Bars that reach the close of the venue's latest session stay current
|
|
181
215
|
// once it has closed, so a closed market keeps its last session until the
|
|
182
216
|
// next one opens. A copy taken earlier in that session is still behind.
|
|
217
|
+
// Asked before the quote rule below, which reads any US bar dated before
|
|
218
|
+
// today as behind from 04:00 ET: right for a last price, wrong for bars
|
|
219
|
+
// waiting for the next session's first one.
|
|
183
220
|
const regularSession = isRegularSessionTime(exchange, now);
|
|
184
221
|
if (regularSession !== null) {
|
|
185
222
|
const open = latestRegularSessionOpen(exchange, now);
|
|
@@ -190,6 +227,12 @@ export function isPriceHistoryStaleForCurrentWindow(
|
|
|
190
227
|
if (regularSession && close < open && latestTime < open && now - open <= allowedLag) return false;
|
|
191
228
|
}
|
|
192
229
|
}
|
|
230
|
+
if (
|
|
231
|
+
resolveExchangeTimeZone(exchange)
|
|
232
|
+
&& isTimestampStaleForExchangeSession(latestTime, exchange, now)
|
|
233
|
+
) {
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
193
236
|
const hasExchangeSession = Boolean(resolveExchangeTimeZone(exchange));
|
|
194
237
|
if (age <= MAX_CURRENT_INTRADAY_HISTORY_LAG_MS) return hasExchangeSession;
|
|
195
238
|
return !hasExchangeSession;
|
|
@@ -209,7 +252,7 @@ const BEHIND_RECHECK_BACKOFF = 4;
|
|
|
209
252
|
// re-check fails, answers nothing usable, or is rejected.
|
|
210
253
|
const UNSETTLED_RETRY_MS = 5 * 60 * 1000;
|
|
211
254
|
|
|
212
|
-
interface CalendarHistoryFetchOptions extends Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs"> {
|
|
255
|
+
interface CalendarHistoryFetchOptions extends Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs" | "symbol"> {
|
|
213
256
|
/**
|
|
214
257
|
* The latest check of this request, including a failed or empty one; the
|
|
215
258
|
* fetch of the copy itself when absent.
|
|
@@ -243,12 +286,13 @@ function barDate(time: number, timeZone: string): string {
|
|
|
243
286
|
* The venue date of the latest bar, read as calendarHistoryFetchState reads
|
|
244
287
|
* it, so copies whose sources label a session differently compare equal.
|
|
245
288
|
*/
|
|
246
|
-
export function calendarHistoryLastBarDate(points: PricePoint[], exchange?: string): string | null {
|
|
289
|
+
export function calendarHistoryLastBarDate(points: PricePoint[], exchange?: string, symbol?: string): string | null {
|
|
247
290
|
const latest = normalizePriceHistory(points).findLast(hasFiniteClose);
|
|
248
291
|
if (!latest) return null;
|
|
249
292
|
const time = getPricePointTimestamp(latest);
|
|
250
293
|
if (!Number.isFinite(time)) return null;
|
|
251
|
-
// Bare symbols resolve to their US listing at the sources.
|
|
294
|
+
// Bare symbols resolve to their US listing at the sources, a coin to its UTC date.
|
|
295
|
+
if (isRoundTheClockCoin(symbol, exchange)) return barDate(time, "UTC");
|
|
252
296
|
return barDate(time, sessionCalendarTimeZone(canonicalExchange(exchange) || "NYSE") ?? "UTC");
|
|
253
297
|
}
|
|
254
298
|
|
|
@@ -270,7 +314,7 @@ function isBarBeforeSession(latestTime: number, session: string, intervalMs: num
|
|
|
270
314
|
* A daily or coarser series changes at every close. A copy fetched before the
|
|
271
315
|
* latest settled close is outdated whatever its cache TTL. A copy fetched
|
|
272
316
|
* after it but without its bar is behind only where the venue's closures are
|
|
273
|
-
* published (
|
|
317
|
+
* published (hasPublishedSessionCalendar): elsewhere, and for a bare symbol whose venue is
|
|
274
318
|
* unknown, a local holiday would read as a missing session. A copy of a 24/7
|
|
275
319
|
* series goes out of date within the hour.
|
|
276
320
|
*/
|
|
@@ -285,7 +329,7 @@ export function calendarHistoryFetchState(
|
|
|
285
329
|
const intervalMs = options.intervalMs ?? inferredHistoryIntervalMs(normalized);
|
|
286
330
|
if (intervalMs == null || intervalMs < DAY_MS) return "current";
|
|
287
331
|
const exchange = canonicalExchange(options.exchange);
|
|
288
|
-
if (exchange
|
|
332
|
+
if (isRoundTheClockCoin(options.symbol, options.exchange)) {
|
|
289
333
|
return now - fetchedAt > CRYPTO_BAR_MAX_AGE_MS
|
|
290
334
|
? unsettledState(fetchedAt + CRYPTO_BAR_MAX_AGE_MS, options.checkedAt, now) : "current";
|
|
291
335
|
}
|
|
@@ -309,12 +353,13 @@ export function calendarHistoryFetchState(
|
|
|
309
353
|
export function reachesLatestSettledSession(
|
|
310
354
|
points: PricePoint[],
|
|
311
355
|
now = Date.now(),
|
|
312
|
-
options: Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs"> = {},
|
|
356
|
+
options: Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs" | "symbol"> = {},
|
|
313
357
|
): boolean {
|
|
314
358
|
const normalized = normalizePriceHistory(points);
|
|
315
359
|
const latest = normalized.findLast(hasFiniteClose);
|
|
316
360
|
const latestTime = latest ? getPricePointTimestamp(latest) : Number.NaN;
|
|
317
361
|
if (!Number.isFinite(latestTime)) return false;
|
|
362
|
+
if (isRoundTheClockCoin(options.symbol, options.exchange)) return false;
|
|
318
363
|
// Bare symbols resolve to their US listing at the sources.
|
|
319
364
|
const session = latestRegularSessionClose(canonicalExchange(options.exchange) || "NYSE", now - SESSION_BAR_SETTLE_MS);
|
|
320
365
|
if (!session) return false;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** A timeout this many times past its limit means the machine slept through it. */
|
|
2
|
+
const SLEEP_TIMEOUT_FACTOR = 5;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A call to the desktop's Bun process that did not complete in time: the
|
|
6
|
+
* request timer ran out, or the bridge socket never opened. `name` stays
|
|
7
|
+
* "Error", so crash reports and filters see the same type as before.
|
|
8
|
+
*/
|
|
9
|
+
export class RpcTimeoutError extends Error {
|
|
10
|
+
readonly elapsedMs: number;
|
|
11
|
+
readonly limitMs: number;
|
|
12
|
+
|
|
13
|
+
constructor(message: string, { elapsedMs, limitMs, cause }: { elapsedMs: number; limitMs: number; cause?: unknown }) {
|
|
14
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
15
|
+
this.elapsedMs = elapsedMs;
|
|
16
|
+
this.limitMs = limitMs;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A timeout whose timer fired long after its limit. A laptop that sleeps
|
|
22
|
+
* suspends the page, and on wake the timer runs once for a request the Bun
|
|
23
|
+
* process already lost. Nothing the user did failed, so it is not a crash.
|
|
24
|
+
*/
|
|
25
|
+
export function isSleepRpcTimeout(error: unknown): boolean {
|
|
26
|
+
return error instanceof RpcTimeoutError && error.elapsedMs > SLEEP_TIMEOUT_FACTOR * error.limitMs;
|
|
27
|
+
}
|
package/src/utils/sec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TickerRecord } from "../types/ticker";
|
|
2
|
-
import { canonicalExchange, US_LISTING_EXCHANGES } from "./exchanges";
|
|
2
|
+
import { canonicalExchange, parsePublicTickerKey, US_LISTING_EXCHANGES } from "./exchanges";
|
|
3
3
|
|
|
4
4
|
/** Canonical US equity venues: the listing exchanges plus other lit and OTC venues. */
|
|
5
5
|
const US_EQUITY_EXCHANGES = new Set([
|
|
@@ -102,6 +102,18 @@ export function isKnownNonUsEquityTicker(ticker: TickerRecord | null | undefined
|
|
|
102
102
|
.some((exchange) => normalize(exchange).length > 0);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* The venue an SEC issuer lookup has to respect: a listing outside the US,
|
|
107
|
+
* whose bare symbol the SEC may know as another company (SAN is Banco
|
|
108
|
+
* Santander in New York, Sanofi in Paris). Null for a US venue, a routing
|
|
109
|
+
* destination or no venue at all, which look the symbol up as a US ticker.
|
|
110
|
+
*/
|
|
111
|
+
export function nonUsSecListingVenue(ticker: string, exchange?: string): string | null {
|
|
112
|
+
const venue = parsePublicTickerKey(ticker).exchange ?? canonicalExchange(exchange);
|
|
113
|
+
if (!venue || ROUTING_EXCHANGES.has(venue) || isUsExchange(venue)) return null;
|
|
114
|
+
return venue;
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
/**
|
|
106
118
|
* The item codes in EDGAR's `items` field ("2.02,9.01"). EDGAR fills the same
|
|
107
119
|
* field with other values for some forms, such as the order dates of a CT
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Times in CLI and report text print in UTC with the zone named, so a value
|
|
3
|
+
* copied out of a report means the same thing on every machine and in every
|
|
4
|
+
* time zone. JSON keeps the raw ISO or epoch values.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
8
|
+
/** An ISO date and time with an explicit zone; one without a zone cannot be placed in UTC. */
|
|
9
|
+
const ZONED_ISO_DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})$/i;
|
|
10
|
+
// Epoch milliseconds between 2001 and 2286, so counts and prices are never read as times.
|
|
11
|
+
const EPOCH_MS_MIN = 1e12;
|
|
12
|
+
const EPOCH_MS_MAX = 1e13;
|
|
13
|
+
|
|
14
|
+
export interface ReportTime {
|
|
15
|
+
/** Epoch milliseconds; a date-only value sits at UTC midnight. */
|
|
16
|
+
time: number;
|
|
17
|
+
/** The value named a calendar date, not an instant. */
|
|
18
|
+
dateOnly: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isEpochMilliseconds(value: number): boolean {
|
|
22
|
+
return Number.isFinite(value) && value >= EPOCH_MS_MIN && value < EPOCH_MS_MAX;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isZonedIsoDateTime(value: string): boolean {
|
|
26
|
+
return ZONED_ISO_DATE_TIME.test(value);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Reads a Date, epoch milliseconds, an ISO date or a zoned ISO date and time.
|
|
31
|
+
* A date and time without a zone, or anything else, is not a report time.
|
|
32
|
+
*/
|
|
33
|
+
export function parseReportTime(value: unknown): ReportTime | null {
|
|
34
|
+
if (value instanceof Date) {
|
|
35
|
+
const time = value.getTime();
|
|
36
|
+
return Number.isFinite(time) ? { time, dateOnly: false } : null;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "number") return isEpochMilliseconds(value) ? { time: value, dateOnly: false } : null;
|
|
39
|
+
if (typeof value !== "string") return null;
|
|
40
|
+
const text = value.trim();
|
|
41
|
+
if (DATE_ONLY.test(text)) {
|
|
42
|
+
const time = Date.parse(`${text}T00:00:00Z`);
|
|
43
|
+
return Number.isFinite(time) ? { time, dateOnly: true } : null;
|
|
44
|
+
}
|
|
45
|
+
if (!ZONED_ISO_DATE_TIME.test(text)) return null;
|
|
46
|
+
const time = Date.parse(text);
|
|
47
|
+
return Number.isFinite(time) ? { time, dateOnly: false } : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* `2026-10-09 00:08 UTC`. Only an explicitly date-only value prints
|
|
52
|
+
* as `2026-10-09`; midnight instants keep their time and zone.
|
|
53
|
+
*/
|
|
54
|
+
export function formatUtcTime(value: ReportTime | Date | number | string): string {
|
|
55
|
+
const parsed = typeof value === "object" && !(value instanceof Date) ? value : parseReportTime(value);
|
|
56
|
+
if (!parsed) return typeof value === "string" ? value : "";
|
|
57
|
+
const iso = new Date(parsed.time).toISOString();
|
|
58
|
+
if (parsed.dateOnly) return iso.slice(0, 10);
|
|
59
|
+
return `${iso.slice(0, 16).replace("T", " ")} UTC`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The newest of some report times, as given, so a loader can declare its as-of from the rows it means. */
|
|
63
|
+
export function newestReportTime<T>(values: Iterable<T>): T | null {
|
|
64
|
+
let best: { value: T; time: number } | null = null;
|
|
65
|
+
for (const value of values) {
|
|
66
|
+
const parsed = parseReportTime(value);
|
|
67
|
+
if (parsed && (!best || parsed.time > best.time)) best = { value, time: parsed.time };
|
|
68
|
+
}
|
|
69
|
+
return best?.value ?? null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function oldestReportTime<T>(values: Iterable<T>): T | null {
|
|
73
|
+
let best: { value: T; time: number } | null = null;
|
|
74
|
+
for (const value of values) {
|
|
75
|
+
const parsed = parseReportTime(value);
|
|
76
|
+
if (parsed && (!best || parsed.time < best.time)) best = { value, time: parsed.time };
|
|
77
|
+
}
|
|
78
|
+
return best?.value ?? null;
|
|
79
|
+
}
|