@363045841yyt/klinechart-core 0.8.11-alpha.0 → 0.8.12
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/dist/alerts/createAlertController.d.ts +30 -0
- package/dist/alerts/createAlertController.d.ts.map +1 -0
- package/dist/alerts/createAlertController.js +261 -0
- package/dist/alerts/createAlertController.js.map +1 -0
- package/dist/alerts/index.d.ts +5 -0
- package/dist/alerts/index.d.ts.map +1 -0
- package/dist/alerts/index.js +4 -0
- package/dist/alerts/index.js.map +1 -0
- package/dist/alerts/predicates.d.ts +28 -0
- package/dist/alerts/predicates.d.ts.map +1 -0
- package/dist/alerts/predicates.js +211 -0
- package/dist/alerts/predicates.js.map +1 -0
- package/dist/alerts/rollingVolume.d.ts +15 -0
- package/dist/alerts/rollingVolume.d.ts.map +1 -0
- package/dist/alerts/rollingVolume.js +42 -0
- package/dist/alerts/rollingVolume.js.map +1 -0
- package/dist/alerts/ruleSchema.d.ts +42 -0
- package/dist/alerts/ruleSchema.d.ts.map +1 -0
- package/dist/alerts/ruleSchema.js +240 -0
- package/dist/alerts/ruleSchema.js.map +1 -0
- package/dist/alerts/types.d.ts +169 -0
- package/dist/alerts/types.d.ts.map +1 -0
- package/dist/alerts/types.js +24 -0
- package/dist/alerts/types.js.map +1 -0
- package/dist/chartTypes/heikinAshi.d.ts +49 -0
- package/dist/chartTypes/heikinAshi.d.ts.map +1 -0
- package/dist/chartTypes/heikinAshi.js +94 -0
- package/dist/chartTypes/heikinAshi.js.map +1 -0
- package/dist/chartTypes/index.d.ts +6 -0
- package/dist/chartTypes/index.d.ts.map +1 -0
- package/dist/chartTypes/index.js +5 -0
- package/dist/chartTypes/index.js.map +1 -0
- package/dist/chartTypes/pointAndFigure.d.ts +83 -0
- package/dist/chartTypes/pointAndFigure.d.ts.map +1 -0
- package/dist/chartTypes/pointAndFigure.js +159 -0
- package/dist/chartTypes/pointAndFigure.js.map +1 -0
- package/dist/chartTypes/rangeBars.d.ts +61 -0
- package/dist/chartTypes/rangeBars.d.ts.map +1 -0
- package/dist/chartTypes/rangeBars.js +181 -0
- package/dist/chartTypes/rangeBars.js.map +1 -0
- package/dist/chartTypes/renko.d.ts +94 -0
- package/dist/chartTypes/renko.d.ts.map +1 -0
- package/dist/chartTypes/renko.js +207 -0
- package/dist/chartTypes/renko.js.map +1 -0
- package/dist/chartTypes/types.d.ts +97 -0
- package/dist/chartTypes/types.d.ts.map +1 -0
- package/dist/chartTypes/types.js +39 -0
- package/dist/chartTypes/types.js.map +1 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts +76 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts.map +1 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.js +155 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.js.map +1 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts +28 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts.map +1 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.js +282 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.js.map +1 -0
- package/dist/components/anchoredVwap/index.d.ts +11 -0
- package/dist/components/anchoredVwap/index.d.ts.map +1 -0
- package/dist/components/anchoredVwap/index.js +10 -0
- package/dist/components/anchoredVwap/index.js.map +1 -0
- package/dist/components/anchoredVwap/types.d.ts +171 -0
- package/dist/components/anchoredVwap/types.d.ts.map +1 -0
- package/dist/components/anchoredVwap/types.js +25 -0
- package/dist/components/anchoredVwap/types.js.map +1 -0
- package/dist/components/crosshairSync/createCrosshairSync.d.ts +94 -0
- package/dist/components/crosshairSync/createCrosshairSync.d.ts.map +1 -0
- package/dist/components/crosshairSync/createCrosshairSync.js +118 -0
- package/dist/components/crosshairSync/createCrosshairSync.js.map +1 -0
- package/dist/components/crosshairSync/index.d.ts +2 -0
- package/dist/components/crosshairSync/index.d.ts.map +1 -0
- package/dist/components/crosshairSync/index.js +2 -0
- package/dist/components/crosshairSync/index.js.map +1 -0
- package/dist/components/footprint/aggressor.d.ts +89 -0
- package/dist/components/footprint/aggressor.d.ts.map +1 -0
- package/dist/components/footprint/aggressor.js +106 -0
- package/dist/components/footprint/aggressor.js.map +1 -0
- package/dist/components/footprint/createFootprintController.d.ts +29 -0
- package/dist/components/footprint/createFootprintController.d.ts.map +1 -0
- package/dist/components/footprint/createFootprintController.js +264 -0
- package/dist/components/footprint/createFootprintController.js.map +1 -0
- package/dist/components/footprint/index.d.ts +7 -0
- package/dist/components/footprint/index.d.ts.map +1 -0
- package/dist/components/footprint/index.js +4 -0
- package/dist/components/footprint/index.js.map +1 -0
- package/dist/components/footprint/perBarStats.d.ts +63 -0
- package/dist/components/footprint/perBarStats.d.ts.map +1 -0
- package/dist/components/footprint/perBarStats.js +123 -0
- package/dist/components/footprint/perBarStats.js.map +1 -0
- package/dist/components/footprint/types.d.ts +197 -0
- package/dist/components/footprint/types.d.ts.map +1 -0
- package/dist/components/footprint/types.js +23 -0
- package/dist/components/footprint/types.js.map +1 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.d.ts +45 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.d.ts.map +1 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.js +92 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.js.map +1 -0
- package/dist/components/mtfOverlay/createMtfController.d.ts +7 -0
- package/dist/components/mtfOverlay/createMtfController.d.ts.map +1 -0
- package/dist/components/mtfOverlay/createMtfController.js +134 -0
- package/dist/components/mtfOverlay/createMtfController.js.map +1 -0
- package/dist/components/mtfOverlay/index.d.ts +19 -0
- package/dist/components/mtfOverlay/index.d.ts.map +1 -0
- package/dist/components/mtfOverlay/index.js +18 -0
- package/dist/components/mtfOverlay/index.js.map +1 -0
- package/dist/components/mtfOverlay/resampleBars.d.ts +37 -0
- package/dist/components/mtfOverlay/resampleBars.d.ts.map +1 -0
- package/dist/components/mtfOverlay/resampleBars.js +93 -0
- package/dist/components/mtfOverlay/resampleBars.js.map +1 -0
- package/dist/components/mtfOverlay/types.d.ts +132 -0
- package/dist/components/mtfOverlay/types.d.ts.map +1 -0
- package/dist/components/mtfOverlay/types.js +22 -0
- package/dist/components/mtfOverlay/types.js.map +1 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.d.ts +21 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.js +234 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.js.map +1 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.d.ts +18 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.js +102 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.js.map +1 -0
- package/dist/components/orderBookHeatmap/deltaArchive.d.ts +25 -0
- package/dist/components/orderBookHeatmap/deltaArchive.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/deltaArchive.js +106 -0
- package/dist/components/orderBookHeatmap/deltaArchive.js.map +1 -0
- package/dist/components/orderBookHeatmap/index.d.ts +13 -0
- package/dist/components/orderBookHeatmap/index.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/index.js +12 -0
- package/dist/components/orderBookHeatmap/index.js.map +1 -0
- package/dist/components/orderBookHeatmap/logColorScale.d.ts +20 -0
- package/dist/components/orderBookHeatmap/logColorScale.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/logColorScale.js +71 -0
- package/dist/components/orderBookHeatmap/logColorScale.js.map +1 -0
- package/dist/components/orderBookHeatmap/snapshotRing.d.ts +16 -0
- package/dist/components/orderBookHeatmap/snapshotRing.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/snapshotRing.js +61 -0
- package/dist/components/orderBookHeatmap/snapshotRing.js.map +1 -0
- package/dist/components/orderBookHeatmap/types.d.ts +128 -0
- package/dist/components/orderBookHeatmap/types.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/types.js +16 -0
- package/dist/components/orderBookHeatmap/types.js.map +1 -0
- package/dist/components/volumeProfile/binning.d.ts +54 -0
- package/dist/components/volumeProfile/binning.d.ts.map +1 -0
- package/dist/components/volumeProfile/binning.js +123 -0
- package/dist/components/volumeProfile/binning.js.map +1 -0
- package/dist/components/volumeProfile/createVolumeProfileController.d.ts +31 -0
- package/dist/components/volumeProfile/createVolumeProfileController.d.ts.map +1 -0
- package/dist/components/volumeProfile/createVolumeProfileController.js +179 -0
- package/dist/components/volumeProfile/createVolumeProfileController.js.map +1 -0
- package/dist/components/volumeProfile/index.d.ts +6 -0
- package/dist/components/volumeProfile/index.d.ts.map +1 -0
- package/dist/components/volumeProfile/index.js +5 -0
- package/dist/components/volumeProfile/index.js.map +1 -0
- package/dist/components/volumeProfile/poc.d.ts +35 -0
- package/dist/components/volumeProfile/poc.d.ts.map +1 -0
- package/dist/components/volumeProfile/poc.js +51 -0
- package/dist/components/volumeProfile/poc.js.map +1 -0
- package/dist/components/volumeProfile/types.d.ts +138 -0
- package/dist/components/volumeProfile/types.d.ts.map +1 -0
- package/dist/components/volumeProfile/types.js +19 -0
- package/dist/components/volumeProfile/types.js.map +1 -0
- package/dist/components/volumeProfile/valueArea.d.ts +58 -0
- package/dist/components/volumeProfile/valueArea.d.ts.map +1 -0
- package/dist/components/volumeProfile/valueArea.js +172 -0
- package/dist/components/volumeProfile/valueArea.js.map +1 -0
- package/dist/controllers/createChartController.d.ts.map +1 -1
- package/dist/controllers/createChartController.js +22 -11
- package/dist/controllers/createChartController.js.map +1 -1
- package/dist/controllers/types.d.ts +3 -1
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.js +2 -1
- package/dist/data-fetchers/baostock.js.map +1 -1
- package/dist/data-fetchers/dataBuffer.effects.d.ts.map +1 -1
- package/dist/data-fetchers/dataBuffer.effects.js +2 -1
- package/dist/data-fetchers/dataBuffer.effects.js.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.js +2 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -1
- package/dist/data-fetchers/gotdx.js +4 -3
- package/dist/data-fetchers/gotdx.js.map +1 -1
- package/dist/data-fetchers/router.d.ts.map +1 -1
- package/dist/data-fetchers/router.js +4 -3
- package/dist/data-fetchers/router.js.map +1 -1
- package/dist/data-fetchers/tradingview.js +3 -2
- package/dist/data-fetchers/tradingview.js.map +1 -1
- package/dist/engine/chart.d.ts +13 -0
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +109 -0
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/data/chartDataManager.d.ts +1 -0
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +27 -4
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/drawing/toolConfig.d.ts.map +1 -1
- package/dist/engine/drawing/toolConfig.js +2 -1
- package/dist/engine/drawing/toolConfig.js.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.js +2 -1
- package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.js +2 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.js.map +1 -1
- package/dist/engine/indicators/indicatorMetadata.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorMetadata.js +2 -1
- package/dist/engine/indicators/indicatorMetadata.js.map +1 -1
- package/dist/engine/indicators/indicatorRegistry.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorRegistry.js +6 -5
- package/dist/engine/indicators/indicatorRegistry.js.map +1 -1
- package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -1
- package/dist/engine/indicators/registerBuiltins.js +2 -1
- package/dist/engine/indicators/registerBuiltins.js.map +1 -1
- package/dist/engine/indicators/scheduler.d.ts +6 -0
- package/dist/engine/indicators/scheduler.d.ts.map +1 -1
- package/dist/engine/indicators/scheduler.js +12 -0
- package/dist/engine/indicators/scheduler.js.map +1 -1
- package/dist/engine/indicators/soa.d.ts.map +1 -1
- package/dist/engine/indicators/soa.js +2 -1
- package/dist/engine/indicators/soa.js.map +1 -1
- package/dist/engine/indicators/stateComposer.d.ts.map +1 -1
- package/dist/engine/indicators/stateComposer.js +2 -1
- package/dist/engine/indicators/stateComposer.js.map +1 -1
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +2 -1
- package/dist/engine/subPaneManager.js.map +1 -1
- package/dist/engine/utils/chartZoomController.d.ts +2 -0
- package/dist/engine/utils/chartZoomController.d.ts.map +1 -1
- package/dist/engine/utils/chartZoomController.js +5 -1
- package/dist/engine/utils/chartZoomController.js.map +1 -1
- package/dist/errors-help.d.ts +72 -0
- package/dist/errors-help.d.ts.map +1 -0
- package/dist/errors-help.js +149 -0
- package/dist/errors-help.js.map +1 -0
- package/dist/errors.d.ts +64 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +61 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/indicators/alma.d.ts +27 -0
- package/dist/indicators/alma.d.ts.map +1 -0
- package/dist/indicators/alma.js +36 -0
- package/dist/indicators/alma.js.map +1 -0
- package/dist/indicators/awesomeOscillator.d.ts +19 -0
- package/dist/indicators/awesomeOscillator.d.ts.map +1 -0
- package/dist/indicators/awesomeOscillator.js +36 -0
- package/dist/indicators/awesomeOscillator.js.map +1 -0
- package/dist/indicators/dpo.d.ts +17 -0
- package/dist/indicators/dpo.d.ts.map +1 -0
- package/dist/indicators/dpo.js +24 -0
- package/dist/indicators/dpo.js.map +1 -0
- package/dist/indicators/fisherTransform.d.ts +26 -0
- package/dist/indicators/fisherTransform.d.ts.map +1 -0
- package/dist/indicators/fisherTransform.js +44 -0
- package/dist/indicators/fisherTransform.js.map +1 -0
- package/dist/indicators/frama.d.ts +25 -0
- package/dist/indicators/frama.d.ts.map +1 -0
- package/dist/indicators/frama.js +61 -0
- package/dist/indicators/frama.js.map +1 -0
- package/dist/indicators/index.d.ts +24 -0
- package/dist/indicators/index.d.ts.map +1 -0
- package/dist/indicators/index.js +26 -0
- package/dist/indicators/index.js.map +1 -0
- package/dist/indicators/lsma.d.ts +21 -0
- package/dist/indicators/lsma.d.ts.map +1 -0
- package/dist/indicators/lsma.js +37 -0
- package/dist/indicators/lsma.js.map +1 -0
- package/dist/indicators/schaffTrendCycle.d.ts +24 -0
- package/dist/indicators/schaffTrendCycle.d.ts.map +1 -0
- package/dist/indicators/schaffTrendCycle.js +70 -0
- package/dist/indicators/schaffTrendCycle.js.map +1 -0
- package/dist/indicators/stochRSI.d.ts +24 -0
- package/dist/indicators/stochRSI.d.ts.map +1 -0
- package/dist/indicators/stochRSI.js +86 -0
- package/dist/indicators/stochRSI.js.map +1 -0
- package/dist/indicators/t3.d.ts +31 -0
- package/dist/indicators/t3.d.ts.map +1 -0
- package/dist/indicators/t3.js +63 -0
- package/dist/indicators/t3.js.map +1 -0
- package/dist/indicators/ultimateOscillator.d.ts +26 -0
- package/dist/indicators/ultimateOscillator.d.ts.map +1 -0
- package/dist/indicators/ultimateOscillator.js +59 -0
- package/dist/indicators/ultimateOscillator.js.map +1 -0
- package/dist/indicators/vidya.d.ts +24 -0
- package/dist/indicators/vidya.d.ts.map +1 -0
- package/dist/indicators/vidya.js +54 -0
- package/dist/indicators/vidya.js.map +1 -0
- package/dist/indicators/zlema.d.ts +16 -0
- package/dist/indicators/zlema.d.ts.map +1 -0
- package/dist/indicators/zlema.js +26 -0
- package/dist/indicators/zlema.js.map +1 -0
- package/dist/input/gesture.d.ts +125 -0
- package/dist/input/gesture.d.ts.map +1 -0
- package/dist/input/gesture.js +249 -0
- package/dist/input/gesture.js.map +1 -0
- package/dist/input/index.d.ts +9 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +9 -0
- package/dist/input/index.js.map +1 -0
- package/dist/input/keyboard.d.ts +140 -0
- package/dist/input/keyboard.d.ts.map +1 -0
- package/dist/input/keyboard.js +260 -0
- package/dist/input/keyboard.js.map +1 -0
- package/dist/mcp/chartBridge.d.ts +2 -2
- package/dist/mcp/chartBridge.d.ts.map +1 -1
- package/dist/mcp/chartBridge.js +27 -21
- package/dist/mcp/chartBridge.js.map +1 -1
- package/dist/plugin/PluginHost.d.ts +0 -3
- package/dist/plugin/PluginHost.d.ts.map +1 -1
- package/dist/plugin/PluginHost.js +7 -3
- package/dist/plugin/PluginHost.js.map +1 -1
- package/dist/plugin/PluginRegistry.d.ts +0 -3
- package/dist/plugin/PluginRegistry.d.ts.map +1 -1
- package/dist/plugin/PluginRegistry.js +5 -1
- package/dist/plugin/PluginRegistry.js.map +1 -1
- package/dist/render/Renderer.d.ts +116 -0
- package/dist/render/Renderer.d.ts.map +1 -0
- package/dist/render/Renderer.js +31 -0
- package/dist/render/Renderer.js.map +1 -0
- package/dist/render/SurfaceBackend.d.ts +83 -0
- package/dist/render/SurfaceBackend.d.ts.map +1 -0
- package/dist/render/SurfaceBackend.js +27 -0
- package/dist/render/SurfaceBackend.js.map +1 -0
- package/dist/render/index.d.ts +12 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +11 -0
- package/dist/render/index.js.map +1 -0
- package/dist/renderer-tier/detectRendererTier.d.ts +57 -0
- package/dist/renderer-tier/detectRendererTier.d.ts.map +1 -0
- package/dist/renderer-tier/detectRendererTier.js +143 -0
- package/dist/renderer-tier/detectRendererTier.js.map +1 -0
- package/dist/renderer-tier/index.d.ts +12 -0
- package/dist/renderer-tier/index.d.ts.map +1 -0
- package/dist/renderer-tier/index.js +12 -0
- package/dist/renderer-tier/index.js.map +1 -0
- package/dist/renderer-tier/selectBackend.d.ts +106 -0
- package/dist/renderer-tier/selectBackend.d.ts.map +1 -0
- package/dist/renderer-tier/selectBackend.js +113 -0
- package/dist/renderer-tier/selectBackend.js.map +1 -0
- package/dist/renderer-tier/types.d.ts +50 -0
- package/dist/renderer-tier/types.d.ts.map +1 -0
- package/dist/renderer-tier/types.js +24 -0
- package/dist/renderer-tier/types.js.map +1 -0
- package/dist/replay/createReplayController.d.ts +3 -0
- package/dist/replay/createReplayController.d.ts.map +1 -0
- package/dist/replay/createReplayController.js +251 -0
- package/dist/replay/createReplayController.js.map +1 -0
- package/dist/replay/index.d.ts +5 -0
- package/dist/replay/index.d.ts.map +1 -0
- package/dist/replay/index.js +3 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/timeline.d.ts +50 -0
- package/dist/replay/timeline.d.ts.map +1 -0
- package/dist/replay/timeline.js +104 -0
- package/dist/replay/timeline.js.map +1 -0
- package/dist/replay/types.d.ts +94 -0
- package/dist/replay/types.d.ts.map +1 -0
- package/dist/replay/types.js +21 -0
- package/dist/replay/types.js.map +1 -0
- package/dist/scale/anchoredZoom.d.ts +64 -0
- package/dist/scale/anchoredZoom.d.ts.map +1 -0
- package/dist/scale/anchoredZoom.js +67 -0
- package/dist/scale/anchoredZoom.js.map +1 -0
- package/dist/scale/createPriceScale.d.ts +49 -0
- package/dist/scale/createPriceScale.d.ts.map +1 -0
- package/dist/scale/createPriceScale.js +175 -0
- package/dist/scale/createPriceScale.js.map +1 -0
- package/dist/scale/createTimeScale.d.ts +27 -0
- package/dist/scale/createTimeScale.d.ts.map +1 -0
- package/dist/scale/createTimeScale.js +139 -0
- package/dist/scale/createTimeScale.js.map +1 -0
- package/dist/scale/index.d.ts +6 -0
- package/dist/scale/index.d.ts.map +1 -0
- package/dist/scale/index.js +5 -0
- package/dist/scale/index.js.map +1 -0
- package/dist/scale/originShift.d.ts +69 -0
- package/dist/scale/originShift.d.ts.map +1 -0
- package/dist/scale/originShift.js +41 -0
- package/dist/scale/originShift.js.map +1 -0
- package/dist/scale/types.d.ts +90 -0
- package/dist/scale/types.d.ts.map +1 -0
- package/dist/scale/types.js +17 -0
- package/dist/scale/types.js.map +1 -0
- package/dist/scene/createScene.d.ts +22 -0
- package/dist/scene/createScene.d.ts.map +1 -0
- package/dist/scene/createScene.js +114 -0
- package/dist/scene/createScene.js.map +1 -0
- package/dist/scene/index.d.ts +13 -0
- package/dist/scene/index.d.ts.map +1 -0
- package/dist/scene/index.js +11 -0
- package/dist/scene/index.js.map +1 -0
- package/dist/scene/layerRegistry.d.ts +83 -0
- package/dist/scene/layerRegistry.d.ts.map +1 -0
- package/dist/scene/layerRegistry.js +43 -0
- package/dist/scene/layerRegistry.js.map +1 -0
- package/dist/scene/types.d.ts +128 -0
- package/dist/scene/types.d.ts.map +1 -0
- package/dist/scene/types.js +21 -0
- package/dist/scene/types.js.map +1 -0
- package/dist/scheduler/createFrameBudget.d.ts +91 -0
- package/dist/scheduler/createFrameBudget.d.ts.map +1 -0
- package/dist/scheduler/createFrameBudget.js +232 -0
- package/dist/scheduler/createFrameBudget.js.map +1 -0
- package/dist/scheduler/index.d.ts +2 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +2 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/tokens/themeToCssVars.d.ts.map +1 -1
- package/dist/tokens/themeToCssVars.js +2 -28
- package/dist/tokens/themeToCssVars.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/__bench__/indicators.bench.ts +215 -0
- package/src/__bench__/orderBookHeatmap.bench.ts +68 -0
- package/src/__bench__/scale.bench.ts +80 -0
- package/src/__bench__/signal.bench.ts +41 -0
- package/src/__bench__/volumeProfile.bench.ts +66 -0
- package/src/__tests__/errors-help.test.ts +184 -0
- package/src/__tests__/errors.test.ts +187 -0
- package/src/alerts/__tests__/controller.test.ts +231 -0
- package/src/alerts/__tests__/predicates.test.ts +374 -0
- package/src/alerts/__tests__/ruleSchema.test.ts +180 -0
- package/src/alerts/createAlertController.ts +312 -0
- package/src/alerts/index.ts +18 -0
- package/src/alerts/predicates.ts +231 -0
- package/src/alerts/rollingVolume.ts +51 -0
- package/src/alerts/ruleSchema.ts +278 -0
- package/src/alerts/types.ts +177 -0
- package/src/chartTypes/__tests__/heikinAshi.test.ts +122 -0
- package/src/chartTypes/__tests__/pointAndFigure.test.ts +167 -0
- package/src/chartTypes/__tests__/rangeBars.test.ts +146 -0
- package/src/chartTypes/__tests__/renko.test.ts +160 -0
- package/src/chartTypes/heikinAshi.ts +116 -0
- package/src/chartTypes/index.ts +5 -0
- package/src/chartTypes/pointAndFigure.ts +278 -0
- package/src/chartTypes/rangeBars.ts +303 -0
- package/src/chartTypes/renko.ts +311 -0
- package/src/chartTypes/types.ts +99 -0
- package/src/components/anchoredVwap/__tests__/computeAnchoredVwap.test.ts +331 -0
- package/src/components/anchoredVwap/__tests__/controller.test.ts +430 -0
- package/src/components/anchoredVwap/computeAnchoredVwap.ts +174 -0
- package/src/components/anchoredVwap/createAnchoredVwapController.ts +358 -0
- package/src/components/anchoredVwap/index.ts +17 -0
- package/src/components/anchoredVwap/types.ts +187 -0
- package/src/components/crosshairSync/__tests__/crosshairSync.test.ts +261 -0
- package/src/components/crosshairSync/createCrosshairSync.ts +187 -0
- package/src/components/crosshairSync/index.ts +5 -0
- package/src/components/footprint/__tests__/aggressor.test.ts +127 -0
- package/src/components/footprint/__tests__/controller.test.ts +130 -0
- package/src/components/footprint/__tests__/perBarStats.test.ts +114 -0
- package/src/components/footprint/aggressor.ts +165 -0
- package/src/components/footprint/createFootprintController.ts +338 -0
- package/src/components/footprint/index.ts +21 -0
- package/src/components/footprint/perBarStats.ts +137 -0
- package/src/components/footprint/types.ts +232 -0
- package/src/components/mtfOverlay/__tests__/alignToBaseIndex.test.ts +103 -0
- package/src/components/mtfOverlay/__tests__/controller.test.ts +172 -0
- package/src/components/mtfOverlay/__tests__/resampleBars.test.ts +106 -0
- package/src/components/mtfOverlay/alignToBaseIndex.ts +108 -0
- package/src/components/mtfOverlay/createMtfController.ts +180 -0
- package/src/components/mtfOverlay/index.ts +26 -0
- package/src/components/mtfOverlay/resampleBars.ts +134 -0
- package/src/components/mtfOverlay/types.ts +148 -0
- package/src/components/orderBookHeatmap/__tests__/controller.test.ts +237 -0
- package/src/components/orderBookHeatmap/__tests__/deltaArchive.test.ts +88 -0
- package/src/components/orderBookHeatmap/__tests__/logColorScale.test.ts +69 -0
- package/src/components/orderBookHeatmap/__tests__/orderBookState.test.ts +113 -0
- package/src/components/orderBookHeatmap/__tests__/snapshotRing.test.ts +53 -0
- package/src/components/orderBookHeatmap/computeShader.wgsl.md +130 -0
- package/src/components/orderBookHeatmap/createHeatmapController.ts +273 -0
- package/src/components/orderBookHeatmap/createOrderBookState.ts +116 -0
- package/src/components/orderBookHeatmap/deltaArchive.ts +113 -0
- package/src/components/orderBookHeatmap/index.ts +25 -0
- package/src/components/orderBookHeatmap/logColorScale.ts +77 -0
- package/src/components/orderBookHeatmap/snapshotRing.ts +65 -0
- package/src/components/orderBookHeatmap/types.ts +168 -0
- package/src/components/volumeProfile/__tests__/binning.test.ts +133 -0
- package/src/components/volumeProfile/__tests__/poc.test.ts +44 -0
- package/src/components/volumeProfile/__tests__/valueArea.test.ts +177 -0
- package/src/components/volumeProfile/binning.ts +133 -0
- package/src/components/volumeProfile/createVolumeProfileController.ts +213 -0
- package/src/components/volumeProfile/index.ts +12 -0
- package/src/components/volumeProfile/poc.ts +53 -0
- package/src/components/volumeProfile/types.ts +148 -0
- package/src/components/volumeProfile/valueArea.ts +187 -0
- package/src/controllers/createChartController.ts +23 -10
- package/src/controllers/types.ts +5 -1
- package/src/data-fetchers/baostock.ts +2 -1
- package/src/data-fetchers/dataBuffer.effects.ts +3 -1
- package/src/data-fetchers/fetcherDefinitionRegistry.ts +2 -1
- package/src/data-fetchers/gotdx.ts +4 -3
- package/src/data-fetchers/router.ts +6 -3
- package/src/data-fetchers/tradingview.ts +3 -2
- package/src/engine/chart.ts +126 -3
- package/src/engine/data/chartDataManager.ts +26 -4
- package/src/engine/drawing/toolConfig.ts +2 -1
- package/src/engine/indicators/chartIndicatorManager.ts +2 -1
- package/src/engine/indicators/indicatorDefinitionRegistry.ts +2 -1
- package/src/engine/indicators/indicatorMetadata.ts +2 -1
- package/src/engine/indicators/indicatorRegistry.ts +6 -5
- package/src/engine/indicators/registerBuiltins.ts +2 -1
- package/src/engine/indicators/scheduler.ts +15 -0
- package/src/engine/indicators/soa.ts +2 -1
- package/src/engine/indicators/stateComposer.ts +2 -1
- package/src/engine/subPaneManager.ts +2 -1
- package/src/engine/utils/chartZoomController.ts +7 -1
- package/src/errors-help.ts +218 -0
- package/src/errors.ts +128 -0
- package/src/index.ts +37 -0
- package/src/indicators/__tests__/maFamily.test.ts +159 -0
- package/src/indicators/__tests__/oscillators.test.ts +150 -0
- package/src/indicators/alma.ts +61 -0
- package/src/indicators/awesomeOscillator.ts +54 -0
- package/src/indicators/dpo.ts +37 -0
- package/src/indicators/fisherTransform.ts +63 -0
- package/src/indicators/frama.ts +87 -0
- package/src/indicators/index.ts +39 -0
- package/src/indicators/lsma.ts +58 -0
- package/src/indicators/schaffTrendCycle.ts +92 -0
- package/src/indicators/stochRSI.ts +108 -0
- package/src/indicators/t3.ts +96 -0
- package/src/indicators/ultimateOscillator.ts +83 -0
- package/src/indicators/vidya.ts +80 -0
- package/src/indicators/zlema.ts +41 -0
- package/src/input/__tests__/gesture.test.ts +271 -0
- package/src/input/__tests__/keyboard.test.ts +317 -0
- package/src/input/gesture.ts +357 -0
- package/src/input/index.ts +26 -0
- package/src/input/keyboard.ts +373 -0
- package/src/mcp/chartBridge.ts +98 -72
- package/src/plugin/PluginHost.ts +4 -3
- package/src/plugin/PluginRegistry.ts +2 -1
- package/src/render/Renderer.ts +127 -0
- package/src/render/SurfaceBackend.ts +94 -0
- package/src/render/__tests__/contract.test.ts +176 -0
- package/src/render/index.ts +27 -0
- package/src/renderer-tier/__tests__/detectRendererTier.test.ts +180 -0
- package/src/renderer-tier/__tests__/selectBackend.test.ts +253 -0
- package/src/renderer-tier/detectRendererTier.ts +168 -0
- package/src/renderer-tier/index.ts +30 -0
- package/src/renderer-tier/selectBackend.ts +201 -0
- package/src/renderer-tier/types.ts +59 -0
- package/src/replay/__tests__/controller.test.ts +309 -0
- package/src/replay/__tests__/timeline.test.ts +99 -0
- package/src/replay/createReplayController.ts +302 -0
- package/src/replay/index.ts +15 -0
- package/src/replay/timeline.ts +106 -0
- package/src/replay/types.ts +107 -0
- package/src/scale/__tests__/anchoredZoom.test.ts +125 -0
- package/src/scale/__tests__/originShift.test.ts +97 -0
- package/src/scale/__tests__/priceScale.test.ts +219 -0
- package/src/scale/__tests__/timeScale.test.ts +119 -0
- package/src/scale/anchoredZoom.ts +104 -0
- package/src/scale/createPriceScale.ts +226 -0
- package/src/scale/createTimeScale.ts +150 -0
- package/src/scale/index.ts +9 -0
- package/src/scale/originShift.ts +111 -0
- package/src/scale/types.ts +100 -0
- package/src/scene/__tests__/layerRegistry.test.ts +207 -0
- package/src/scene/__tests__/scene.test.ts +411 -0
- package/src/scene/createScene.ts +117 -0
- package/src/scene/index.ts +29 -0
- package/src/scene/layerRegistry.ts +117 -0
- package/src/scene/types.ts +143 -0
- package/src/scheduler/__tests__/createFrameBudget.test.ts +315 -0
- package/src/scheduler/createFrameBudget.ts +316 -0
- package/src/scheduler/index.ts +7 -0
- package/src/tokens/themeToCssVars.ts +3 -1
- package/src/version.ts +1 -1
- package/dist/data-fetchers/gotdx/gotdx.d.ts +0 -7
- package/dist/data-fetchers/gotdx/gotdx.d.ts.map +0 -1
- package/dist/data-fetchers/gotdx/gotdx.js +0 -7
- package/dist/data-fetchers/gotdx/gotdx.js.map +0 -1
- package/src/data-fetchers/gotdx/gotdx.ts +0 -6
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `selectBackend` / `selectBackendOrThrow`.
|
|
3
|
+
*
|
|
4
|
+
* Coverage:
|
|
5
|
+
* 1. Direct match — detected tier has a registered factory.
|
|
6
|
+
* 2. Downgrade — detected tier is webgpu but only webgl2 registered.
|
|
7
|
+
* 3. Floor — `minimum: 'webgl2'` rejects canvas2d even if registered.
|
|
8
|
+
* 4. Detection injection — `opts.detection` skips the sniffer.
|
|
9
|
+
* 5. Probe injection — `opts.detect.probes` flows through.
|
|
10
|
+
* 6. Empty registry → `tier: 'none'` with informative reason.
|
|
11
|
+
* 7. fallbackChain enumerates tried tiers high → low.
|
|
12
|
+
* 8. `factory` is the same function reference passed in.
|
|
13
|
+
* 9. `reason` strings differ between direct match and downgrade.
|
|
14
|
+
* 10. Invalid minimum → `KLineChartError('INVALID_PARAM')`.
|
|
15
|
+
* 11. `selectBackendOrThrow` throws `INVALID_STATE` on no match.
|
|
16
|
+
* 12. `detection.tier` is preserved even when downgrade occurs.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { describe, it, expect } from 'vitest'
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
selectBackend,
|
|
23
|
+
selectBackendOrThrow,
|
|
24
|
+
type BackendRegistry,
|
|
25
|
+
} from '..'
|
|
26
|
+
import type { RendererTierResult } from '../types'
|
|
27
|
+
import { isKLineChartError } from '../../errors'
|
|
28
|
+
|
|
29
|
+
const ALWAYS = (): boolean => true
|
|
30
|
+
const NEVER = (): boolean => false
|
|
31
|
+
|
|
32
|
+
function fakeFactory<T>(tag: T): () => T {
|
|
33
|
+
return () => tag
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Helper: build a detection result without running the sniffer.
|
|
37
|
+
function fakeDetection(tier: RendererTierResult['tier']): RendererTierResult {
|
|
38
|
+
return {
|
|
39
|
+
tier,
|
|
40
|
+
reason: `synthetic detection: ${tier}`,
|
|
41
|
+
tried: [tier],
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Direct match
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
describe('selectBackend — direct match', () => {
|
|
50
|
+
it('detected webgpu + webgpu factory registered → webgpu factory', () => {
|
|
51
|
+
const sel = selectBackend({
|
|
52
|
+
detection: fakeDetection('webgpu'),
|
|
53
|
+
registry: {
|
|
54
|
+
webgpu: fakeFactory('GPU'),
|
|
55
|
+
webgl2: fakeFactory('GL2'),
|
|
56
|
+
canvas2d: fakeFactory('C2D'),
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
expect(sel.tier).toBe('webgpu')
|
|
60
|
+
expect(sel.factory!()).toBe('GPU')
|
|
61
|
+
expect(sel.fallbackChain).toEqual(['webgpu'])
|
|
62
|
+
expect(sel.reason).toContain('direct match')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('detected canvas2d + canvas2d factory registered → canvas2d factory', () => {
|
|
66
|
+
const sel = selectBackend({
|
|
67
|
+
detection: fakeDetection('canvas2d'),
|
|
68
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
69
|
+
})
|
|
70
|
+
expect(sel.tier).toBe('canvas2d')
|
|
71
|
+
expect(sel.factory!()).toBe('C2D')
|
|
72
|
+
expect(sel.fallbackChain).toEqual(['canvas2d'])
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Downgrade
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
describe('selectBackend — downgrade', () => {
|
|
81
|
+
it('detected webgpu, only webgl2 registered → webgl2 factory', () => {
|
|
82
|
+
const sel = selectBackend({
|
|
83
|
+
detection: fakeDetection('webgpu'),
|
|
84
|
+
registry: { webgl2: fakeFactory('GL2') },
|
|
85
|
+
})
|
|
86
|
+
expect(sel.tier).toBe('webgl2')
|
|
87
|
+
expect(sel.factory!()).toBe('GL2')
|
|
88
|
+
expect(sel.fallbackChain).toEqual(['webgpu', 'webgl2'])
|
|
89
|
+
expect(sel.reason).toContain('downgrade')
|
|
90
|
+
expect(sel.reason).toContain('webgpu')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('detected webgl2, only canvas2d registered → canvas2d factory', () => {
|
|
94
|
+
const sel = selectBackend({
|
|
95
|
+
detection: fakeDetection('webgl2'),
|
|
96
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
97
|
+
})
|
|
98
|
+
expect(sel.tier).toBe('canvas2d')
|
|
99
|
+
expect(sel.fallbackChain).toEqual(['webgl2', 'canvas2d'])
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('null factory entries are skipped (treated as not registered)', () => {
|
|
103
|
+
const sel = selectBackend({
|
|
104
|
+
detection: fakeDetection('webgpu'),
|
|
105
|
+
registry: { webgpu: null, webgl2: fakeFactory('GL2') },
|
|
106
|
+
})
|
|
107
|
+
expect(sel.tier).toBe('webgl2')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('detection.tier is preserved in the result even after downgrade', () => {
|
|
111
|
+
const sel = selectBackend({
|
|
112
|
+
detection: fakeDetection('webgpu'),
|
|
113
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
114
|
+
})
|
|
115
|
+
expect(sel.tier).toBe('canvas2d')
|
|
116
|
+
expect(sel.detection.tier).toBe('webgpu')
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Floor
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
describe('selectBackend — minimum floor', () => {
|
|
125
|
+
it('minimum=webgl2 rejects canvas2d even if registered', () => {
|
|
126
|
+
const sel = selectBackend({
|
|
127
|
+
detection: fakeDetection('canvas2d'),
|
|
128
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
129
|
+
minimum: 'webgl2',
|
|
130
|
+
})
|
|
131
|
+
expect(sel.tier).toBe('none')
|
|
132
|
+
expect(sel.factory).toBeNull()
|
|
133
|
+
expect(sel.reason).toContain('minimum=webgl2')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('minimum=webgl2 accepts a higher tier', () => {
|
|
137
|
+
const sel = selectBackend({
|
|
138
|
+
detection: fakeDetection('webgl2'),
|
|
139
|
+
registry: { webgl2: fakeFactory('GL2') },
|
|
140
|
+
minimum: 'webgl2',
|
|
141
|
+
})
|
|
142
|
+
expect(sel.tier).toBe('webgl2')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('minimum=canvas2d does not affect behaviour (effective default)', () => {
|
|
146
|
+
const sel = selectBackend({
|
|
147
|
+
detection: fakeDetection('canvas2d'),
|
|
148
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
149
|
+
minimum: 'canvas2d',
|
|
150
|
+
})
|
|
151
|
+
expect(sel.tier).toBe('canvas2d')
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Empty / no-match registries
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
describe('selectBackend — no match', () => {
|
|
160
|
+
it('empty registry → tier:none + null factory', () => {
|
|
161
|
+
const sel = selectBackend({
|
|
162
|
+
detection: fakeDetection('webgpu'),
|
|
163
|
+
registry: {} as BackendRegistry,
|
|
164
|
+
})
|
|
165
|
+
expect(sel.tier).toBe('none')
|
|
166
|
+
expect(sel.factory).toBeNull()
|
|
167
|
+
expect(sel.reason).toContain('no registered backend')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('detected none + no factories → tier:none with host reason', () => {
|
|
171
|
+
const sel = selectBackend({
|
|
172
|
+
detection: fakeDetection('none'),
|
|
173
|
+
registry: {} as BackendRegistry,
|
|
174
|
+
})
|
|
175
|
+
expect(sel.tier).toBe('none')
|
|
176
|
+
expect(sel.reason).toContain('no renderable tier')
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
// Detection / probe pass-through
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
|
|
184
|
+
describe('selectBackend — probe pass-through', () => {
|
|
185
|
+
it('detect.probes flows to detectRendererTier', () => {
|
|
186
|
+
const sel = selectBackend({
|
|
187
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
188
|
+
detect: {
|
|
189
|
+
probes: { webgpu: NEVER, webgl2: NEVER, canvas2d: ALWAYS },
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
expect(sel.detection.tier).toBe('canvas2d')
|
|
193
|
+
expect(sel.tier).toBe('canvas2d')
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('explicit detection overrides probe detection', () => {
|
|
197
|
+
const sel = selectBackend({
|
|
198
|
+
registry: { canvas2d: fakeFactory('C2D') },
|
|
199
|
+
detection: fakeDetection('webgpu'),
|
|
200
|
+
// detect.probes here would say 'canvas2d' if consulted —
|
|
201
|
+
// but they shouldn't be, since explicit detection wins.
|
|
202
|
+
detect: { probes: { webgpu: NEVER, webgl2: NEVER, canvas2d: ALWAYS } },
|
|
203
|
+
})
|
|
204
|
+
expect(sel.detection.tier).toBe('webgpu')
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// Validation
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
describe('selectBackend — input validation', () => {
|
|
213
|
+
it('throws KLineChartError(INVALID_PARAM) on unknown minimum', () => {
|
|
214
|
+
try {
|
|
215
|
+
selectBackend({
|
|
216
|
+
detection: fakeDetection('webgpu'),
|
|
217
|
+
registry: { webgpu: fakeFactory('X') },
|
|
218
|
+
minimum: 'doesNotExist' as never,
|
|
219
|
+
})
|
|
220
|
+
expect.fail('expected throw')
|
|
221
|
+
} catch (e) {
|
|
222
|
+
expect(isKLineChartError(e, 'INVALID_PARAM')).toBe(true)
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Strict variant
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
describe('selectBackendOrThrow', () => {
|
|
232
|
+
it('returns the selection unchanged when a factory was found', () => {
|
|
233
|
+
const sel = selectBackendOrThrow({
|
|
234
|
+
detection: fakeDetection('webgpu'),
|
|
235
|
+
registry: { webgpu: fakeFactory('GPU') },
|
|
236
|
+
})
|
|
237
|
+
expect(sel.tier).toBe('webgpu')
|
|
238
|
+
// Type-narrowed: factory is non-null at compile time.
|
|
239
|
+
expect(sel.factory()).toBe('GPU')
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('throws KLineChartError(INVALID_STATE) on no match', () => {
|
|
243
|
+
try {
|
|
244
|
+
selectBackendOrThrow({
|
|
245
|
+
detection: fakeDetection('none'),
|
|
246
|
+
registry: {} as BackendRegistry,
|
|
247
|
+
})
|
|
248
|
+
expect.fail('expected throw')
|
|
249
|
+
} catch (e) {
|
|
250
|
+
expect(isKLineChartError(e, 'INVALID_STATE')).toBe(true)
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
})
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous renderer tier detection.
|
|
3
|
+
*
|
|
4
|
+
* Probes (in descending capability order):
|
|
5
|
+
*
|
|
6
|
+
* 1. **webgpu** `'gpu' in navigator`. We deliberately do NOT call
|
|
7
|
+
* `navigator.gpu.requestAdapter()` here — that's async
|
|
8
|
+
* and the answer can change between probe and use
|
|
9
|
+
* (e.g. user toggles the WebGPU flag). The renderer
|
|
10
|
+
* should retry adapter acquisition at startup; this
|
|
11
|
+
* sync check is a pre-mount fast path.
|
|
12
|
+
*
|
|
13
|
+
* 2. **webgl2** `canvas.getContext('webgl2') !== null`. Probes a
|
|
14
|
+
* throwaway `<canvas>`; if the browser hard-disabled
|
|
15
|
+
* WebGL (some hardened policies do), this returns
|
|
16
|
+
* null and we fall through.
|
|
17
|
+
*
|
|
18
|
+
* 3. **canvas2d** `canvas.getContext('2d') !== null`. Universal
|
|
19
|
+
* fallback for browsers from the 2010s onwards.
|
|
20
|
+
*
|
|
21
|
+
* 4. **none** None of the above worked — likely SSR (no document)
|
|
22
|
+
* or a sandboxed environment. The caller can decide
|
|
23
|
+
* whether that's an error or a "render nothing" state.
|
|
24
|
+
*
|
|
25
|
+
* All exceptions from a probe are caught and folded into the `reason`
|
|
26
|
+
* field — a probe that throws is treated identically to one that
|
|
27
|
+
* returns false (no tier-skip cascade).
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { KLineChartError } from '../errors'
|
|
31
|
+
import {
|
|
32
|
+
RENDERER_TIER_RANK,
|
|
33
|
+
type DetectRendererTierOptions,
|
|
34
|
+
type RendererTier,
|
|
35
|
+
type RendererTierResult,
|
|
36
|
+
} from './types'
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Production probes — only run when no override is supplied
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
function probeWebGpu(): boolean {
|
|
43
|
+
const nav = (globalThis as { navigator?: unknown }).navigator
|
|
44
|
+
if (typeof nav !== 'object' || nav === null) return false
|
|
45
|
+
return 'gpu' in (nav as object)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function probeWebGl2(): boolean {
|
|
49
|
+
const doc = (globalThis as { document?: { createElement?: (s: string) => unknown } }).document
|
|
50
|
+
if (typeof doc?.createElement !== 'function') return false
|
|
51
|
+
const canvas = doc.createElement('canvas') as {
|
|
52
|
+
getContext?: (id: string) => unknown
|
|
53
|
+
}
|
|
54
|
+
if (typeof canvas.getContext !== 'function') return false
|
|
55
|
+
return canvas.getContext('webgl2') !== null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function probeCanvas2d(): boolean {
|
|
59
|
+
const doc = (globalThis as { document?: { createElement?: (s: string) => unknown } }).document
|
|
60
|
+
if (typeof doc?.createElement !== 'function') return false
|
|
61
|
+
const canvas = doc.createElement('canvas') as {
|
|
62
|
+
getContext?: (id: string) => unknown
|
|
63
|
+
}
|
|
64
|
+
if (typeof canvas.getContext !== 'function') return false
|
|
65
|
+
return canvas.getContext('2d') !== null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// runProbe — adapter that turns probe → "ok, false, or error string"
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
function runProbe(probe: () => boolean): { ok: boolean; error: string | null } {
|
|
73
|
+
try {
|
|
74
|
+
return { ok: probe() === true, error: null }
|
|
75
|
+
} catch (e) {
|
|
76
|
+
const msg = e instanceof Error ? e.message : String(e)
|
|
77
|
+
return { ok: false, error: msg }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Public API
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
const TIER_ORDER: ReadonlyArray<RendererTier> = ['webgpu', 'webgl2', 'canvas2d']
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Detect the best renderer tier available in the current environment.
|
|
89
|
+
*
|
|
90
|
+
* Returns synchronously. Use this at the call site of `createChart` to
|
|
91
|
+
* pick the renderer backend; persist the result if you re-mount, since
|
|
92
|
+
* recomputing is cheap but not free (probing creates a throwaway canvas).
|
|
93
|
+
*/
|
|
94
|
+
export function detectRendererTier(
|
|
95
|
+
opts?: DetectRendererTierOptions,
|
|
96
|
+
): RendererTierResult {
|
|
97
|
+
const probes = opts?.probes ?? {}
|
|
98
|
+
const reasonParts: string[] = []
|
|
99
|
+
const tried: RendererTier[] = []
|
|
100
|
+
|
|
101
|
+
for (const tier of TIER_ORDER) {
|
|
102
|
+
tried.push(tier)
|
|
103
|
+
const probe =
|
|
104
|
+
tier === 'webgpu'
|
|
105
|
+
? (probes.webgpu ?? probeWebGpu)
|
|
106
|
+
: tier === 'webgl2'
|
|
107
|
+
? (probes.webgl2 ?? probeWebGl2)
|
|
108
|
+
: (probes.canvas2d ?? probeCanvas2d)
|
|
109
|
+
const r = runProbe(probe)
|
|
110
|
+
if (r.ok) {
|
|
111
|
+
return {
|
|
112
|
+
tier,
|
|
113
|
+
reason: `selected ${tier} (${reasonParts.length === 0 ? 'first probe succeeded' : reasonParts.join('; ')})`,
|
|
114
|
+
tried: [...tried],
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
reasonParts.push(
|
|
118
|
+
r.error === null ? `${tier}: not available` : `${tier}: threw "${r.error}"`,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
tier: 'none',
|
|
124
|
+
reason: `no tier available — ${reasonParts.join('; ')}`,
|
|
125
|
+
tried: [...tried],
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Strict variant: throws `KLineChartError('INVALID_STATE')` when no
|
|
131
|
+
* renderable tier is found. Use when you want a hard failure rather
|
|
132
|
+
* than a silent `'none'`.
|
|
133
|
+
*/
|
|
134
|
+
export function detectRendererTierOrThrow(
|
|
135
|
+
opts?: DetectRendererTierOptions,
|
|
136
|
+
): RendererTierResult {
|
|
137
|
+
const r = detectRendererTier(opts)
|
|
138
|
+
if (r.tier === 'none') {
|
|
139
|
+
throw new KLineChartError(
|
|
140
|
+
'INVALID_STATE',
|
|
141
|
+
`detectRendererTierOrThrow: ${r.reason}`,
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
return r
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Three-way compare on the tier rank. `a > b → 1`, `a < b → -1`, equal → 0.
|
|
149
|
+
*
|
|
150
|
+
* compareRendererTier('webgpu', 'webgl2') === 1
|
|
151
|
+
* compareRendererTier('canvas2d', 'webgl2') === -1
|
|
152
|
+
* compareRendererTier('webgl2', 'webgl2') === 0
|
|
153
|
+
*/
|
|
154
|
+
export function compareRendererTier(a: RendererTier, b: RendererTier): -1 | 0 | 1 {
|
|
155
|
+
const ra = RENDERER_TIER_RANK[a]
|
|
156
|
+
const rb = RENDERER_TIER_RANK[b]
|
|
157
|
+
if (ra > rb) return 1
|
|
158
|
+
if (ra < rb) return -1
|
|
159
|
+
return 0
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* `tier >= minimum` guard for renderer features that require a floor
|
|
164
|
+
* (e.g. GPU compute volume profile needs `>= 'webgl2'`).
|
|
165
|
+
*/
|
|
166
|
+
export function isTierAtLeast(tier: RendererTier, minimum: RendererTier): boolean {
|
|
167
|
+
return compareRendererTier(tier, minimum) >= 0
|
|
168
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @klinechart-quant/core/renderer-tier — pre-mount renderer tier detection.
|
|
3
|
+
*
|
|
4
|
+
* Used by the `Renderer` factory to pick the highest backend the host
|
|
5
|
+
* environment supports (WebGPU → WebGL2 → Canvas2D → none).
|
|
6
|
+
*
|
|
7
|
+
* See `./detectRendererTier.ts` for design notes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
detectRendererTier,
|
|
12
|
+
detectRendererTierOrThrow,
|
|
13
|
+
compareRendererTier,
|
|
14
|
+
isTierAtLeast,
|
|
15
|
+
} from './detectRendererTier'
|
|
16
|
+
export {
|
|
17
|
+
selectBackend,
|
|
18
|
+
selectBackendOrThrow,
|
|
19
|
+
type BackendFactory,
|
|
20
|
+
type BackendRegistry,
|
|
21
|
+
type BackendSelection,
|
|
22
|
+
type SelectBackendOptions,
|
|
23
|
+
} from './selectBackend'
|
|
24
|
+
export {
|
|
25
|
+
RENDERER_TIER_RANK,
|
|
26
|
+
type RendererTier,
|
|
27
|
+
type RendererTierResult,
|
|
28
|
+
type RendererTierProbes,
|
|
29
|
+
type DetectRendererTierOptions,
|
|
30
|
+
} from './types'
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer backend selector — bridges the tier-detection layer
|
|
3
|
+
* ({@link detectRendererTier}) to the actual backend factory the
|
|
4
|
+
* `Renderer` interface will instantiate.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists separately from {@link detectRendererTier}:
|
|
7
|
+
*
|
|
8
|
+
* - Detection answers "what's *possible*?".
|
|
9
|
+
* - Selection answers "what's *registered* and matches what's possible?".
|
|
10
|
+
*
|
|
11
|
+
* In practice the answers diverge. A consumer can:
|
|
12
|
+
*
|
|
13
|
+
* (a) Choose to omit a backend they don't want to ship (e.g. drop the
|
|
14
|
+
* WebGPU backend to save bundle size; the selector then falls
|
|
15
|
+
* through to WebGL2 even when the host supports WebGPU).
|
|
16
|
+
* (b) Override a backend for a specific tier (e.g. inject a Canvas2D
|
|
17
|
+
* backend stub during tests, so the chart still renders headless).
|
|
18
|
+
*
|
|
19
|
+
* Both shapes need a *structural* fallback chain, not just "give me the
|
|
20
|
+
* factory for the detected tier". This module formalises that chain so
|
|
21
|
+
* the wiring is consistent across React, Vue, Angular, and any future
|
|
22
|
+
* adapter.
|
|
23
|
+
*
|
|
24
|
+
* Pure data: no DOM, no async, no side effects. The returned factory is
|
|
25
|
+
* just the function the caller registered.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { KLineChartError } from '../errors'
|
|
29
|
+
import {
|
|
30
|
+
RENDERER_TIER_RANK,
|
|
31
|
+
type DetectRendererTierOptions,
|
|
32
|
+
type RendererTier,
|
|
33
|
+
type RendererTierResult,
|
|
34
|
+
} from './types'
|
|
35
|
+
import { detectRendererTier, isTierAtLeast } from './detectRendererTier'
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Public shape
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Opaque factory shape. We don't constrain the Renderer construction here —
|
|
43
|
+
* the consumer's backend implementation knows its own signature. The
|
|
44
|
+
* selector is purely about *which* factory to hand back.
|
|
45
|
+
*/
|
|
46
|
+
export type BackendFactory<T = unknown> = () => T
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Map of tier → registered factory. Tiers that are absent or `null` are
|
|
50
|
+
* treated as "not registered" and skipped during selection.
|
|
51
|
+
*
|
|
52
|
+
* `'none'` is intentionally absent from the type. A `'none'` tier is the
|
|
53
|
+
* absence of any rendering capability; there is nothing to register.
|
|
54
|
+
*/
|
|
55
|
+
export type BackendRegistry<T = unknown> = Partial<
|
|
56
|
+
Record<Exclude<RendererTier, 'none'>, BackendFactory<T> | null>
|
|
57
|
+
>
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Selection result. `tier` is the effective tier the chosen factory
|
|
61
|
+
* targets — which is at most the detected tier. `fallbackChain`
|
|
62
|
+
* enumerates the tiers the selector traversed (high → low). When no
|
|
63
|
+
* backend is registered for any tier ≤ the detected tier, returns
|
|
64
|
+
* `tier: 'none'` and `factory: null`.
|
|
65
|
+
*/
|
|
66
|
+
export interface BackendSelection<T = unknown> {
|
|
67
|
+
readonly tier: RendererTier
|
|
68
|
+
readonly factory: BackendFactory<T> | null
|
|
69
|
+
readonly fallbackChain: ReadonlyArray<RendererTier>
|
|
70
|
+
readonly reason: string
|
|
71
|
+
/**
|
|
72
|
+
* The original tier-detection result. Useful for telemetry — when
|
|
73
|
+
* `tier < detection.tier` the consumer knows the host could have
|
|
74
|
+
* done better but the registry was the binding constraint.
|
|
75
|
+
*/
|
|
76
|
+
readonly detection: RendererTierResult
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface SelectBackendOptions<T = unknown> {
|
|
80
|
+
readonly registry: BackendRegistry<T>
|
|
81
|
+
/**
|
|
82
|
+
* Tier-detection probes pass-through for tests. Same shape as
|
|
83
|
+
* {@link DetectRendererTierOptions}.
|
|
84
|
+
*/
|
|
85
|
+
readonly detect?: DetectRendererTierOptions
|
|
86
|
+
/**
|
|
87
|
+
* Optional pre-computed detection result. When provided, the selector
|
|
88
|
+
* skips `detectRendererTier()` and uses this directly. Useful when
|
|
89
|
+
* the caller cached the detection at app startup.
|
|
90
|
+
*/
|
|
91
|
+
readonly detection?: RendererTierResult
|
|
92
|
+
/**
|
|
93
|
+
* Optional floor — refuse to select a backend below this tier even
|
|
94
|
+
* if a lower-tier factory is registered. Used by features that need
|
|
95
|
+
* GPU compute (`minimum: 'webgl2'`). When the floor can't be met,
|
|
96
|
+
* the result has `tier: 'none'` and `factory: null`.
|
|
97
|
+
*/
|
|
98
|
+
readonly minimum?: RendererTier
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Selection
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
const SEARCH_ORDER: ReadonlyArray<Exclude<RendererTier, 'none'>> = [
|
|
106
|
+
'webgpu',
|
|
107
|
+
'webgl2',
|
|
108
|
+
'canvas2d',
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Pick the highest registered backend at or below the detected tier
|
|
113
|
+
* (and at or above the optional minimum). Pure-data.
|
|
114
|
+
*
|
|
115
|
+
* const sel = selectBackend({
|
|
116
|
+
* registry: { webgpu: makeGpu, webgl2: makeGl2, canvas2d: makeC2d },
|
|
117
|
+
* })
|
|
118
|
+
* if (sel.factory === null) throw new Error('no renderer')
|
|
119
|
+
* const renderer = sel.factory()
|
|
120
|
+
*
|
|
121
|
+
* Telemetry pattern:
|
|
122
|
+
*
|
|
123
|
+
* if (sel.tier !== sel.detection.tier) {
|
|
124
|
+
* log('renderer downgrade', sel.detection.tier, '→', sel.tier, sel.reason)
|
|
125
|
+
* }
|
|
126
|
+
*/
|
|
127
|
+
export function selectBackend<T = unknown>(
|
|
128
|
+
opts: SelectBackendOptions<T>,
|
|
129
|
+
): BackendSelection<T> {
|
|
130
|
+
const detection = opts.detection ?? detectRendererTier(opts.detect)
|
|
131
|
+
const detectedTier = detection.tier
|
|
132
|
+
const minimum = opts.minimum ?? 'none'
|
|
133
|
+
|
|
134
|
+
// Validate the minimum is a known tier; reject 'none' as a minimum
|
|
135
|
+
// because a 'none' floor is meaningless — nothing can be below it.
|
|
136
|
+
if (!(minimum in RENDERER_TIER_RANK)) {
|
|
137
|
+
throw new KLineChartError(
|
|
138
|
+
'INVALID_PARAM',
|
|
139
|
+
`selectBackend: minimum must be a RendererTier, got ${JSON.stringify(minimum)}`,
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const chain: RendererTier[] = []
|
|
144
|
+
// Search from the detected tier downwards through SEARCH_ORDER.
|
|
145
|
+
for (const candidate of SEARCH_ORDER) {
|
|
146
|
+
// Skip tiers above the detected ceiling.
|
|
147
|
+
if (RENDERER_TIER_RANK[candidate] > RENDERER_TIER_RANK[detectedTier]) {
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
chain.push(candidate)
|
|
151
|
+
// Skip below the configured minimum.
|
|
152
|
+
if (!isTierAtLeast(candidate, minimum)) {
|
|
153
|
+
// No further candidate will satisfy the minimum.
|
|
154
|
+
break
|
|
155
|
+
}
|
|
156
|
+
const factory = opts.registry[candidate] ?? null
|
|
157
|
+
if (factory !== null) {
|
|
158
|
+
return {
|
|
159
|
+
tier: candidate,
|
|
160
|
+
factory,
|
|
161
|
+
fallbackChain: chain,
|
|
162
|
+
reason:
|
|
163
|
+
candidate === detectedTier
|
|
164
|
+
? `direct match: detected ${candidate} and ${candidate} backend is registered`
|
|
165
|
+
: `downgrade: detected ${detectedTier}, but only ${candidate} backend is registered`,
|
|
166
|
+
detection,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
tier: 'none',
|
|
173
|
+
factory: null,
|
|
174
|
+
fallbackChain: chain,
|
|
175
|
+
reason:
|
|
176
|
+
detectedTier === 'none'
|
|
177
|
+
? `host has no renderable tier`
|
|
178
|
+
: `no registered backend at or below detected ${detectedTier}` +
|
|
179
|
+
(opts.minimum !== undefined && opts.minimum !== 'none'
|
|
180
|
+
? ` (minimum=${opts.minimum})`
|
|
181
|
+
: ''),
|
|
182
|
+
detection,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Strict variant: throws `KLineChartError('INVALID_STATE')` if no factory
|
|
188
|
+
* could be selected. Use when a renderable backend is mandatory.
|
|
189
|
+
*/
|
|
190
|
+
export function selectBackendOrThrow<T = unknown>(
|
|
191
|
+
opts: SelectBackendOptions<T>,
|
|
192
|
+
): BackendSelection<T> & { factory: BackendFactory<T> } {
|
|
193
|
+
const sel = selectBackend(opts)
|
|
194
|
+
if (sel.factory === null) {
|
|
195
|
+
throw new KLineChartError(
|
|
196
|
+
'INVALID_STATE',
|
|
197
|
+
`selectBackendOrThrow: ${sel.reason}`,
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
return sel as BackendSelection<T> & { factory: BackendFactory<T> }
|
|
201
|
+
}
|