gloomberb 0.16.3 → 0.16.5
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 +14 -91
- package/package.json +7 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
- package/src/account/upgrade-personalization.ts +57 -0
- package/src/account/upgrade-tickers.ts +124 -0
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +58 -18
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +16 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +95 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +46 -10
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +74 -2
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +26 -2
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +61 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +19 -4
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +744 -181
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +425 -0
- package/src/cli/commands/overview.ts +251 -40
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +109 -15
- package/src/cli/commands/system.ts +151 -24
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +149 -40
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +150 -17
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +22 -8
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/glossary.ts +429 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +58 -0
- package/src/cli/index.ts +29 -12
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +595 -26
- package/src/cli/not-a-ticker.ts +44 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +11 -4
- package/src/cli/pane-functions/catalog.ts +48 -7
- package/src/cli/pane-functions/data.ts +48 -13
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +41 -19
- package/src/cli/pane-functions/freshness.ts +531 -32
- package/src/cli/pane-functions/function-help.ts +77 -25
- package/src/cli/pane-functions/headless.ts +50 -21
- package/src/cli/pane-functions/index.ts +66 -10
- package/src/cli/pane-functions/market-session.ts +147 -0
- package/src/cli/pane-functions/options.ts +77 -25
- package/src/cli/pane-functions/report-notices.ts +81 -0
- package/src/cli/pane-functions/report.ts +19 -8
- package/src/cli/pane-functions/resolver.ts +53 -18
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +199 -30
- package/src/cli/registry.ts +2 -1
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +53 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +83 -10
- package/src/components/chart/composite/legend.tsx +88 -8
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +9 -2
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +40 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +26 -2
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +43 -9
- package/src/components/layout/shell/drag/live.ts +87 -6
- package/src/components/layout/shell/drag/runtime.ts +62 -20
- package/src/components/layout/shell/index.tsx +71 -12
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +33 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +216 -28
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +69 -23
- package/src/components/metric-treemap/heat-surface.tsx +37 -9
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +50 -41
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +17 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +49 -0
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +20 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +13 -2
- package/src/components/ui/index.ts +1 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +44 -5
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +75 -5
- package/src/i18n/ja.ts +75 -5
- package/src/i18n/ko.ts +75 -5
- package/src/i18n/zh-cn.ts +75 -5
- package/src/i18n/zh-tw.ts +75 -5
- package/src/layout/desks.ts +2 -3
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +193 -30
- package/src/market-data/market/status.ts +59 -23
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +22 -2
- package/src/market-data/quotes/metadata.ts +8 -9
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +61 -9
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +2 -56
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +37 -8
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +71 -12
- package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +50 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
- package/src/plugins/builtin/cloud/askg/model.ts +156 -78
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
- package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +116 -67
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +23 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +70 -22
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +70 -9
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +64 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +114 -20
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/index.tsx +18 -8
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +42 -134
- package/src/plugins/builtin/holders/pane.tsx +14 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +27 -10
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +26 -6
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +27 -12
- package/src/plugins/builtin/iv-history/index.tsx +5 -3
- package/src/plugins/builtin/iv-history/model.ts +172 -20
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +68 -3
- package/src/plugins/builtin/macro-day/headless.ts +18 -12
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +66 -15
- package/src/plugins/builtin/macro-day/pane.tsx +34 -20
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +102 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +11 -3
- package/src/plugins/builtin/market-movers/model.ts +101 -17
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +162 -13
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +5 -2
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +75 -18
- package/src/plugins/builtin/options-scenario/headless.ts +72 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -8
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +32 -6
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +90 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
- package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +8 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +69 -0
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +59 -2
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +21 -4
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +3 -10
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
- package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +125 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +129 -64
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +173 -28
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +25 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +126 -59
- package/src/remote/matching.ts +69 -0
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +63 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +32 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +27 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +21 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +4 -1
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +14 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +74 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +6 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +26 -17
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +14 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +9 -5
- package/src/sources/provider-router/financial-routes.ts +12 -5
- package/src/sources/provider-router/financials.ts +55 -15
- package/src/sources/provider-router/history.ts +68 -34
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +5 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +67 -9
- package/src/tickers/search/ranking.ts +78 -18
- package/src/tickers/search/types.ts +10 -2
- package/src/tickers/starter-symbols.ts +8 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +96 -30
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +67 -1
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +72 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +68 -3
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +26 -4
- package/src/ui/index.tsx +2 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +21 -2
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +120 -1
- package/src/utils/format.ts +17 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +44 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +130 -40
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +178 -36
- package/src/utils/sec.ts +98 -40
- package/src/utils/throttled-fetch.ts +51 -22
- package/src/utils/utc-time.ts +51 -4
|
@@ -3,6 +3,7 @@ import type { DataTableCell, DataTableColumn } from "../../../components";
|
|
|
3
3
|
import { scalarPoint, staticSeries } from "../../../components/chart/static/series";
|
|
4
4
|
import { getTableWidth } from "../../../components/ui/table-layout";
|
|
5
5
|
import { formatCompact } from "../../../utils/format";
|
|
6
|
+
import { isUsListingExchange, publicTickerKey } from "../../../utils/exchanges";
|
|
6
7
|
import type { ThemeColors } from "../../../theme/colors";
|
|
7
8
|
export const PERP_TABS = ["board", "rankings", "compare", "history", "evidence"] as const;
|
|
8
9
|
export type PerpTab = typeof PERP_TABS[number];
|
|
@@ -21,7 +22,29 @@ export const compact = (n: number | null | undefined) => n == null ? "--" : form
|
|
|
21
22
|
export const time = (s: string | null | undefined) => s ? `${s.slice(0, 10)} ${s.slice(11, 16)} UTC` : "--";
|
|
22
23
|
/** A list row's observation, month to minute: the header names UTC and the footer the full as-of. */
|
|
23
24
|
const observed = (s: string | null | undefined) => s ? `${s.slice(5, 10)} ${s.slice(11, 16)}` : "--";
|
|
25
|
+
/**
|
|
26
|
+
* The listed security a market tracks, as DES, FA and G take it: a US listing by its symbol, the key a stock is
|
|
27
|
+
* saved and opened under, and a listing abroad with its venue (`NET:XLON`), so they open the security the premium
|
|
28
|
+
* is measured against. Null for crypto, indices, commodities and any market without one.
|
|
29
|
+
*/
|
|
30
|
+
export function underlyingTicker(row: Pick<PerpBoardRow, "underlyingSymbol" | "underlying" | "equityMatch">): string | null {
|
|
31
|
+
const symbol = row.underlyingSymbol?.trim().toUpperCase();
|
|
32
|
+
if (!symbol) return null;
|
|
33
|
+
const listing = row.equityMatch?.underlying.symbol.toUpperCase() === symbol ? row.equityMatch.underlying.exchange
|
|
34
|
+
: row.underlying?.symbol.toUpperCase() === symbol ? row.underlying.listingExchange : undefined;
|
|
35
|
+
return !listing || isUsListingExchange(listing) ? symbol : publicTickerKey(symbol, listing);
|
|
36
|
+
}
|
|
24
37
|
export const marketLabel = (row: PerpBoardRow) => row.dex && row.dex !== "default" ? `${row.baseAsset} · ${row.dex.toUpperCase()}` : row.baseAsset;
|
|
38
|
+
/** What the contract is, in plain words: perpetual futures never expire and trade around the clock. */
|
|
39
|
+
export const perpDescription = (row: Pick<PerpBoardRow, "venue">) =>
|
|
40
|
+
`Perpetual futures (24/7 ${row.venue === "hyperliquid" || row.venue === "dydx" ? "on-chain" : venueName(row.venue)} market)`;
|
|
41
|
+
/** When the venue's figures were read, in UTC: the time alone for today, with the date for an older reading. */
|
|
42
|
+
export function readingTime(observedAt: string | null | undefined, now = Date.now()): string | null {
|
|
43
|
+
const read = observedAt ? Date.parse(observedAt) : Number.NaN;
|
|
44
|
+
if (!Number.isFinite(read)) return null;
|
|
45
|
+
const iso = new Date(read).toISOString();
|
|
46
|
+
return `${iso.slice(0, 10) === new Date(now).toISOString().slice(0, 10) ? "" : `${iso.slice(0, 10)} `}${iso.slice(11, 16)} UTC`;
|
|
47
|
+
}
|
|
25
48
|
export const fundingInterval = (row: Pick<PerpBoardRow, "fundingIntervalHours" | "fundingKind">) => row.fundingIntervalHours ? `${row.fundingIntervalHours}h${row.fundingKind === "last-paid" ? " paid" : row.fundingKind === "continuous" ? " continuous" : ""}` : "--";
|
|
26
49
|
export const HISTORY_METRICS = ["funding", "oi", "premium", "price", "long-short"] as const;
|
|
27
50
|
export type HistoryMetric = typeof HISTORY_METRICS[number];
|
|
@@ -116,12 +139,15 @@ const PERP_COLUMNS: Record<PerpColumnId, DataTableColumn> = {
|
|
|
116
139
|
value: { id: "value", label: "Value %", width: 10, align: "right" },
|
|
117
140
|
};
|
|
118
141
|
// Columns in reading order, then the order a narrow pane gives them up in.
|
|
119
|
-
export const BOARD_COLUMNS: PerpColumnId[] = ["market", "venue", "markPrice", "fundingRate", "
|
|
120
|
-
// The venue goes last: the same market trades on several, and only the venue tells those rows apart.
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
142
|
+
export const BOARD_COLUMNS: PerpColumnId[] = ["market", "venue", "markPrice", "fundingRate", "premium", "openInterestUsd", "oiChange24h", "longShare", "fundingApr", "priceChange24h", "observedAt"];
|
|
143
|
+
// The venue goes last: the same market trades on several, and only the venue tells those rows apart. Venues are polled
|
|
144
|
+
// apart, so when each row was observed stays until only the venue is left to give up. The long share is what the board
|
|
145
|
+
// and the comparison are read for, so a 100-column pane keeps it beside the observation time: the annualised funding,
|
|
146
|
+
// which only restates the funding rate, goes first (the 24h OI change next on the board, the per-interval rate on
|
|
147
|
+
// Compare), and the premium before the long share.
|
|
148
|
+
const BOARD_DROPS: PerpColumnId[] = ["fundingApr", "priceChange24h", "oiChange24h", "premium", "longShare", "markPrice", "openInterestUsd", "observedAt", "venue"];
|
|
149
|
+
export const COMPARE_COLUMNS: PerpColumnId[] = ["venue", "symbol", "markPrice", "fundingRate", "fundingRate8h", "premium", "openInterestUsd", "oiChange24h", "longShare", "fundingApr", "observedAt"];
|
|
150
|
+
const COMPARE_DROPS: PerpColumnId[] = ["fundingApr", "oiChange24h", "fundingRate", "premium", "longShare", "markPrice", "openInterestUsd", "observedAt", "symbol"];
|
|
125
151
|
export const RANKING_COLUMNS: PerpColumnId[] = ["market", "venue", "value", "openInterestUsd"];
|
|
126
152
|
|
|
127
153
|
/** The columns that fit the pane, the least read going first; before the last of them goes, a long market name gives up its tail. */
|
|
@@ -3,31 +3,67 @@ import { isAccessDenied } from "../../../api-client/errors";
|
|
|
3
3
|
import { usePlanAccess } from "../../../api-client/plan-access";
|
|
4
4
|
import type { PerpBoardRow, PerpMarketPayload } from "../../../api-client/perps";
|
|
5
5
|
import { buildSectionedRows, ChartTableHeader, DataTableView, EmptyState, KeyValueRow, SectionHeading, PaneStatusBody, QueryBar, StatGrid, useChartTableSelection,
|
|
6
|
-
usePaneNoticeFooter, usePaneStatusFooter, usePaneTabs, useQueryBarSearch, type DataTableCell, type
|
|
6
|
+
usePaneNoticeFooter, usePaneStatusFooter, usePaneTabs, useQueryBarSearch, type DataTableCell, type KeyValueRowProps, type PaneFooterSegment, type PaneHint, type SectionedRow,
|
|
7
|
+
type StatItem } from "../../../components";
|
|
8
|
+
import { deriveHeadlessFreshness, paneStatusLineVariants } from "../../../cli/pane-functions/freshness";
|
|
7
9
|
import { openFormModal } from "../../../components/form-modal";
|
|
10
|
+
import { tf } from "../../../i18n";
|
|
8
11
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
9
12
|
import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePaneTitle, usePluginAppActions, usePluginPaneState } from "../../../public/react";
|
|
13
|
+
import { useAgeClock } from "../../../react/auto-refresh";
|
|
14
|
+
import { useRemoteUiNode } from "../../../remote/semantic-tree";
|
|
10
15
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
11
16
|
import type { PaneProps } from "../../../types/plugin";
|
|
12
17
|
import { Box, ScrollBox, useRendererHost, useUiCapabilities } from "../../../ui";
|
|
13
18
|
import { getSharedRegistry } from "../../registry/shared";
|
|
14
19
|
import { SignInWall } from "../cloud/auth-actions";
|
|
15
20
|
import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
|
|
21
|
+
import { useCommandValue } from "../shared/command-tab";
|
|
22
|
+
import { useOpenDescription } from "../shared/open-description";
|
|
16
23
|
import { UpgradeLabel } from "../shared/locked-rows";
|
|
17
24
|
import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
|
|
18
25
|
import { cachedPerpSelection, cachedPerpsBoard, cachedPerpsCompare, cachedPerpsRankings, loadPerpSelection, loadPerpsBoard, loadPerpsCompare,
|
|
19
26
|
loadPerpsHistoryForRange, loadPerpsRankings } from "./client";
|
|
27
|
+
import { perpFreshness, perpObservation } from "./freshness";
|
|
20
28
|
import { ASSET_FILTERS, BOARD_SORTS, boardColumns, compact, compareColumns, dayChange, fundingInterval, fundingSpread, historyCaption, historyCell, historyChange, historyColumns,
|
|
21
29
|
HISTORY_METRICS, historyRows, historySeries, historyValue, inPoints, isMarketTab, label, longShortReason, marketLabel, metricLabel, openingTab, perpCell, PERP_TABS, percent,
|
|
22
|
-
positioningFields, price, rankingColumns, rankingRows, RANKINGS, ratioText, share, sortLabel, time, venueLabel, venueName, venuesOf, type HistoryMetric,
|
|
23
|
-
type PerpTab, type RankingKey } from "./model";
|
|
30
|
+
positioningFields, price, rankingColumns, rankingRows, RANKINGS, ratioText, share, sortLabel, time, underlyingTicker, venueLabel, venueName, venuesOf, type HistoryMetric,
|
|
31
|
+
type PerpColumnId, type PerpTab, type RankingKey } from "./model";
|
|
32
|
+
|
|
33
|
+
const NO_ROWS: readonly PerpBoardRow[] = [];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The footer line for the rows on screen: each venue's own observation time, how old the oldest is, the delay state
|
|
37
|
+
* and what the funding figures are, the line `fn PERP` and `shot PERP` end with. It keeps ageing while the pane is
|
|
38
|
+
* seen (`since` is when the rows loaded), and is published for a capture to date itself the same way.
|
|
39
|
+
*/
|
|
40
|
+
function usePerpStatusLine(rows: readonly PerpBoardRow[], funding: readonly PerpBoardRow[], since: number | null): PaneFooterSegment[] {
|
|
41
|
+
const now = useAgeClock(since);
|
|
42
|
+
const declared = useMemo(() => rows.length ? perpFreshness(rows, { funding, now }) : null, [rows, funding, now]);
|
|
43
|
+
useRemoteUiNode(declared ? { role: "report-freshness", label: "Venue freshness", getMetadata: () => ({ ...declared, observations: rows.map(perpObservation) }) } : null);
|
|
44
|
+
return useMemo(() => {
|
|
45
|
+
if (!declared) return [];
|
|
46
|
+
const freshness = deriveHeadlessFreshness({ shape: "rows" }, { rows: rows.map(perpObservation), freshness: declared }, now);
|
|
47
|
+
const tone = freshness.status === "stale" ? "warning" as const : "muted" as const;
|
|
48
|
+
// A footer too narrow beside its keys gives up the funding part before any venue's time.
|
|
49
|
+
const [line, ...shorter] = paneStatusLineVariants(freshness).map((text) => [{ text, tone }]);
|
|
50
|
+
return [{ id: "perp-freshness", asOf: true, parts: line!, variants: shorter }];
|
|
51
|
+
}, [declared, rows, now]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type EvidenceField = [label: string, value: string, detail?: string, link?: KeyValueRowProps["link"]];
|
|
24
55
|
|
|
25
56
|
function MarketEvidence({ row, data, width, height }: { row: PerpBoardRow; data: PerpMarketPayload; width: number; height: number }) {
|
|
26
57
|
const desktop = !!useUiCapabilities().nativePaneChrome;
|
|
27
58
|
const upgrade = useCloudUpgradeAction("perp");
|
|
59
|
+
const openDescription = useOpenDescription();
|
|
28
60
|
const positioning = positioningFields(row);
|
|
61
|
+
// The security the premium is measured against opens its DES, as the `d` key does.
|
|
62
|
+
const security = underlyingTicker(row);
|
|
63
|
+
const listed: EvidenceField[] = security && row.underlying ? [["Ticker", row.underlying.symbol, row.underlying.listingExchange,
|
|
64
|
+
{ label: tf("Open {ticker}", { ticker: row.underlying.symbol }), onOpen: () => openDescription(security) }]] : [];
|
|
29
65
|
// Grouped as a trader reads a contract; a stock reference only for a market that has one.
|
|
30
|
-
const groups: Array<[string,
|
|
66
|
+
const groups: Array<[string, EvidenceField[]]> = [
|
|
31
67
|
["Market", [["Venue", venueLabel(row)], ["Contract symbol", row.symbol], ["Observed", time(row.observedAt)], ["Source as of", time(row.sourceAsOf)],
|
|
32
68
|
["Mark", `${price(row.markPrice)} ${row.quoteCurrency}`], ["Oracle", `${price(row.oraclePrice)} ${row.quoteCurrency}`], ["Premium vs oracle", percent(row.premium)]]],
|
|
33
69
|
["Funding", [["Funding", `${percent(row.fundingRate, 5)} / ${fundingInterval(row)}`, row.fundingKind === "last-paid" ? "Last paid" : row.fundingKind === "continuous" ? "Continuous rate" : "Current rate"],
|
|
@@ -36,16 +72,17 @@ function MarketEvidence({ row, data, width, height }: { row: PerpBoardRow; data:
|
|
|
36
72
|
...(row.nextFundingAt ? [["Next funding", time(row.nextFundingAt)] as [string, string]] : [])]],
|
|
37
73
|
["Open Interest", [["Open interest", `${compact(row.openInterestBase)} ${row.baseAsset} · ${compact(row.openInterestUsd)} USD`],
|
|
38
74
|
["OI change 1h / 24h", row.oiChange1h == null && row.oiChange24h == null ? "Collecting" : `${percent(row.oiChange1h, 2)} / ${percent(row.oiChange24h, 2)}`, "own snapshots"]]],
|
|
39
|
-
...(positioning ? [["Positioning", positioning.map((field) => [field.label, field.text, field.detail])] as [string,
|
|
40
|
-
...(row.underlying ? [["Underlying", [["Underlying last", `${price(row.underlying.price)} ${row.underlying.currency}`, time(row.underlying.asOf)], ["Underlying session", row.underlying.marketState ?? "Unknown"],
|
|
41
|
-
["Premium vs underlying", percent(row.underlyingPremium)], ["Closed-market premium", percent(row.closedMarketPremium)]]] as [string,
|
|
75
|
+
...(positioning ? [["Positioning", positioning.map((field) => [field.label, field.text, field.detail])] as [string, EvidenceField[]]] : []),
|
|
76
|
+
...(row.underlying ? [["Underlying", [...listed, ["Underlying last", `${price(row.underlying.price)} ${row.underlying.currency}`, time(row.underlying.asOf)], ["Underlying session", row.underlying.marketState ?? "Unknown"],
|
|
77
|
+
["Premium vs underlying", percent(row.underlyingPremium)], ["Closed-market premium", percent(row.closedMarketPremium)]]] as [string, EvidenceField[]]] : []),
|
|
42
78
|
["Contract", [["Contract", `${label(row.contractType)} · ${row.priceMultiplier}× price`], ["Margin", row.marginCurrency], ["Max leverage", row.maxLeverage == null ? "--" : `${row.maxLeverage}×`],
|
|
43
79
|
["Margin mode", row.isolatedOnly === null ? "Unspecified" : row.isolatedOnly ? "Isolated only" : "Cross / isolated"], ["Listing", row.delisted ? "Delisted" : "Active"], ["Confidence", label(row.confidence)]]],
|
|
44
80
|
];
|
|
81
|
+
// The ticker's link is not listed in the pane menu again: `d` there opens the same DES.
|
|
45
82
|
return <ScrollBox scrollY width={width} height={desktop ? undefined : height} flexGrow={1} flexBasis={0} minHeight={0} contentOptions={{ paddingX: 1 }}>
|
|
46
83
|
{groups.map(([title, fields]) => <Fragment key={title}>
|
|
47
84
|
<SectionHeading title={title} />
|
|
48
|
-
{fields.map(([name, value, detail]) => <KeyValueRow key={name} labelWidth={25} label={name} value={value} detail={detail} />)}
|
|
85
|
+
{fields.map(([name, value, detail, link]) => <KeyValueRow key={name} labelWidth={25} label={name} value={value} detail={detail} link={link} />)}
|
|
49
86
|
</Fragment>)}
|
|
50
87
|
{data.evidence.length ? <SectionHeading title="Observation Revisions" /> : null}
|
|
51
88
|
{data.evidence.map((entry) => {
|
|
@@ -86,8 +123,11 @@ function History({ market, accessKey, width, height, focused, range, metric, ref
|
|
|
86
123
|
useAutoRefresh(resource.updatedAt, resource.load, { intervalMs: 60_000 });
|
|
87
124
|
usePaneRefreshKey(() => { refreshMarket(); void resource.reload(); }, { focused });
|
|
88
125
|
const lastTime = rows.at(-1)?.time;
|
|
126
|
+
// The market row dates the figures beside the series. Its funding is the current estimate, unless the series is paid funding.
|
|
127
|
+
const marketRows = useMemo(() => [market], [market]);
|
|
128
|
+
const line = usePerpStatusLine(marketRows, metric === "funding" && !data?.funding.length ? marketRows : NO_ROWS, resource.updatedAt);
|
|
89
129
|
usePaneStatusFooter({ registrationId: "perps:history", loading: resource.loading, error: resource.error, stale: resource.data?.stale,
|
|
90
|
-
info: lastTime ? [{ id: "history-asof", parts: [{ text: `${historyCaption(data, metric)} · ${time(lastTime)}`, tone: "muted" }] }] : [] });
|
|
130
|
+
info: [...line, ...(lastTime ? [{ id: "history-asof", parts: [{ text: `${historyCaption(data, metric)} · ${time(lastTime)}`, tone: "muted" as const }] }] : [])] });
|
|
91
131
|
usePaneNoticeFooter({ registrationId: "perps:history-notice", focused, notices: [resource.data?.refreshError,
|
|
92
132
|
data?.truncated ? "History reached the 5,000-observation limit. Narrow the range for all observations." : null].filter((value): value is string => !!value) });
|
|
93
133
|
const periodChange = rows.length > 1 && rows[0]!.value != null && rows.at(-1)!.value != null ? rows.at(-1)!.value! - rows[0]!.value! : null;
|
|
@@ -155,7 +195,6 @@ interface ListTabProps {
|
|
|
155
195
|
onOpen: (row: PerpBoardRow) => void;
|
|
156
196
|
}
|
|
157
197
|
|
|
158
|
-
const asOfInfo = (id: string, asOf: string | null | undefined) => asOf ? [{ id, parts: [{ text: time(asOf), tone: "muted" as const }] }] : [];
|
|
159
198
|
const moreText = (count: number, noun: string) => `Upgrade for ${count.toLocaleString("en-US")} more ${noun}`;
|
|
160
199
|
|
|
161
200
|
/** The preview's lock: under the rows it shows, or in place of the rows when none of the preview matches. */
|
|
@@ -189,7 +228,8 @@ function Board({ accessKey, width, height, focused, onPick, onOpen }: ListTabPro
|
|
|
189
228
|
const locked = typeof data?.locked === "number" ? data.locked : 0;
|
|
190
229
|
useAutoRefresh(resource.updatedAt, resource.load, { intervalMs: 60_000 });
|
|
191
230
|
usePaneRefreshKey(() => { void resource.reload(); }, { focused: focused && !querySearch.active });
|
|
192
|
-
|
|
231
|
+
const line = usePerpStatusLine(rows, rows, resource.updatedAt);
|
|
232
|
+
usePaneStatusFooter({ registrationId: "perps:board", loading: resource.loading, error: data ? resource.error : null, stale: resource.data?.stale, info: line });
|
|
193
233
|
usePaneNoticeFooter({ registrationId: "perps:board-notice", focused, notices: resource.data?.refreshError ? [resource.data.refreshError] : [] });
|
|
194
234
|
if (!data && isCloudSessionRequired(resource.error)) return <SignInWall placement="perps-signin" action="view perpetual markets" needsVerification={session.needsVerification} />;
|
|
195
235
|
const narrow = (apply: () => void) => { apply(); setSelected(null); };
|
|
@@ -232,7 +272,11 @@ function Rankings({ accessKey, width, height, focused, onPick, onOpen }: ListTab
|
|
|
232
272
|
const columns = useMemo(() => rankingColumns(width), [width]);
|
|
233
273
|
useAutoRefresh(resource.updatedAt, resource.load, { intervalMs: 60_000 });
|
|
234
274
|
usePaneRefreshKey(() => { void resource.reload(); }, { focused });
|
|
235
|
-
|
|
275
|
+
// Every ranked row is dated; only the funding lists show funding.
|
|
276
|
+
const rankedRows = useMemo(() => RANKINGS.flatMap((ranking) => rankingRows(data, ranking.key)), [data]);
|
|
277
|
+
const fundingRows = useMemo(() => RANKINGS.filter((ranking) => ranking.field === "fundingRate8h").flatMap((ranking) => rankingRows(data, ranking.key)), [data]);
|
|
278
|
+
const line = usePerpStatusLine(rankedRows, fundingRows, resource.updatedAt);
|
|
279
|
+
usePaneStatusFooter({ registrationId: "perps:rankings", loading: resource.loading, error: data ? resource.error : null, stale: resource.data?.stale, info: line });
|
|
236
280
|
usePaneNoticeFooter({ registrationId: "perps:rankings-notice", focused, notices: resource.data?.refreshError ? [resource.data.refreshError] : [] });
|
|
237
281
|
if (!data && isCloudSessionRequired(resource.error)) return <SignInWall placement="perps-signin" action="view perpetual rankings" needsVerification={session.needsVerification} />;
|
|
238
282
|
const renderCell = (entry: SectionedRow<Ranked>, column: { id: string }): DataTableCell => {
|
|
@@ -266,15 +310,16 @@ function Compare({ asset, onAssetChange, accessKey, width, height, focused, onPi
|
|
|
266
310
|
const loader = useCallback((force: boolean) => loadPerpsCompare(base, accessKey, force), [base, accessKey]);
|
|
267
311
|
const resource = useAsyncResource(loader, { initialData: () => cachedPerpsCompare(base, accessKey), clearOnError: isAccessDenied, keepPreviousData: true });
|
|
268
312
|
const data = resource.data?.payload;
|
|
269
|
-
const rows = data?.rows ?? [];
|
|
313
|
+
const rows = useMemo(() => data?.rows ?? [], [data]);
|
|
270
314
|
const selected = rows.find((row) => row.marketId === selectedId) ?? rows[0] ?? null;
|
|
271
315
|
useEffect(() => { onPick(selected); }, [selected, onPick]);
|
|
272
316
|
const columns = useMemo(() => compareColumns(width), [width]);
|
|
317
|
+
const line = usePerpStatusLine(rows, rows, resource.updatedAt);
|
|
273
318
|
const spread = useMemo(() => fundingSpread(rows), [rows]);
|
|
274
319
|
const locked = typeof data?.locked === "number" ? data.locked : 0;
|
|
275
320
|
useAutoRefresh(resource.updatedAt, resource.load, { intervalMs: 60_000 });
|
|
276
321
|
usePaneRefreshKey(() => { void resource.reload(); }, { focused: focused && !querySearch.active });
|
|
277
|
-
usePaneStatusFooter({ registrationId: "perps:compare", loading: resource.loading, error: data ? resource.error : null, stale: resource.data?.stale, info:
|
|
322
|
+
usePaneStatusFooter({ registrationId: "perps:compare", loading: resource.loading, error: data ? resource.error : null, stale: resource.data?.stale, info: line });
|
|
278
323
|
usePaneNoticeFooter({ registrationId: "perps:compare-notice", focused, notices: resource.data?.refreshError ? [resource.data.refreshError] : [] });
|
|
279
324
|
if (!data && isCloudSessionRequired(resource.error)) return <SignInWall placement="perps-signin" action="compare perpetual venues" needsVerification={session.needsVerification} />;
|
|
280
325
|
const figures: StatItem[] = spread ? [{ id: "spread", label: "Funding spread 8h", value: spread.text, detail: spread.detail }] : [];
|
|
@@ -311,13 +356,16 @@ export function PerpsPane({ width, height, focused, marketAction }: Pick<PanePro
|
|
|
311
356
|
const access = usePlanAccess();
|
|
312
357
|
const accessKey = `${session.requestKey}:${access.hasProAccess ? "pro" : "preview"}`;
|
|
313
358
|
const { createPaneFromTemplate, notify } = usePluginAppActions();
|
|
359
|
+
const openDescription = useOpenDescription();
|
|
314
360
|
const upgrade = useCloudUpgradeAction("perp");
|
|
315
361
|
const [openingMarket] = usePaneSettingValue("market", "");
|
|
316
362
|
const [openingTabValue] = usePaneSettingValue("tab", openingTab(openingMarket));
|
|
317
|
-
|
|
363
|
+
// A market asked for again (a stock's perpetual row, PERP) comes back to it on its opening tab, whatever this pane
|
|
364
|
+
// shows by then.
|
|
365
|
+
const [savedTab, setTab] = useCommandValue<string>("perps", "perps:tab", (params) => params.market ? openingTabValue : null, openingTabValue);
|
|
318
366
|
const tab = PERP_TABS.includes(savedTab as PerpTab) ? savedTab as PerpTab : openingTab(openingMarket);
|
|
319
367
|
const marketTab = isMarketTab(tab);
|
|
320
|
-
const [search, setSearch] =
|
|
368
|
+
const [search, setSearch] = useCommandValue("perps", "perps:search", (params) => params.market || null, openingMarket);
|
|
321
369
|
const [compareAsset, setCompareAsset] = usePluginPaneState<string>("perps:compare", compareOpening(openingMarket));
|
|
322
370
|
// The row under a list's cursor, and the last one any list had: an empty list keeps the market it was given.
|
|
323
371
|
const [listRow, setListRow] = useState<PerpBoardRow | null>(null);
|
|
@@ -349,7 +397,9 @@ export function PerpsPane({ width, height, focused, marketAction }: Pick<PanePro
|
|
|
349
397
|
const refreshMarket = useCallback(() => { void resource.reload(); }, [resource.reload]);
|
|
350
398
|
useAutoRefresh(resource.updatedAt, resource.load, { intervalMs: 60_000 });
|
|
351
399
|
usePaneRefreshKey(refreshMarket, { focused: focused && marketTab && !querySearch.active && (tab !== "history" || !active) });
|
|
352
|
-
|
|
400
|
+
// The listed stock or fund a market tracks opens the way a ticker link does, on the DES already open for that
|
|
401
|
+
// listing when there is one; crypto, indices and commodities have none.
|
|
402
|
+
const underlying = current ? underlyingTicker(current) : null;
|
|
353
403
|
const preview = marketTab ? data?.access === "preview" : !access.hasProAccess;
|
|
354
404
|
const hints: PaneHint[] = [
|
|
355
405
|
...(current && marketAction ? [{ id: marketAction.id, key: marketAction.key, label: marketAction.label, onPress: () => marketAction.onPress(current) }] : []),
|
|
@@ -358,11 +408,17 @@ export function PerpsPane({ width, height, focused, marketAction }: Pick<PanePro
|
|
|
358
408
|
} }] : []),
|
|
359
409
|
...(current && tab !== "evidence" ? [{ id: "evidence", key: "e", label: "vidence", onPress: () => marketTab ? setTab("evidence") : openMarket(current, "evidence") }] : []),
|
|
360
410
|
...(current ? [{ id: "source", key: "o", label: "pen source", onPress: () => void host.openExternal(current.sourceUrl) }] : []),
|
|
361
|
-
...(
|
|
411
|
+
...(underlying ? [{ id: "description", key: "d", label: "es", title: "Description (DES)", onPress: () => openDescription(underlying) },
|
|
412
|
+
// A fund has no statements to analyse.
|
|
413
|
+
...(current?.assetClass === "stocks" ? [{ id: "financials", key: "f", label: "a", title: "Financial analysis (FA)", onPress: () => createPaneFromTemplate("financial-analysis-pane", { symbol: underlying }) }] : []),
|
|
414
|
+
{ id: "graph", key: "g", label: "raph", title: "Price chart (G)", onPress: () => createPaneFromTemplate("chart-composer-pane", { arg: underlying }) }] : []),
|
|
362
415
|
...(preview ? [{ id: "upgrade", key: CLOUD_PLAN_KEY, label: "upgrade", title: "Upgrade to Pro", onPress: upgrade }] : []),
|
|
363
416
|
];
|
|
364
|
-
|
|
365
|
-
|
|
417
|
+
// History dates its own market beside its series; Evidence is dated here.
|
|
418
|
+
const evidenceRows = useMemo(() => tab === "evidence" && active ? [active] : NO_ROWS, [tab, active]);
|
|
419
|
+
const evidenceLine = usePerpStatusLine(evidenceRows, evidenceRows, resource.updatedAt);
|
|
420
|
+
usePaneStatusFooter({ registrationId: "perps", loading: marketTab && resource.loading, error: data ? resource.error : null, stale: marketTab && resource.data?.stale,
|
|
421
|
+
info: evidenceLine, hints });
|
|
366
422
|
usePaneNoticeFooter({ registrationId: "perps:notices", focused, notices: marketTab ? [resource.data?.refreshError,
|
|
367
423
|
...(active?.qualityFlags.map((flag) => flag.replaceAll("_", " ").replaceAll("-", " ")) ?? [])].filter((s): s is string => !!s) : [] });
|
|
368
424
|
if (marketTab && !data && isCloudSessionRequired(resource.error)) return <SignInWall placement="perps-signin" action="view perpetual history" needsVerification={session.needsVerification} />;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
2
|
+
import { fetchPerpSelection, fetchPerpsCompare, fetchPerpsHistory } from "./client";
|
|
3
|
+
import { historyRows, type HistoryMetric } from "./model";
|
|
4
|
+
|
|
5
|
+
/** The coin a pair names: BTC-USD charts the BTC perpetual. */
|
|
6
|
+
function baseAsset(ticker: string): string {
|
|
7
|
+
return ticker.trim().toUpperCase().split(/[-/]/)[0] ?? ticker;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** What the perps pane says where the free preview leaves history out. */
|
|
11
|
+
const PRO_HISTORY = "Full history requires Gloom Pro.";
|
|
12
|
+
|
|
13
|
+
const METRICS: ReadonlyArray<{ metric: HistoryMetric; name: string; unit: string; scale: number; tags: readonly string[] }> = [
|
|
14
|
+
{ metric: "funding", name: "Perpetual funding rate (8h)", unit: "%", scale: 100, tags: ["funding", "carry"] },
|
|
15
|
+
{ metric: "oi", name: "Perpetual open interest", unit: "USD", scale: 1, tags: ["open interest", "OI", "leverage"] },
|
|
16
|
+
{ metric: "premium", name: "Perpetual premium to index", unit: "%", scale: 100, tags: ["premium", "basis"] },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const historyStart = (start: Date | undefined) => (start ?? new Date(Date.now() - 90 * 86_400_000)).toISOString();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A coin's main perpetual contract, as the perps pane picks it, by the
|
|
23
|
+
* history its detail charts: funding, open interest and premium.
|
|
24
|
+
*/
|
|
25
|
+
const METRIC_SERIES: readonly SeriesDefinition[] = METRICS.map(({ metric, name, unit, scale, tags }): SeriesDefinition => ({
|
|
26
|
+
id: `perps:${metric}`,
|
|
27
|
+
name,
|
|
28
|
+
unit,
|
|
29
|
+
frequency: "intraday",
|
|
30
|
+
group: "Crypto",
|
|
31
|
+
tags: ["perpetual", "perps", ...tags],
|
|
32
|
+
input: "crypto",
|
|
33
|
+
load: async ({ ticker, start }) => {
|
|
34
|
+
const market = await fetchPerpSelection(baseAsset(ticker!));
|
|
35
|
+
const marketId = market.rows[0]?.marketId;
|
|
36
|
+
if (!marketId) throw new Error(`No perpetual contract for ${baseAsset(ticker!)}.`);
|
|
37
|
+
const history = await fetchPerpsHistory({
|
|
38
|
+
marketId,
|
|
39
|
+
from: historyStart(start),
|
|
40
|
+
resolution: "auto",
|
|
41
|
+
limit: 5000,
|
|
42
|
+
});
|
|
43
|
+
if (history.locked) throw new Error(PRO_HISTORY);
|
|
44
|
+
return historyRows(history, metric).map((row) => ({ date: row.time, value: row.value == null ? null : row.value * scale }));
|
|
45
|
+
},
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The share of accounts long a coin's perpetual, as the perps pane charts it
|
|
50
|
+
* for a contract whose venue publishes one. Venues count accounts their own
|
|
51
|
+
* way and only some publish a ratio, so the series reads the coin's largest
|
|
52
|
+
* contract that does. History is Pro's.
|
|
53
|
+
*/
|
|
54
|
+
const LONG_SHORT_SERIES: SeriesDefinition = {
|
|
55
|
+
id: "perps:long-accounts",
|
|
56
|
+
name: "Perpetual long account share",
|
|
57
|
+
unit: "%",
|
|
58
|
+
frequency: "intraday",
|
|
59
|
+
group: "Crypto",
|
|
60
|
+
tags: ["perpetual", "perps", "long/short", "long short ratio", "accounts", "positioning"],
|
|
61
|
+
description: "Share of accounts long the coin's largest perpetual contract whose venue publishes a long/short account ratio, hour by hour, as PERP charts it. Needs Pro.",
|
|
62
|
+
input: "crypto",
|
|
63
|
+
load: async ({ ticker, start }) => {
|
|
64
|
+
const base = baseAsset(ticker!);
|
|
65
|
+
const contracts = await fetchPerpsCompare(base);
|
|
66
|
+
if (contracts.access === "preview") throw new Error(PRO_HISTORY);
|
|
67
|
+
// The server lists a coin's contracts by open interest, largest first.
|
|
68
|
+
const market = contracts.rows.find((row) => !row.delisted && row.longShortRatio);
|
|
69
|
+
if (!market) throw new Error(`No ${base} perpetual contract publishes a long/short account ratio.`);
|
|
70
|
+
const history = await fetchPerpsHistory({ marketId: market.marketId, from: historyStart(start), resolution: "auto", limit: 5000 });
|
|
71
|
+
if (history.locked) throw new Error(PRO_HISTORY);
|
|
72
|
+
return historyRows(history, "long-short").map((row) => ({ date: row.time, value: row.value == null ? null : row.value * 100 }));
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const PERP_SERIES: readonly SeriesDefinition[] = [...METRIC_SERIES, LONG_SHORT_SERIES];
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { PluginTarget } from "../../../types/plugin";
|
|
2
2
|
import { compareSemver, formatVersion, requiredGloomberb } from "../../../utils/semver";
|
|
3
3
|
import { runsExternalPlugins } from "../../current-target";
|
|
4
|
+
import { BUILTIN_EDITORIAL } from "../../builtin-editorial";
|
|
5
|
+
import { builtinPluginGroupMembers } from "../../ownership";
|
|
6
|
+
import type { FunctionAccess } from "../../../cli/pane-functions/function-help";
|
|
7
|
+
import { PACK_PLUGIN_IDS } from "./packs";
|
|
4
8
|
|
|
5
9
|
type PluginTier = "official" | "verified" | "community";
|
|
6
10
|
|
|
@@ -9,6 +13,8 @@ export interface RegistryPluginShortcut {
|
|
|
9
13
|
code: string;
|
|
10
14
|
name: string;
|
|
11
15
|
description: string;
|
|
16
|
+
/** Built-ins only: what Free gets of it. */
|
|
17
|
+
access?: FunctionAccess;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
/** One record from https://plugins.gloom.sh/registry.json. */
|
|
@@ -28,7 +34,7 @@ export interface RegistryPlugin {
|
|
|
28
34
|
panes: string[];
|
|
29
35
|
capabilities: string[];
|
|
30
36
|
broker: boolean;
|
|
31
|
-
/** Declared in the plugin's gloom.json; absent from older feeds
|
|
37
|
+
/** Declared in the plugin's gloom.json, or listed for a built-in; absent from older feeds. */
|
|
32
38
|
shortcuts?: RegistryPluginShortcut[];
|
|
33
39
|
};
|
|
34
40
|
minGloomberb?: string;
|
|
@@ -78,7 +84,11 @@ export interface InstalledPlugin {
|
|
|
78
84
|
needsRestart?: boolean;
|
|
79
85
|
}
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
/**
|
|
88
|
+
* `research` holds the built-ins starter packs switch, so a pack's reach is
|
|
89
|
+
* the section above the others; `builtin` the other built-ins.
|
|
90
|
+
*/
|
|
91
|
+
export type MarketplaceSection = "research" | "builtin" | "installed" | "available";
|
|
82
92
|
|
|
83
93
|
export interface MarketplaceEntry {
|
|
84
94
|
id: string;
|
|
@@ -131,8 +141,8 @@ export interface MarketplaceEntry {
|
|
|
131
141
|
|
|
132
142
|
const TIER_RANK: Record<PluginTier, number> = { official: 0, verified: 1, community: 2 };
|
|
133
143
|
|
|
134
|
-
function sectionOf(entry: { installed: boolean; bundled: boolean }): MarketplaceSection {
|
|
135
|
-
if (entry.bundled) return "builtin";
|
|
144
|
+
function sectionOf(entry: { id: string; installed: boolean; bundled: boolean }): MarketplaceSection {
|
|
145
|
+
if (entry.bundled) return PACK_PLUGIN_IDS.includes(entry.id) ? "research" : "builtin";
|
|
136
146
|
return entry.installed ? "installed" : "available";
|
|
137
147
|
}
|
|
138
148
|
|
|
@@ -151,6 +161,11 @@ function repoDirectory(repo: string | undefined): string | null {
|
|
|
151
161
|
return name ? name.toLowerCase() : null;
|
|
152
162
|
}
|
|
153
163
|
|
|
164
|
+
/** The short line a built-in's row reads: its editorial tagline, else its description. */
|
|
165
|
+
function builtinTagline(local: InstalledPlugin): string {
|
|
166
|
+
return BUILTIN_EDITORIAL[local.id]?.tagline ?? local.description ?? "";
|
|
167
|
+
}
|
|
168
|
+
|
|
154
169
|
export function mergeCatalog(options: {
|
|
155
170
|
registry: readonly RegistryPlugin[];
|
|
156
171
|
/** Remote default-branch heads by plugin folder, from `PluginManager.remoteHeads`. */
|
|
@@ -158,7 +173,11 @@ export function mergeCatalog(options: {
|
|
|
158
173
|
installed: readonly InstalledPlugin[];
|
|
159
174
|
target: PluginTarget;
|
|
160
175
|
}): MarketplaceEntry[] {
|
|
161
|
-
const {
|
|
176
|
+
const { installed, target, remoteHeads } = options;
|
|
177
|
+
// A built-in this build split into several, which a feed generated before
|
|
178
|
+
// the split still lists. Its id now only switches its successors together,
|
|
179
|
+
// and they have rows of their own.
|
|
180
|
+
const registry = options.registry.filter((plugin) => !(plugin.bundled && builtinPluginGroupMembers(plugin.id)));
|
|
162
181
|
const remoteHeadFor = (local: InstalledPlugin | undefined) => (
|
|
163
182
|
local?.directory ? remoteHeads?.[local.directory] : undefined
|
|
164
183
|
);
|
|
@@ -193,6 +212,9 @@ export function mergeCatalog(options: {
|
|
|
193
212
|
|
|
194
213
|
for (const plugin of registry) {
|
|
195
214
|
const local = localFor.get(plugin.id);
|
|
215
|
+
// The feed lags the app: a built-in this build renamed or redescribed
|
|
216
|
+
// reads the way the running app has it.
|
|
217
|
+
const builtin = local?.source === "builtin" ? local : null;
|
|
196
218
|
|
|
197
219
|
const base = {
|
|
198
220
|
// A bundled plugin is present whether or not the local catalog reports it,
|
|
@@ -205,10 +227,10 @@ export function mergeCatalog(options: {
|
|
|
205
227
|
};
|
|
206
228
|
entries.push({
|
|
207
229
|
id: plugin.id,
|
|
208
|
-
name: plugin.name,
|
|
209
|
-
tagline: plugin.tagline,
|
|
210
|
-
description: plugin.description,
|
|
211
|
-
categories: plugin.categories,
|
|
230
|
+
name: builtin?.name ?? plugin.name,
|
|
231
|
+
tagline: builtin ? builtinTagline(builtin) : plugin.tagline,
|
|
232
|
+
description: builtin?.description ?? plugin.description,
|
|
233
|
+
categories: builtin ? BUILTIN_EDITORIAL[plugin.id]?.categories ?? plugin.categories : plugin.categories,
|
|
212
234
|
tier: plugin.tier,
|
|
213
235
|
targets: plugin.targets,
|
|
214
236
|
hosts: plugin.hosts,
|
|
@@ -246,7 +268,7 @@ export function mergeCatalog(options: {
|
|
|
246
268
|
: plugin.bundled
|
|
247
269
|
? !plugin.targets.includes(target)
|
|
248
270
|
: !runsExternalPlugins(target) || !plugin.targets.includes(target),
|
|
249
|
-
section: sectionOf(base),
|
|
271
|
+
section: sectionOf({ id: plugin.id, ...base }),
|
|
250
272
|
});
|
|
251
273
|
}
|
|
252
274
|
|
|
@@ -257,10 +279,13 @@ export function mergeCatalog(options: {
|
|
|
257
279
|
entries.push({
|
|
258
280
|
id: local.id,
|
|
259
281
|
name: local.name,
|
|
260
|
-
tagline: local.
|
|
282
|
+
tagline: local.source === "builtin"
|
|
283
|
+
? builtinTagline(local)
|
|
284
|
+
: local.description ?? (local.linked ? "Linked from a local checkout" : "Installed outside the registry"),
|
|
261
285
|
description: local.description,
|
|
262
|
-
categories: local.source === "builtin" ? [] : ["unlisted"],
|
|
263
|
-
|
|
286
|
+
categories: local.source === "builtin" ? [...BUILTIN_EDITORIAL[local.id]?.categories ?? []] : ["unlisted"],
|
|
287
|
+
// Shipped by Gloom like every built-in, whether or not the feed lists it.
|
|
288
|
+
tier: local.source === "builtin" ? "official" : "community",
|
|
264
289
|
targets: local.unsupportedTarget ? [] : [target],
|
|
265
290
|
hosts: [],
|
|
266
291
|
stars: 0,
|
|
@@ -282,7 +307,7 @@ export function mergeCatalog(options: {
|
|
|
282
307
|
lastError: local.lastError,
|
|
283
308
|
needsRestart: local.needsRestart === true,
|
|
284
309
|
unsupportedHere: !!local.unsupportedTarget,
|
|
285
|
-
section: sectionOf(base),
|
|
310
|
+
section: sectionOf({ id: local.id, ...base }),
|
|
286
311
|
});
|
|
287
312
|
}
|
|
288
313
|
|
|
@@ -366,6 +391,12 @@ export interface MarketplaceStatus {
|
|
|
366
391
|
text: string;
|
|
367
392
|
}
|
|
368
393
|
|
|
394
|
+
/**
|
|
395
|
+
* The built-in the research pane, DES and the G charts come from. It can be
|
|
396
|
+
* switched off, after a confirmation, and every starter pack keeps it on.
|
|
397
|
+
*/
|
|
398
|
+
export const CORE_PLUGIN_ID = "ticker-core";
|
|
399
|
+
|
|
369
400
|
/**
|
|
370
401
|
* One word for "what should I do about this row". Health outranks state:
|
|
371
402
|
* a plugin that is enabled but failed to load is `failed`, not `enabled`.
|
|
@@ -383,21 +414,32 @@ export function statusOf(entry: MarketplaceEntry): MarketplaceStatus {
|
|
|
383
414
|
const required = requiredGloomberb(entry.minGloomberb);
|
|
384
415
|
const needsGloomberb: MarketplaceStatus | null = required ? { kind: "needs-gloomberb", text: `needs ${required}` } : null;
|
|
385
416
|
if (!entry.installed) return needsGloomberb ?? { kind: "none", text: "" };
|
|
386
|
-
if (!entry.enabled) return { kind: "disabled", text: "
|
|
417
|
+
if (!entry.enabled) return { kind: "disabled", text: "off" };
|
|
418
|
+
if (entry.id === CORE_PLUGIN_ID && entry.bundled) return { kind: "enabled", text: "core" };
|
|
387
419
|
if (entry.needsSetup) return { kind: "needs-setup", text: "needs setup" };
|
|
388
420
|
if (hasUpdate(entry)) return needsGloomberb ?? { kind: "update", text: "update" };
|
|
389
421
|
if (entry.errorCount > 0) return { kind: "errors", text: `errors (${entry.errorCount})` };
|
|
390
|
-
return { kind: "enabled", text: "
|
|
422
|
+
return { kind: "enabled", text: "on" };
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** Whether a section lists plugins that ship inside Gloomberb. */
|
|
426
|
+
function isBuiltinSection(section: MarketplaceSection): boolean {
|
|
427
|
+
return section === "research" || section === "builtin";
|
|
391
428
|
}
|
|
392
429
|
|
|
393
430
|
/**
|
|
394
|
-
* Sorted for a sectioned list:
|
|
395
|
-
*
|
|
431
|
+
* Sorted for a sectioned list: the research built-ins in pack order, the
|
|
432
|
+
* other built-ins, then installed, then available; within the last two the
|
|
433
|
+
* curated order: featured, then tier, then stars.
|
|
396
434
|
*/
|
|
397
435
|
export function sortEntries(entries: readonly MarketplaceEntry[]): MarketplaceEntry[] {
|
|
398
|
-
const SECTION_RANK: Record<MarketplaceSection, number> = {
|
|
436
|
+
const SECTION_RANK: Record<MarketplaceSection, number> = { research: 0, builtin: 1, installed: 2, available: 3 };
|
|
399
437
|
return [...entries].sort((a, b) => {
|
|
400
438
|
if (a.section !== b.section) return SECTION_RANK[a.section] - SECTION_RANK[b.section];
|
|
439
|
+
if (a.section === "research") return PACK_PLUGIN_IDS.indexOf(a.id) - PACK_PLUGIN_IDS.indexOf(b.id);
|
|
440
|
+
// The other built-ins read alphabetically after the featured one: a
|
|
441
|
+
// repository's stars say nothing about something built in.
|
|
442
|
+
if (a.section === "builtin" && a.featured === b.featured) return a.name.localeCompare(b.name);
|
|
401
443
|
if (a.featured !== b.featured) return a.featured ? -1 : 1;
|
|
402
444
|
if (a.tier !== b.tier) return TIER_RANK[a.tier] - TIER_RANK[b.tier];
|
|
403
445
|
if (a.stars !== b.stars) return b.stars - a.stars;
|
|
@@ -413,8 +455,8 @@ export function filterEntries(
|
|
|
413
455
|
|
|
414
456
|
return entries.filter((entry) => {
|
|
415
457
|
// Core modules with no switch are not something the user manages; a
|
|
416
|
-
// toggleable built-in is,
|
|
417
|
-
if (entry.section
|
|
458
|
+
// toggleable built-in is, unless the built-in filter is off.
|
|
459
|
+
if (isBuiltinSection(entry.section) && (!entry.toggleable || !options.showBuiltin)) return false;
|
|
418
460
|
if (options.category && !entry.categories.includes(options.category)) return false;
|
|
419
461
|
if (!query) return true;
|
|
420
462
|
return [entry.name, entry.id, entry.tagline, entry.description, ...entry.categories]
|
|
@@ -435,6 +477,7 @@ export type MarketplaceRow =
|
|
|
435
477
|
| { type: "entry"; entry: MarketplaceEntry };
|
|
436
478
|
|
|
437
479
|
export const SECTION_LABELS: Record<MarketplaceSection, string> = {
|
|
480
|
+
research: "Research and markets",
|
|
438
481
|
installed: "Installed",
|
|
439
482
|
available: "Available",
|
|
440
483
|
builtin: "Built in",
|