gloomberb 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -6,6 +6,7 @@ import type { KeyEventLike } from "../../react/input";
|
|
|
6
6
|
import type { NativeRendererHost, PixelResolution, RendererHost } from "../../ui/host";
|
|
7
7
|
import { colors } from "../../theme/colors";
|
|
8
8
|
import { safeExternalUrl } from "../../utils/external-url";
|
|
9
|
+
import { browserOpenCommands, runBrowserOpener } from "./browser-open";
|
|
9
10
|
import { buildTerminalMediaArgs, createTerminalMediaReaper, terminalMediaStateFile } from "./terminal-media";
|
|
10
11
|
import { saveTextFileToDownloads } from "../../utils/save-text-file";
|
|
11
12
|
import { installInteractionPerformanceRecorder } from "./interaction-performance";
|
|
@@ -129,23 +130,13 @@ export async function createOpenTuiHost(): Promise<OpenTuiHost> {
|
|
|
129
130
|
requestExit: () => renderer.destroy(),
|
|
130
131
|
async openExternal(rawUrl) {
|
|
131
132
|
const url = safeExternalUrl(rawUrl);
|
|
132
|
-
if (!url) return;
|
|
133
|
-
const command
|
|
134
|
-
|
|
135
|
-
: process.platform === "win32"
|
|
136
|
-
? ["cmd", "/c", "start", "", url]
|
|
137
|
-
: ["xdg-open", url];
|
|
138
|
-
try {
|
|
139
|
-
const proc = Bun.spawn(command, {
|
|
140
|
-
stdout: "ignore",
|
|
141
|
-
stderr: "ignore",
|
|
142
|
-
});
|
|
143
|
-
if (await proc.exited === 0) return;
|
|
144
|
-
} catch {
|
|
145
|
-
// No opener installed (xdg-open is missing on minimal Linux and WSL).
|
|
133
|
+
if (!url) return false;
|
|
134
|
+
for (const command of browserOpenCommands(url, process.env, process.platform)) {
|
|
135
|
+
if (await runBrowserOpener(command)) return true;
|
|
146
136
|
}
|
|
147
137
|
// Leave the link on the clipboard, so it can at least be pasted.
|
|
148
138
|
renderer.copyToClipboardOSC52(url);
|
|
139
|
+
return false;
|
|
149
140
|
},
|
|
150
141
|
async copyText(text) {
|
|
151
142
|
if (!text) return;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Jimp } from "jimp";
|
|
2
1
|
import type { NativeChartBitmap } from "../../../components/chart/native/chart-rasterizer";
|
|
3
2
|
|
|
4
3
|
type ImageObjectFit = "contain" | "cover";
|
|
@@ -67,7 +66,9 @@ function loadSourceImage(src: string): Promise<JimpImageLike> {
|
|
|
67
66
|
if (cached) return cached;
|
|
68
67
|
|
|
69
68
|
const promise = fetchImageBytes(src)
|
|
70
|
-
|
|
69
|
+
// Loaded with the first image: the decoder is a large part of what the
|
|
70
|
+
// terminal would otherwise load before it draws anything.
|
|
71
|
+
.then(async (bytes) => (await import("jimp")).Jimp.read(bytes))
|
|
71
72
|
.then(adaptJimpImage)
|
|
72
73
|
.catch((error) => {
|
|
73
74
|
sourceImageCache.delete(src);
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
import "@opentui/core";
|
|
1
|
+
import { resolveRenderLib } from "@opentui/core";
|
|
2
|
+
import { loadRenderLib } from "./render-lib";
|
|
3
|
+
|
|
4
|
+
// Loaded the way a launch loads it, so the smoke covers the cache folder used
|
|
5
|
+
// when the temp folder cannot run the library.
|
|
6
|
+
await loadRenderLib();
|
|
7
|
+
// Importing @opentui/core swallows a render library that fails to load and
|
|
8
|
+
// throws only on first use, so load it here: the glibc library on a musl
|
|
9
|
+
// system fails this way ("getcontext: symbol not found").
|
|
10
|
+
resolveRenderLib();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CliRenderer } from "@opentui/core";
|
|
2
|
-
import { Jimp } from "jimp";
|
|
3
2
|
import type { NativeSurfaceManager } from "../../../components/chart/native/surface/manager";
|
|
4
3
|
import type { CellRect } from "../../../components/chart/native/chart-rasterizer";
|
|
5
4
|
import { intersectCellRects } from "../../../components/chart/native/chart-rasterizer";
|
|
@@ -95,6 +94,8 @@ export async function captureTerminalPaneImage(
|
|
|
95
94
|
const base = hexRgb(background);
|
|
96
95
|
const layers = imageLayers(manager, clipRect(rect, renderer.currentRenderBuffer.width, renderer.currentRenderBuffer.height)!);
|
|
97
96
|
const image = rasterizeFrame(frame, layers, base);
|
|
97
|
+
// Loaded on the first capture rather than with the terminal.
|
|
98
|
+
const { Jimp } = await import("jimp");
|
|
98
99
|
const jimp = new Jimp({ width: image.width, height: image.height, data: Buffer.from(image.pixels.buffer, image.pixels.byteOffset, image.pixels.byteLength) });
|
|
99
100
|
const png = await jimp.getBuffer("image/png");
|
|
100
101
|
return {
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads OpenTUI's native render library before the terminal starts, and
|
|
3
|
+
* keeps the standalone binary starting when its temp folder cannot run it.
|
|
4
|
+
*
|
|
5
|
+
* A Bun-compiled binary carries the library inside itself. Bun's dlopen
|
|
6
|
+
* writes it to a new file in the temp folder on every launch and loads that
|
|
7
|
+
* file. When the folder is full or read-only the write fails and the load
|
|
8
|
+
* fails on the path inside the binary ("/$bunfs/root/libopentui-*.so: cannot
|
|
9
|
+
* open shared object file"); when it is mounted noexec the file is written
|
|
10
|
+
* but cannot be mapped ("failed to map segment from shared object"). Either
|
|
11
|
+
* way the library is copied once into the native cache folder and loaded
|
|
12
|
+
* from there on every later launch. The copy is named after the embedded
|
|
13
|
+
* file, whose name carries a hash of its contents, so an upgrade never loads
|
|
14
|
+
* an older library.
|
|
15
|
+
*
|
|
16
|
+
* Bun never deletes the files it writes, so each launch would leave 8 MB in
|
|
17
|
+
* the temp folder until it fills up. On Linux the one this launch mapped is
|
|
18
|
+
* removed once it is loaded: the mapping keeps it usable until exit.
|
|
19
|
+
*/
|
|
20
|
+
import { mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
21
|
+
import { basename, dirname, join } from "path";
|
|
22
|
+
import { getGloomberbDirs } from "../../data/config/home";
|
|
23
|
+
|
|
24
|
+
/** Where the render library sits inside a standalone binary. */
|
|
25
|
+
interface EmbeddedRenderLib {
|
|
26
|
+
/** The library @opentui/core loads by default. */
|
|
27
|
+
path: string;
|
|
28
|
+
/** Linux: the musl library, which it loads instead when `OPENTUI_LIBC` is `musl`. */
|
|
29
|
+
musl?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let embeddedRenderLib: EmbeddedRenderLib | null = null;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Where the standalone binary carries its render library. A package or a
|
|
36
|
+
* checkout has none.
|
|
37
|
+
* @knipignore Called by the module scripts/build.ts writes for the release binary.
|
|
38
|
+
*/
|
|
39
|
+
export function useEmbeddedRenderLib(lib: EmbeddedRenderLib): void {
|
|
40
|
+
embeddedRenderLib = lib;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The embedded library @opentui/core picks, by the same rule it uses. */
|
|
44
|
+
function embeddedRenderLibPath(env: NodeJS.ProcessEnv): string | null {
|
|
45
|
+
if (!embeddedRenderLib) return null;
|
|
46
|
+
return env.OPENTUI_LIBC === "musl" && embeddedRenderLib.musl ? embeddedRenderLib.musl : embeddedRenderLib.path;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The folder Bun writes embedded libraries to before loading them: a
|
|
51
|
+
* non-empty `BUN_TMPDIR`, else `TMPDIR`, `TMP` or `TEMP`, else the platform's
|
|
52
|
+
* (Bun 1.3, `RealFS.tmpdirPath`).
|
|
53
|
+
*/
|
|
54
|
+
function bunTempDir(env: NodeJS.ProcessEnv, platform: NodeJS.Platform): string {
|
|
55
|
+
const dir = env.BUN_TMPDIR || env.TMPDIR || env.TMP || env.TEMP;
|
|
56
|
+
if (dir) return dir.length > 1 && /[\\/]$/.test(dir) ? dir.slice(0, -1) : dir;
|
|
57
|
+
if (platform === "darwin") return "/private/tmp";
|
|
58
|
+
if (platform === "win32") return `${(env.SYSTEMROOT || env.WINDIR || "C:\\Windows").replace(/\\$/, "")}\\Temp`;
|
|
59
|
+
return "/tmp";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** How Bun names the copy it writes: `.<hex>-<HEX>.so` (`.dylib`, `.dll`). */
|
|
63
|
+
const BUN_EXTRACTED_NAME = /^\.[0-9a-f]+-[0-9A-F]+\.(?:so|dylib|dll)$/;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The temp folder copies this process has mapped, read from
|
|
67
|
+
* `/proc/self/maps`: `address perms offset dev inode path`, with
|
|
68
|
+
* ` (deleted)` after a path that is gone.
|
|
69
|
+
*/
|
|
70
|
+
function mappedExtractedCopies(maps: string, tempDir: string): string[] {
|
|
71
|
+
const copies = new Set<string>();
|
|
72
|
+
for (const line of maps.split("\n")) {
|
|
73
|
+
const path = /^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\/.*)$/.exec(line)?.[1];
|
|
74
|
+
if (!path || path.endsWith(" (deleted)")) continue;
|
|
75
|
+
if (dirname(path) === tempDir && BUN_EXTRACTED_NAME.test(basename(path))) copies.add(path);
|
|
76
|
+
}
|
|
77
|
+
return [...copies];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Copies of the library Bun wrote to the temp folder during this launch and
|
|
82
|
+
* could not load: a noexec folder holds a whole copy for every attempt, a
|
|
83
|
+
* full one a cut-off copy. Matched by Bun's naming, a size up to the
|
|
84
|
+
* library's and a write time after this process started.
|
|
85
|
+
*/
|
|
86
|
+
function failedExtractedCopies(tempDir: string, size: number, sinceMs: number): string[] {
|
|
87
|
+
return listDir(tempDir).filter((name) => BUN_EXTRACTED_NAME.test(name)).map((name) => join(tempDir, name)).filter((path) => {
|
|
88
|
+
try {
|
|
89
|
+
const stat = statSync(path);
|
|
90
|
+
return stat.isFile() && stat.size <= size && stat.mtimeMs >= sinceMs;
|
|
91
|
+
} catch {
|
|
92
|
+
// Intentional ignore: a copy that vanished needs no removal.
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function listDir(dir: string): string[] {
|
|
99
|
+
try {
|
|
100
|
+
return readdirSync(dir);
|
|
101
|
+
} catch {
|
|
102
|
+
// Intentional ignore: an unreadable folder holds nothing we could remove.
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function removeFiles(paths: readonly string[]): void {
|
|
108
|
+
for (const path of paths) {
|
|
109
|
+
try {
|
|
110
|
+
rmSync(path, { force: true });
|
|
111
|
+
} catch {
|
|
112
|
+
// Intentional ignore: a copy left behind only costs disk space.
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Puts the embedded library in the cache folder unless an intact copy is there, and returns its path. */
|
|
118
|
+
function cachedCopy(embeddedPath: string, size: number, cacheDir: string): string {
|
|
119
|
+
const name = basename(embeddedPath);
|
|
120
|
+
const target = join(cacheDir, name);
|
|
121
|
+
try {
|
|
122
|
+
if (statSync(target).size === size) return target;
|
|
123
|
+
} catch {
|
|
124
|
+
// Intentional ignore: no copy yet, written below.
|
|
125
|
+
}
|
|
126
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
127
|
+
const partial = join(cacheDir, `.${name}.${process.pid}.partial`);
|
|
128
|
+
try {
|
|
129
|
+
writeFileSync(partial, readFileSync(embeddedPath), { mode: 0o755 });
|
|
130
|
+
renameSync(partial, target);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
removeFiles([partial]);
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
// The copy an earlier version left, now unused. Another launch's partial
|
|
136
|
+
// copy (dot-named) is still being written and stays.
|
|
137
|
+
removeFiles(listDir(cacheDir).filter((entry) => entry !== name && entry.startsWith("libopentui")).map((entry) => join(cacheDir, entry)));
|
|
138
|
+
return target;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* A failed load the folder the library was in explains: it never left the
|
|
143
|
+
* binary because the temp folder took no file (`$bunfs`, `~BUN` on Windows),
|
|
144
|
+
* or the folder does not let code run from it (glibc: "failed to map
|
|
145
|
+
* segment", musl: "Operation not permitted"). A missing symbol or dependency
|
|
146
|
+
* fails wherever the file sits.
|
|
147
|
+
*/
|
|
148
|
+
function isFolderFailure(error: unknown): boolean {
|
|
149
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
150
|
+
return /\$bunfs|~BUN|failed to map segment|operation not permitted|permission denied/i.test(message);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Neither the temp folder nor the cache folder can hold and run the library. */
|
|
154
|
+
export class RenderLibUnavailableError extends Error {
|
|
155
|
+
constructor(tempDir: string, cacheDir: string) {
|
|
156
|
+
super(
|
|
157
|
+
`Gloom can't load its render library: neither the temp folder ${tempDir} nor ${cacheDir} can hold and run it. `
|
|
158
|
+
+ "Start it with TMPDIR set to a writable folder that allows running programs: TMPDIR=/path/to/folder gloom",
|
|
159
|
+
);
|
|
160
|
+
this.name = "RenderLibUnavailableError";
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface RenderLibLoadOptions {
|
|
165
|
+
/** Points @opentui/core at a library file (undefined: the one it picks) and loads it, throwing what loading threw. */
|
|
166
|
+
load(path?: string): void;
|
|
167
|
+
/** The library inside a standalone binary; null for a package or a checkout. */
|
|
168
|
+
embeddedPath: string | null;
|
|
169
|
+
tempDir: string;
|
|
170
|
+
cacheDir: string;
|
|
171
|
+
/** `/proc/self/maps`, or null where there is none. */
|
|
172
|
+
readMaps(): string | null;
|
|
173
|
+
/** When this process started, in epoch milliseconds. */
|
|
174
|
+
startedAtMs: number;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Loads the library from the temp folder, and from the cache folder when
|
|
179
|
+
* the temp folder cannot hold or run it. Anything this cannot help with is
|
|
180
|
+
* left as it was: the terminal then fails on it where it always did.
|
|
181
|
+
* Throws {@link RenderLibUnavailableError} when both folders fail.
|
|
182
|
+
*/
|
|
183
|
+
export function loadRenderLibWith(options: RenderLibLoadOptions): void {
|
|
184
|
+
const { load, embeddedPath, tempDir, cacheDir } = options;
|
|
185
|
+
let tempError: unknown;
|
|
186
|
+
try {
|
|
187
|
+
load();
|
|
188
|
+
if (embeddedPath) removeFiles(mappedExtractedCopies(options.readMaps() ?? "", realPath(tempDir)));
|
|
189
|
+
return;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
if (!embeddedPath) return;
|
|
192
|
+
tempError = error;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let size: number;
|
|
196
|
+
try {
|
|
197
|
+
size = statSync(embeddedPath).size;
|
|
198
|
+
} catch {
|
|
199
|
+
// Intentional ignore: without the embedded file there is nothing to copy, so the original failure stands.
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// The margin allows for file systems with coarse times.
|
|
203
|
+
removeFiles(failedExtractedCopies(tempDir, size, options.startedAtMs - 2_000));
|
|
204
|
+
|
|
205
|
+
let cachePath: string;
|
|
206
|
+
try {
|
|
207
|
+
cachePath = cachedCopy(embeddedPath, size, cacheDir);
|
|
208
|
+
} catch {
|
|
209
|
+
// The cache folder cannot hold it either. Only the temp folder's fault is reported as such.
|
|
210
|
+
if (isFolderFailure(tempError)) throw new RenderLibUnavailableError(tempDir, cacheDir);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
load(cachePath);
|
|
215
|
+
} catch (cacheError) {
|
|
216
|
+
if (isFolderFailure(tempError) && isFolderFailure(cacheError)) throw new RenderLibUnavailableError(tempDir, cacheDir);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function realPath(path: string): string {
|
|
221
|
+
try {
|
|
222
|
+
return realpathSync(path);
|
|
223
|
+
} catch {
|
|
224
|
+
// Intentional ignore: a temp folder that does not resolve holds nothing mapped.
|
|
225
|
+
return path;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function readProcessMaps(): string | null {
|
|
230
|
+
if (process.platform !== "linux") return null;
|
|
231
|
+
try {
|
|
232
|
+
return readFileSync("/proc/self/maps", "utf8");
|
|
233
|
+
} catch {
|
|
234
|
+
// Intentional ignore: without /proc the copy stays, as it always did.
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Loads the render library for this process; see {@link loadRenderLibWith}. */
|
|
240
|
+
export async function loadRenderLib(): Promise<void> {
|
|
241
|
+
const { resolveRenderLib, setRenderLibPath } = await import("@opentui/core");
|
|
242
|
+
loadRenderLibWith({
|
|
243
|
+
load(path) {
|
|
244
|
+
if (path) setRenderLibPath(path);
|
|
245
|
+
resolveRenderLib();
|
|
246
|
+
},
|
|
247
|
+
embeddedPath: embeddedRenderLibPath(process.env),
|
|
248
|
+
tempDir: bunTempDir(process.env, process.platform),
|
|
249
|
+
cacheDir: getGloomberbDirs().nativeCache,
|
|
250
|
+
readMaps: readProcessMaps,
|
|
251
|
+
startedAtMs: performance.timeOrigin,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
@@ -3,7 +3,7 @@ import { testRender } from "@opentui/react/test-utils";
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A global install runs react-reconciler without its patch (see
|
|
6
|
-
* bin/
|
|
6
|
+
* bin/gloom). If the dev build's user timing turns back on, every render
|
|
7
7
|
* adds a performance.measure entry that Bun never frees (#452).
|
|
8
8
|
*/
|
|
9
9
|
export async function assertRendersLeaveNoTimingEntries(): Promise<void> {
|
|
@@ -60,7 +60,7 @@ export async function startOpenTuiApp({ externalPlugins, cliLaunchRequest }: Sta
|
|
|
60
60
|
debugLog.interceptConsole();
|
|
61
61
|
|
|
62
62
|
const appLog = debugLog.createLogger("app");
|
|
63
|
-
appLog.info("
|
|
63
|
+
appLog.info("Gloom starting");
|
|
64
64
|
const remoteControlAdapter: RemoteControlAdapter = {
|
|
65
65
|
terminalDevice: { kind: "tui", name: hostname() },
|
|
66
66
|
startServer: ({ dataDir, handle }) => {
|
|
@@ -108,7 +108,7 @@ export function LayoutShareView({
|
|
|
108
108
|
return (
|
|
109
109
|
<main className="layout-share wide">
|
|
110
110
|
<header>
|
|
111
|
-
<p className="eyebrow">Shared via
|
|
111
|
+
<p className="eyebrow">Shared via Gloom</p>
|
|
112
112
|
<h1>{entry.name}</h1>
|
|
113
113
|
<p className="layout-meta">{[author, date, `${entry.layout.instances.length} panes`].filter(Boolean).join(" · ")}</p>
|
|
114
114
|
</header>
|
|
@@ -126,7 +126,7 @@ export function LayoutShareView({
|
|
|
126
126
|
|
|
127
127
|
<div className="handoff">
|
|
128
128
|
<a className="cta" href={openLiveUrl}>Use this layout</a>
|
|
129
|
-
<p className="descriptor">Opens in
|
|
129
|
+
<p className="descriptor">Opens in Gloom as an independent, editable copy.</p>
|
|
130
130
|
</div>
|
|
131
131
|
</main>
|
|
132
132
|
);
|
|
@@ -40,7 +40,7 @@ function LayoutApp({ id }: { id: string }) {
|
|
|
40
40
|
|
|
41
41
|
return state.entry
|
|
42
42
|
? <LayoutShareView entry={state.entry} openLiveUrl={openLiveMarketplaceLayoutUrl(id)} />
|
|
43
|
-
: <main><h1>
|
|
43
|
+
: <main><h1>Gloom</h1><p>{state.error ?? "Loading shared layout..."}</p></main>;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function ContentShareApp({ id }: { id: string }) {
|
|
@@ -91,18 +91,18 @@ function ContentShareApp({ id }: { id: string }) {
|
|
|
91
91
|
/>
|
|
92
92
|
);
|
|
93
93
|
}
|
|
94
|
-
return <main><h1>
|
|
94
|
+
return <main><h1>Gloom</h1><p>{state.error ?? "Loading shared view..."}</p></main>;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
function SocialShareApp() {
|
|
98
98
|
const pathname = window.location.pathname;
|
|
99
99
|
const layoutId = parseMarketplaceLayoutId(pathname);
|
|
100
100
|
if (layoutId) return <LayoutApp id={layoutId} />;
|
|
101
|
-
if (pathname.startsWith("/l/")) return <main><h1>
|
|
101
|
+
if (pathname.startsWith("/l/")) return <main><h1>Gloom</h1><p>Invalid layout link.</p></main>;
|
|
102
102
|
const shareId = parseShareId(pathname);
|
|
103
103
|
return shareId
|
|
104
104
|
? <ContentShareApp id={shareId} />
|
|
105
|
-
: <main><h1>
|
|
105
|
+
: <main><h1>Gloom</h1><p>Invalid share link.</p></main>;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
const root = document.getElementById("root");
|
|
@@ -89,7 +89,7 @@ export function ShareView({
|
|
|
89
89
|
return (
|
|
90
90
|
<main className="pane">
|
|
91
91
|
<header>
|
|
92
|
-
<p className="eyebrow">Shared via
|
|
92
|
+
<p className="eyebrow">Shared via Gloom</p>
|
|
93
93
|
<h1>{share.data.title}</h1>
|
|
94
94
|
{share.data.description ? <p className="pane-description">{share.data.description}</p> : null}
|
|
95
95
|
</header>
|
package/src/series/resolve.ts
CHANGED
|
@@ -6,7 +6,8 @@ import type {
|
|
|
6
6
|
SeriesPeriod,
|
|
7
7
|
TimeSeriesPoint,
|
|
8
8
|
} from "../time-series/types";
|
|
9
|
-
import { getPresetResolution,
|
|
9
|
+
import { chartBarSizeSource, getPresetResolution, isCustomChartResolution } from "../time-series/resolution";
|
|
10
|
+
import { futuresSessionOpenMinute } from "../market-data/market/trading-sessions";
|
|
10
11
|
import { SERIES_COLORS } from "../theme/series-colors";
|
|
11
12
|
import type {
|
|
12
13
|
LoadedSeriesDefinition,
|
|
@@ -74,9 +75,24 @@ function seriesColor(id: string, lineIndex = 0): string {
|
|
|
74
75
|
return SERIES_COLORS[(hash + lineIndex) % SERIES_COLORS.length]!;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
/**
|
|
79
|
+
* The bars a chart draws prices in, as a load request states them: the bar
|
|
80
|
+
* size it was set to, else its range's default. A size the source does not
|
|
81
|
+
* serve (4h) goes as the source bars it is built from (`resolution: 1h`) and
|
|
82
|
+
* the size itself (`barSize: 4h`), so a series that knows only the source
|
|
83
|
+
* sizes still gets one it knows.
|
|
84
|
+
*/
|
|
85
|
+
function viewportBars(viewport: ChartViewportSpec, ticker: string | undefined): Pick<SeriesLoadRequest, "resolution" | "barSize"> {
|
|
86
|
+
if (viewport.resolution === "auto") return { resolution: getPresetResolution(viewport.range) };
|
|
87
|
+
if (!isCustomChartResolution(viewport.resolution)) return { resolution: viewport.resolution };
|
|
88
|
+
const openMinute = ticker ? futuresSessionOpenMinute(splitTicker(ticker).symbol, splitTicker(ticker).exchange) : null;
|
|
89
|
+
return { resolution: chartBarSizeSource(viewport.resolution, [], openMinute), barSize: viewport.resolution };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** `NESN:XSWX` as its symbol and listing. */
|
|
93
|
+
function splitTicker(ticker: string): { symbol: string; exchange: string } {
|
|
94
|
+
const colon = ticker.lastIndexOf(":");
|
|
95
|
+
return colon > 0 ? { symbol: ticker.slice(0, colon), exchange: ticker.slice(colon + 1) } : { symbol: ticker, exchange: "" };
|
|
80
96
|
}
|
|
81
97
|
|
|
82
98
|
/** The dates a chart viewport covers, as a series load request takes them. */
|
|
@@ -133,7 +149,7 @@ function loadSeries(definition: LoadedSeriesDefinition, request: SeriesLoadReque
|
|
|
133
149
|
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
134
150
|
// A window measured back from now moves by milliseconds between the lines' requests.
|
|
135
151
|
const minute = (date: Date | undefined) => date ? Math.floor(date.getTime() / 60_000) : null;
|
|
136
|
-
const key = JSON.stringify([shared.ticker ?? null, minute(shared.start), minute(shared.end), shared.resolution ?? null]);
|
|
152
|
+
const key = JSON.stringify([shared.ticker ?? null, minute(shared.start), minute(shared.end), shared.resolution ?? null, shared.barSize ?? null]);
|
|
137
153
|
let byKey = sharedLoads.get(definition);
|
|
138
154
|
if (!byKey) sharedLoads.set(definition, byKey = new Map());
|
|
139
155
|
let load = byKey.get(key);
|
|
@@ -182,7 +198,7 @@ export async function resolveLoadedSeries(
|
|
|
182
198
|
const { points, edge, warning, attribution } = loadResult(await loadSeries(definition, {
|
|
183
199
|
...seriesLoadWindow(request.viewport, now),
|
|
184
200
|
...(ticker ? { ticker } : {}),
|
|
185
|
-
|
|
201
|
+
...viewportBars(request.viewport, ticker),
|
|
186
202
|
...(request.signal ? { signal: request.signal } : {}),
|
|
187
203
|
}), line);
|
|
188
204
|
const seriesId = ticker ? `${definition.id}/${ticker}` : definition.id;
|
package/src/series/standalone.ts
CHANGED
|
@@ -4,11 +4,12 @@ import type { CapabilityInvoker } from "../capabilities/types";
|
|
|
4
4
|
import type { GloomPlugin } from "../types/plugin";
|
|
5
5
|
import { resolveRegisteredSeries } from "./capability";
|
|
6
6
|
import { readSeriesFolder } from "./files";
|
|
7
|
-
import { SeriesRegistry } from "./registry";
|
|
7
|
+
import { SeriesRegistry, seriesExpression } from "./registry";
|
|
8
|
+
import type { SeriesDefinition } from "./types";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Charts the catalog's loaded series where no plugin runtime runs, such as a
|
|
11
|
-
* `
|
|
12
|
+
* `gloom fn G` report: the series plugins declare, and the files in the
|
|
12
13
|
* data directory's series folder. Series a plugin registers from its setup
|
|
13
14
|
* need the app.
|
|
14
15
|
*/
|
|
@@ -47,3 +48,30 @@ export function standaloneSeriesInvoker(
|
|
|
47
48
|
},
|
|
48
49
|
};
|
|
49
50
|
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The plugins' catalog series by what `fn G` charts each as (`FRED:DFII10`),
|
|
54
|
+
* where no plugin runtime runs: a series with an input (a ticker's field) is
|
|
55
|
+
* no one expression. The first plugin to declare an expression keeps it, as
|
|
56
|
+
* the registry's `findByExpression` does.
|
|
57
|
+
*/
|
|
58
|
+
export function standaloneSeriesCatalog(
|
|
59
|
+
plugins: readonly GloomPlugin[],
|
|
60
|
+
disabledPlugins: readonly string[] = [],
|
|
61
|
+
): (expression: string) => SeriesDefinition | undefined {
|
|
62
|
+
let byExpression: Map<string, SeriesDefinition> | null = null;
|
|
63
|
+
return (expression) => {
|
|
64
|
+
if (!byExpression) {
|
|
65
|
+
byExpression = new Map();
|
|
66
|
+
for (const plugin of plugins) {
|
|
67
|
+
if (disabledPlugins.includes(plugin.id)) continue;
|
|
68
|
+
for (const definition of plugin.series ?? []) {
|
|
69
|
+
if (definition.input) continue;
|
|
70
|
+
const key = seriesExpression(definition);
|
|
71
|
+
if (!byExpression.has(key)) byExpression.set(key, definition);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return byExpression.get(expression);
|
|
76
|
+
};
|
|
77
|
+
}
|
package/src/series/types.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* either loads its own history (`load`) or points at something the composer
|
|
7
7
|
* already draws (`expression`), such as a FRED series or a ticker field.
|
|
8
8
|
*/
|
|
9
|
-
import type { ManualChartResolution } from "../time-series/resolution";
|
|
9
|
+
import type { ChartBarSize, ManualChartResolution } from "../time-series/resolution";
|
|
10
10
|
|
|
11
11
|
/** How often a series gets a new observation. */
|
|
12
12
|
export type SeriesFrequency =
|
|
@@ -72,6 +72,13 @@ export interface SeriesLoadRequest {
|
|
|
72
72
|
* bars uses it to compute on the same bars.
|
|
73
73
|
*/
|
|
74
74
|
resolution?: ManualChartResolution;
|
|
75
|
+
/**
|
|
76
|
+
* Set when the chart builds its bars from `resolution` bars rather than
|
|
77
|
+
* drawing those (`4h` from `1h`, `2d` from `1d`): the bar size it draws. A
|
|
78
|
+
* series computed from a ticker's bars builds them the same way with
|
|
79
|
+
* `aggregatePriceBars`, so its points fall on the chart's bars.
|
|
80
|
+
*/
|
|
81
|
+
barSize?: ChartBarSize;
|
|
75
82
|
signal?: AbortSignal;
|
|
76
83
|
}
|
|
77
84
|
|
package/src/shares/api.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiRequestError } from "../api-client/errors";
|
|
2
|
+
import { DataServiceUnreachableError } from "../utils/network-failure";
|
|
2
3
|
import { parseSharePayload, type SharePayload } from "./payload";
|
|
3
4
|
|
|
4
5
|
declare const __GLOOMBERB_API_URL__: string | undefined;
|
|
@@ -36,11 +37,13 @@ function validDate(value: unknown): value is string {
|
|
|
36
37
|
* A request that never got an answer, in the words of whichever fetch made
|
|
37
38
|
* it: a browser's ("Failed to fetch", Safari's "Load failed", Firefox's
|
|
38
39
|
* "NetworkError ..."), Bun's ("Unable to connect ...", which the desktop
|
|
39
|
-
* relays from its Bun process as a plain message),
|
|
40
|
+
* relays from its Bun process as a plain message), the Cloud client's
|
|
41
|
+
* `DataServiceUnreachableError` for any of them, or a timeout.
|
|
40
42
|
*/
|
|
41
43
|
const NETWORK_FAILURE = /failed to fetch|load failed|networkerror|network connection was lost|appears to be offline|fetch failed|unable to connect|socket connection was closed|typo in the url or port|timed out/i;
|
|
42
44
|
|
|
43
45
|
function isNetworkFailure(error: unknown): boolean {
|
|
46
|
+
if (error instanceof DataServiceUnreachableError) return true;
|
|
44
47
|
if (!error || typeof error !== "object") return false;
|
|
45
48
|
const { name, message } = error as { name?: unknown; message?: unknown };
|
|
46
49
|
return name === "AbortError" || name === "TimeoutError" || (typeof message === "string" && NETWORK_FAILURE.test(message));
|
package/src/shares/pane.ts
CHANGED
|
@@ -53,7 +53,7 @@ export async function openPaneShare(
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
const template = pluginRegistry.paneTemplates.get(share.templateId);
|
|
56
|
-
if (!template?.publicShare) throw new Error("This shared pane is unavailable in this version of
|
|
56
|
+
if (!template?.publicShare) throw new Error("This shared pane is unavailable in this version of Gloom.");
|
|
57
57
|
const options = template.publicShare.restore(share.data);
|
|
58
58
|
if (!options) throw new Error("This shared pane contains invalid settings.");
|
|
59
59
|
await pluginRegistry.createPaneFromTemplateAsync(template.id, options);
|
|
@@ -68,21 +68,66 @@ const TURKISH_CPI: SeriesNotOnFred = {
|
|
|
68
68
|
url: "https://www.tcmb.gov.tr/wps/wcm/connect/EN/TCMB+EN/Main+Menu/Statistics/Inflation+Data/Consumer+Prices",
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
/** IBGE's IPCA (433) and IPCA-15 (7478), as the central bank's SGS republishes them. */
|
|
72
|
+
const brazilianCpi = (code: number): SeriesNotOnFred => ({
|
|
73
|
+
publisher: "IBGE",
|
|
74
|
+
via: "the Banco Central do Brasil's SGS",
|
|
75
|
+
url: `https://www3.bcb.gov.br/sgspub/consultarvalores/telaCvsSelecionarSeries.paint?codigoSerie=${code}`,
|
|
76
|
+
});
|
|
77
|
+
|
|
71
78
|
const NOT_ON_FRED: Readonly<Record<string, SeriesNotOnFred>> = {
|
|
72
79
|
TURCPIYOY: TURKISH_CPI,
|
|
73
80
|
TURCPIMOM: TURKISH_CPI,
|
|
81
|
+
BRAIPCAMOM: brazilianCpi(433),
|
|
82
|
+
BRAIPCA15MOM: brazilianCpi(7478),
|
|
83
|
+
// NAHB's builder sentiment index as first released, from the economic calendar's actuals.
|
|
84
|
+
NAHBHMI: {
|
|
85
|
+
publisher: "NAHB",
|
|
86
|
+
via: "the economic calendar",
|
|
87
|
+
url: "https://www.nahb.org/news-and-economics/housing-economics/indices/housing-market-index",
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/** A series Gloom Cloud computes from two of FRED's, the first less the second, and how. */
|
|
92
|
+
interface ComputedFromFred {
|
|
93
|
+
legs: readonly [string, string];
|
|
94
|
+
note: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const COMPUTED_FROM_FRED: Readonly<Record<string, ComputedFromFred>> = {
|
|
98
|
+
MORTGAGE30US10Y: {
|
|
99
|
+
legs: ["MORTGAGE30US", "DGS10"],
|
|
100
|
+
note: "MORTGAGE30US minus DGS10 on each Freddie Mac PMMS date; when the Treasury market is closed that day, the 10-year yield of the session before.",
|
|
101
|
+
},
|
|
74
102
|
};
|
|
75
103
|
|
|
104
|
+
/** How a series Gloom Cloud computes from FRED's is computed, for the note under its table; null for any other. */
|
|
105
|
+
export function computedFredSeriesNote(seriesId: string): string | null {
|
|
106
|
+
return COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.note ?? null;
|
|
107
|
+
}
|
|
108
|
+
|
|
76
109
|
/** The publisher of a served series FRED does not carry; null for FRED's own. */
|
|
77
110
|
export function seriesNotOnFred(seriesId: string): SeriesNotOnFred | null {
|
|
78
111
|
return NOT_ON_FRED[seriesId.trim().toUpperCase()] ?? null;
|
|
79
112
|
}
|
|
80
113
|
|
|
81
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* The series' page on the FRED site, where its notes and release schedule
|
|
116
|
+
* live; FRED's graph of both legs for a series computed from two; its
|
|
117
|
+
* publisher's page when FRED does not carry it.
|
|
118
|
+
*/
|
|
82
119
|
export function fredSeriesUrl(seriesId: string): string {
|
|
120
|
+
const legs = COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.legs;
|
|
121
|
+
if (legs) return `https://fred.stlouisfed.org/graph/?id=${legs.join(",")}`;
|
|
83
122
|
return seriesNotOnFred(seriesId)?.url ?? `https://fred.stlouisfed.org/series/${seriesId}`;
|
|
84
123
|
}
|
|
85
124
|
|
|
125
|
+
/** What a source line names a series by: `FRED DGS10`, or the FRED series a computed one comes from (`FRED MORTGAGE30US minus DGS10`). */
|
|
126
|
+
export function fredSourceLabel(seriesId: string): string {
|
|
127
|
+
const legs = COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.legs;
|
|
128
|
+
return `FRED ${legs ? legs.join(" minus ") : seriesId}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
86
131
|
function cacheKey(request: FredSeriesRequest): string {
|
|
87
132
|
const range = [
|
|
88
133
|
request.startDate ? `start=${request.startDate}` : "",
|