@jbrowse/core 5.0.0-beta.7 → 5.0.0-beta.9
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 +427 -130
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +5 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -5
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +8 -9
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +8 -13
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +3 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +8 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +24 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +5 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.d.ts +1 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +1 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.d.ts +16 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +53 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.d.ts +0 -8
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.js +0 -16
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceContents.js +7 -34
- package/esm/BaseFeatureWidget/configSchema.d.ts +1 -1
- package/esm/BaseFeatureWidget/formatDetails.d.ts +13 -29
- package/esm/BaseFeatureWidget/formatDetails.js +46 -79
- package/esm/BaseFeatureWidget/index.d.ts +1 -0
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +35 -28
- package/esm/BaseFeatureWidget/stateModelFactory.js +94 -102
- package/esm/BaseFeatureWidget/types.d.ts +3 -0
- package/esm/BaseFeatureWidget/util.d.ts +0 -3
- package/esm/BaseFeatureWidget/util.js +0 -17
- package/esm/PluginLoader.d.ts +14 -9
- package/esm/PluginLoader.js +34 -26
- package/esm/PluginManager.d.ts +4 -4
- package/esm/PluginManager.js +1 -1
- package/esm/ReExports/coreModules.generated.d.ts +2 -0
- package/esm/ReExports/coreModules.generated.js +492 -0
- package/esm/ReExports/coreWorkerModules.generated.d.ts +2 -0
- package/esm/ReExports/coreWorkerModules.generated.js +453 -0
- package/esm/ReExports/frameworkModules.d.ts +2 -0
- package/esm/ReExports/frameworkModules.js +67 -0
- package/esm/ReExports/frameworkShared.d.ts +12 -0
- package/esm/ReExports/frameworkShared.js +16 -0
- package/esm/ReExports/frameworkWorkerModules.generated.d.ts +2 -0
- package/esm/ReExports/frameworkWorkerModules.generated.js +130 -0
- package/esm/ReExports/list.js +493 -79
- package/esm/ReExports/modules.d.ts +1 -1
- package/esm/ReExports/modules.js +10 -87
- package/esm/ReExports/registry.d.ts +1 -0
- package/esm/ReExports/registry.js +23 -5
- package/esm/ReExports/uiStub.d.ts +2 -1
- package/esm/ReExports/uiStub.js +24 -2
- package/esm/ReExports/workerModules.js +8 -12
- package/esm/TextSearch/TextSearchManager.d.ts +3 -12
- package/esm/TextSearch/TextSearchManager.js +22 -10
- package/esm/assemblyManager/assembly.d.ts +10 -14
- package/esm/assemblyManager/assembly.js +10 -14
- package/esm/assemblyManager/assemblyConfigSchema.d.ts +23 -81
- package/esm/assemblyManager/assemblyManager.d.ts +10 -16
- package/esm/assemblyManager/assemblyManager.js +7 -10
- package/esm/assemblyManager/loadRefNameMap.js +3 -3
- package/esm/configuration/configurationSchema.d.ts +75 -31
- package/esm/configuration/configurationSchema.js +74 -40
- package/esm/configuration/configurationSchemaUnion.d.ts +39 -0
- package/esm/configuration/configurationSchemaUnion.js +59 -0
- package/esm/configuration/configurationSlot.d.ts +37 -12
- package/esm/configuration/configurationSlot.js +83 -22
- package/esm/configuration/formatAboutConfigSchema.d.ts +7 -21
- package/esm/configuration/formatDetailsConfigSchema.d.ts +11 -37
- package/esm/configuration/formatDetailsConfigSchema.js +10 -13
- package/esm/configuration/getConf.d.ts +17 -9
- package/esm/configuration/getConf.js +52 -7
- package/esm/configuration/index.d.ts +11 -4
- package/esm/configuration/index.js +7 -4
- package/esm/configuration/mergeFormatCallbacks.d.ts +6 -7
- package/esm/configuration/mergeFormatCallbacks.js +13 -10
- package/esm/configuration/readConfObject.d.ts +2 -22
- package/esm/configuration/readConfObject.js +15 -49
- package/esm/configuration/requirements.d.ts +37 -0
- package/esm/configuration/requirements.js +88 -0
- package/esm/configuration/schemaRegistry.d.ts +21 -1
- package/esm/configuration/schemaRegistry.js +11 -0
- package/esm/configuration/schemaTypes.d.ts +3 -0
- package/esm/configuration/schemaTypes.js +10 -0
- package/esm/configuration/slotFacade.d.ts +35 -4
- package/esm/configuration/slotFacade.js +96 -9
- package/esm/configuration/snapshotPreprocess.d.ts +27 -0
- package/esm/configuration/snapshotPreprocess.js +102 -0
- package/esm/configuration/types.d.ts +161 -22
- package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +11 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +12 -1
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +2 -3
- package/esm/data_adapters/BaseAdapter/featureDensity.js +2 -3
- package/esm/data_adapters/BaseAdapter/index.d.ts +22 -3
- package/esm/data_adapters/BaseAdapter/types.d.ts +3 -4
- package/esm/data_adapters/BaseAdapter/zoomRange.d.ts +10 -0
- package/esm/data_adapters/BaseAdapter/zoomRange.js +1 -0
- package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +9 -11
- package/esm/data_adapters/getSequenceSubAdapter.d.ts +1 -3
- package/esm/data_adapters/getSequenceSubAdapter.js +1 -3
- package/esm/pluggableElementTypes/AdapterType.d.ts +7 -7
- package/esm/pluggableElementTypes/RpcMethodType.d.ts +1 -1
- package/esm/pluggableElementTypes/RpcMethodType.js +3 -8
- package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.d.ts +1 -2
- package/esm/pluggableElementTypes/TextSearchAdapterType.d.ts +7 -7
- package/esm/pluggableElementTypes/index.d.ts +1 -1
- package/esm/pluggableElementTypes/index.js +1 -1
- package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +17 -7
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +45 -48
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +40 -36
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +10 -13
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +6 -6
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +37 -17
- package/esm/pluggableElementTypes/models/BaseViewModel.js +25 -10
- package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +26 -16
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +1 -1
- package/esm/pluggableElementTypes/models/baseConnectionConfig.d.ts +22 -18
- package/esm/pluggableElementTypes/models/baseConnectionConfig.js +5 -5
- package/esm/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +26 -31
- package/esm/pluggableElementTypes/models/baseTrackConfig.d.ts +57 -141
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +22 -26
- package/esm/pluggableElementTypes/models/components/SaveTrackData.js +2 -2
- package/esm/pluggableElementTypes/models/components/fetchTrackData.d.ts +3 -4
- package/esm/pluggableElementTypes/models/components/fetchTrackData.js +3 -3
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.d.ts +15 -7
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +38 -29
- package/esm/pluggableElementTypes/models/index.d.ts +1 -2
- package/esm/pluggableElementTypes/models/index.js +1 -2
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.d.ts +3 -3
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +4 -4
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/types.d.ts +3 -3
- package/esm/rpc/BaseRpcDriver.d.ts +1 -2
- package/esm/rpc/BaseRpcDriver.js +23 -30
- package/esm/rpc/MainThreadRpcDriver.d.ts +2 -2
- package/esm/rpc/MainThreadRpcDriver.js +13 -8
- package/esm/rpc/RpcClient.d.ts +17 -6
- package/esm/rpc/RpcClient.js +42 -12
- package/esm/rpc/RpcManager.d.ts +8 -10
- package/esm/rpc/RpcManager.js +1 -1
- package/esm/rpc/RpcRegistry.d.ts +8 -2
- package/esm/rpc/RpcServer.d.ts +3 -1
- package/esm/rpc/RpcServer.js +19 -12
- package/esm/rpc/WebWorkerRpcDriver.d.ts +3 -3
- package/esm/rpc/WebWorkerRpcDriver.js +9 -47
- package/esm/rpc/byteBudget.d.ts +3 -5
- package/esm/rpc/byteBudget.js +4 -4
- package/esm/rpc/configSchema.d.ts +7 -21
- package/esm/rpc/coreRpcMethods.d.ts +1 -0
- package/esm/rpc/coreRpcMethods.js +1 -0
- package/esm/rpc/methods/CoreEncodeFeatures.d.ts +6 -5
- package/esm/rpc/methods/CoreEncodeFeatures.js +26 -31
- package/esm/rpc/methods/CoreGetEncodedFeature.d.ts +13 -0
- package/esm/rpc/methods/CoreGetEncodedFeature.js +31 -0
- package/esm/rpc/methods/CoreGetExportData.js +2 -2
- package/esm/rpc/methods/CoreGetFeatureDensity.js +2 -2
- package/esm/rpc/methods/CoreGetFeatures.js +2 -2
- package/esm/rpc/methods/CoreGetSequence.js +2 -2
- package/esm/rpc/methods/layerFeatures.d.ts +26 -0
- package/esm/rpc/methods/layerFeatures.js +40 -0
- package/esm/svg/SvgExport.js +3 -4
- package/esm/svg/SvgThemeProviders.d.ts +12 -0
- package/esm/svg/SvgThemeProviders.js +15 -0
- package/esm/svg/exportViewSvg.d.ts +32 -0
- package/esm/svg/exportViewSvg.js +13 -0
- package/esm/svg/normalizeSvgMarkup.d.ts +7 -0
- package/esm/svg/normalizeSvgMarkup.js +99 -0
- package/esm/svg/serializeSvg.d.ts +7 -0
- package/esm/svg/serializeSvg.js +11 -0
- package/esm/svg/svgReady.d.ts +8 -7
- package/esm/svg/svgReady.js +8 -7
- package/esm/svg/trackNames.d.ts +5 -5
- package/esm/svg/trackNames.js +6 -6
- package/esm/svg/wrapSvgExport.js +6 -74
- package/esm/ui/CascadingMenu.js +83 -86
- package/esm/ui/ErrorMessageStackTraceDialog.js +0 -5
- package/esm/ui/FileSelector/useInternetAccounts.d.ts +156 -96
- package/esm/ui/HoverMenu.d.ts +1 -2
- package/esm/ui/HoverMenu.js +6 -3
- package/esm/ui/JexlFilterDialog.d.ts +13 -10
- package/esm/ui/JexlFilterDialog.js +122 -49
- package/esm/ui/JexlFilterRowEditors.d.ts +15 -0
- package/esm/ui/JexlFilterRowEditors.js +90 -0
- package/esm/ui/LazyBaseTooltip.d.ts +4 -0
- package/esm/ui/LazyBaseTooltip.js +9 -0
- package/esm/ui/LoadingOverlay.js +3 -1
- package/esm/ui/MonospaceTextField.d.ts +2 -1
- package/esm/ui/MonospaceTextField.js +21 -19
- package/esm/ui/PaletteContext.d.ts +7 -9
- package/esm/ui/PaletteContext.js +24 -10
- package/esm/ui/RefNameAutocomplete/index.d.ts +1 -2
- package/esm/ui/RefNameAutocomplete/index.js +1 -1
- package/esm/ui/ScrollChrome.d.ts +6 -9
- package/esm/ui/ScrollChrome.js +5 -6
- package/esm/ui/ScrollEdgeShadow.d.ts +6 -9
- package/esm/ui/ScrollEdgeShadow.js +9 -24
- package/esm/ui/SettingsChangesTable.js +3 -3
- package/esm/ui/VerticalScrollbar.d.ts +13 -34
- package/esm/ui/VerticalScrollbar.js +29 -83
- package/esm/ui/ViewLoadingScreen.d.ts +2 -2
- package/esm/ui/ViewLoadingScreen.js +3 -3
- package/esm/ui/colorScale.d.ts +26 -1
- package/esm/ui/colorScale.js +28 -5
- package/esm/ui/colors.d.ts +49 -1
- package/esm/ui/colors.js +139 -4
- package/esm/ui/hoverBoxStyle.d.ts +14 -2
- package/esm/ui/hoverBoxStyle.js +17 -2
- package/esm/ui/index.d.ts +5 -3
- package/esm/ui/index.js +9 -7
- package/esm/ui/launchViewMenu.js +3 -3
- package/esm/ui/legendSpec.d.ts +2 -0
- package/esm/ui/legendSpec.js +3 -0
- package/esm/ui/palette.d.ts +0 -1
- package/esm/ui/palette.js +3 -27
- package/esm/ui/replaceViewAction.d.ts +1 -1
- package/esm/ui/replaceViewAction.js +1 -1
- package/esm/ui/theme.d.ts +1 -1
- package/esm/ui/theme.js +6 -40
- package/esm/ui/viewHeaderHeight.d.ts +1 -0
- package/esm/ui/viewHeaderHeight.js +1 -0
- package/esm/util/Base1DUtils.d.ts +1 -1
- package/esm/util/Base1DUtils.js +2 -2
- package/esm/util/SvgCanvas.d.ts +15 -13
- package/esm/util/SvgCanvas.js +72 -53
- package/esm/util/aborting.d.ts +39 -0
- package/esm/util/aborting.js +84 -0
- package/esm/util/adapterMetadata.d.ts +1 -1
- package/esm/util/adapterMetadata.js +6 -6
- package/esm/util/addAndShowTrack.d.ts +1 -4
- package/esm/util/addRelativeUris.d.ts +10 -2
- package/esm/util/addRelativeUris.js +22 -7
- package/esm/util/addTrackFromWidget.d.ts +2 -5
- package/esm/util/animationAllowed.d.ts +9 -0
- package/esm/util/animationAllowed.js +13 -0
- package/esm/util/applyRowResizeWheel.d.ts +10 -5
- package/esm/util/applyRowResizeWheel.js +10 -21
- package/esm/util/bandLayout.d.ts +4 -4
- package/esm/util/bandLayout.js +4 -4
- package/esm/util/bezierConnector.js +5 -4
- package/esm/util/bgzfWorkerPool.d.ts +20 -74
- package/esm/util/bgzfWorkerPool.js +20 -74
- package/esm/util/cachedSetup.d.ts +1 -1
- package/esm/util/cachedSetup.js +2 -2
- package/esm/util/categoricalField.d.ts +37 -0
- package/esm/util/categoricalField.js +52 -0
- package/esm/util/color/cssColorsLevel4.d.ts +1 -0
- package/esm/util/color/cssColorsLevel4.js +1 -0
- package/esm/util/color/index.d.ts +5 -3
- package/esm/util/color/index.js +7 -4
- package/esm/util/colorBits.d.ts +1 -2
- package/esm/util/colorBits.js +17 -39
- package/esm/util/colorRamp.d.ts +27 -1
- package/esm/util/colorRamp.js +56 -2
- package/esm/util/colorSchemes.d.ts +9 -0
- package/esm/util/colorSchemes.js +7 -0
- package/esm/util/{createStopTokenRotation.d.ts → createAbortRotation.d.ts} +11 -14
- package/esm/util/{createStopTokenRotation.js → createAbortRotation.js} +14 -26
- package/esm/util/cssColorParse.d.ts +15 -0
- package/esm/util/cssColorParse.js +53 -0
- package/esm/util/diagonalizeRegions.d.ts +2 -3
- package/esm/util/diagonalizeRegions.js +7 -12
- package/esm/util/expandLooseSearchIndex.d.ts +7 -0
- package/esm/util/expandLooseSearchIndex.js +25 -0
- package/esm/util/featureTransforms.d.ts +30 -3
- package/esm/util/featureTransforms.js +233 -36
- package/esm/util/fetchAndMaybeUnzip.js +5 -6
- package/esm/util/fetchContext.d.ts +5 -6
- package/esm/util/fetchContext.js +1 -1
- package/esm/util/fetchHub.d.ts +3 -1
- package/esm/util/fetchHub.js +2 -2
- package/esm/util/fetchSeq.d.ts +2 -3
- package/esm/util/fetchSeq.js +2 -2
- package/esm/util/fieldReader.d.ts +17 -0
- package/esm/util/fieldReader.js +62 -0
- package/esm/util/groupKeys.d.ts +75 -0
- package/esm/util/groupKeys.js +152 -0
- package/esm/util/highlights.d.ts +6 -4
- package/esm/util/highlights.js +12 -25
- package/esm/util/hooks.d.ts +1 -2
- package/esm/util/hooks.js +1 -2
- package/esm/util/index.d.ts +3 -3
- package/esm/util/index.js +4 -3
- package/esm/util/indexCandidates.js +1 -1
- package/esm/util/installFetch.d.ts +13 -10
- package/esm/util/installFetch.js +11 -10
- package/esm/util/installPrerequisiteFetch.d.ts +5 -3
- package/esm/util/installPrerequisiteFetch.js +3 -4
- package/esm/util/io/index.js +12 -12
- package/esm/util/isDataCurrent.d.ts +7 -5
- package/esm/util/isDataCurrent.js +9 -6
- package/esm/util/jexl.js +24 -21
- package/esm/util/jexlFilterRows.d.ts +89 -0
- package/esm/util/jexlFilterRows.js +252 -0
- package/esm/util/jexlFilters.d.ts +7 -5
- package/esm/util/jexlStrings.d.ts +3 -4
- package/esm/util/jexlStrings.js +2 -3
- package/esm/util/legendCandidates.d.ts +31 -27
- package/esm/util/legendCandidates.js +79 -53
- package/esm/util/localStorage.js +4 -4
- package/esm/util/markEncoding.d.ts +32 -16
- package/esm/util/markEncoding.js +177 -150
- package/esm/util/markEncodingTypes.d.ts +137 -66
- package/esm/util/mstUtils.d.ts +19 -22
- package/esm/util/mstUtils.js +19 -22
- package/esm/util/numericUtils.d.ts +7 -0
- package/esm/util/numericUtils.js +16 -0
- package/esm/util/numericValue.d.ts +14 -0
- package/esm/util/numericValue.js +34 -0
- package/esm/util/openFeatureWidget.js +1 -2
- package/esm/util/openViews.d.ts +1 -0
- package/esm/util/openViews.js +3 -3
- package/esm/util/parseLineByLine.d.ts +3 -4
- package/esm/util/parseLineByLine.js +7 -13
- package/esm/util/progress.d.ts +21 -21
- package/esm/util/progress.js +27 -26
- package/esm/util/renameRegions.d.ts +1 -2
- package/esm/util/renderToStaticMarkup.js +16 -16
- package/esm/util/rxjs.d.ts +7 -8
- package/esm/util/rxjs.js +12 -15
- package/esm/util/simpleFeature.d.ts +0 -1
- package/esm/util/svgColorProps.d.ts +11 -0
- package/esm/util/svgColorProps.js +28 -1
- package/esm/util/tabix.d.ts +3 -4
- package/esm/util/tabix.js +6 -7
- package/esm/util/thresholdScale.d.ts +54 -0
- package/esm/util/thresholdScale.js +112 -0
- package/esm/util/timeGate.d.ts +4 -5
- package/esm/util/timeGate.js +4 -5
- package/esm/util/trackConfigDelta.d.ts +22 -18
- package/esm/util/trackConfigDelta.js +40 -38
- package/esm/util/tracks.d.ts +27 -4
- package/esm/util/tracks.js +116 -43
- package/esm/util/translateTranscript.d.ts +44 -0
- package/esm/util/translateTranscript.js +102 -0
- package/esm/util/types/index.d.ts +19 -7
- package/esm/util/types/services.d.ts +1 -1
- package/esm/util/unknownSnapshotKeys.d.ts +15 -0
- package/esm/util/unknownSnapshotKeys.js +13 -0
- package/esm/util/useFeatureSequence.js +4 -4
- package/esm/util/useFetch.d.ts +3 -4
- package/esm/util/useFetch.js +5 -6
- package/esm/util/usePanelVirtualScroll.d.ts +7 -39
- package/esm/util/usePanelVirtualScroll.js +9 -40
- package/esm/util/useRowVirtualScroll.d.ts +6 -29
- package/esm/util/useRowVirtualScroll.js +8 -49
- package/esm/util/useVirtualScrollWheel.d.ts +20 -4
- package/esm/util/useVirtualScrollWheel.js +40 -84
- package/esm/util/viewHighlights.d.ts +3 -0
- package/esm/util/viewHighlights.js +5 -0
- package/esm/util/viewStatus.d.ts +24 -15
- package/esm/util/viewStatus.js +17 -0
- package/esm/util/withLaunchInput.d.ts +1 -1
- package/esm/util/withLaunchInput.js +0 -4
- package/package.json +26 -12
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.d.ts +0 -80
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.js +0 -583
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +0 -141
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.js +0 -1116
- package/esm/ReExports/BaseFeatureDetails.d.ts +0 -1
- package/esm/ReExports/BaseFeatureDetails.js +0 -10
- package/esm/ReExports/barrelOnlyNames.d.ts +0 -5
- package/esm/ReExports/barrelOnlyNames.js +0 -63
- package/esm/ReExports/index.d.ts +0 -1
- package/esm/ReExports/index.js +0 -1
- package/esm/ReExports/publicTracks.d.ts +0 -1
- package/esm/ReExports/publicTracks.js +0 -14
- package/esm/ReExports/publicUi.d.ts +0 -4
- package/esm/ReExports/publicUi.js +0 -33
- package/esm/ReExports/publicUtil.d.ts +0 -1
- package/esm/ReExports/publicUtil.js +0 -32
- package/esm/ReExports/sharedModules.d.ts +0 -96
- package/esm/ReExports/sharedModules.js +0 -66
- package/esm/ReExports/workerNamespaceNames.d.ts +0 -11
- package/esm/ReExports/workerNamespaceNames.js +0 -275
- package/esm/pluggableElementTypes/models/HighlightsMixin.d.ts +0 -51
- package/esm/pluggableElementTypes/models/HighlightsMixin.js +0 -78
- package/esm/ui/highlightChipReveal.d.ts +0 -32
- package/esm/ui/highlightChipReveal.js +0 -39
- package/esm/util/adapterConfigKey.d.ts +0 -12
- package/esm/util/adapterConfigKey.js +0 -14
- package/esm/util/stopToken.d.ts +0 -212
- package/esm/util/stopToken.js +0 -438
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module
|
|
3
|
-
* The config **readers**: `readConfObject` off a live MST config node,
|
|
4
|
-
* `readConfigValue` off a plain snapshot object in a worker or a renderer
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* The config **readers**: `readConfObject` off a live MST config node, and
|
|
4
|
+
* `readConfigValue` off a plain snapshot object in a worker or a renderer. Both
|
|
5
|
+
* exist to evaluate a slot's `jexl:...` callback on read; they differ only in
|
|
6
|
+
* where the jexl instance comes from, the node's env or an explicit argument.
|
|
7
|
+
* A `featureField` slot's `jexl:` expression is the display's to evaluate per
|
|
8
|
+
* feature, so `readConfObject` hands it over as written.
|
|
9
9
|
*/
|
|
10
10
|
import { getEnv, getSnapshot, getType, isMapType, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
|
|
11
|
+
import { getConfigurationSchemaMetadata } from './schemaRegistry.js';
|
|
11
12
|
import { evaluateJexl, isCallbackValue } from './slotValueUtils.js';
|
|
12
13
|
// Evaluate a slot's `jexl:...` callback string against the realm's single jexl
|
|
13
14
|
// instance (carrying plugin-registered functions), read from the config node's
|
|
@@ -40,6 +41,10 @@ function rawSlotValue(confObject, slotName) {
|
|
|
40
41
|
? confObject.get(slotName)
|
|
41
42
|
: confObject[slotName];
|
|
42
43
|
}
|
|
44
|
+
function isFeatureField(confObject, slotName) {
|
|
45
|
+
return (isStateTreeNode(confObject) &&
|
|
46
|
+
!!getConfigurationSchemaMetadata(getType(confObject))?.featureFields.has(slotName));
|
|
47
|
+
}
|
|
43
48
|
// Read and resolve a single slot: raw value, jexl callback evaluation, then a
|
|
44
49
|
// referentially-stable snapshot for sub-config nodes.
|
|
45
50
|
function readSlot(confObject, slotName, args) {
|
|
@@ -49,7 +54,7 @@ function readSlot(confObject, slotName, args) {
|
|
|
49
54
|
if (value === undefined) {
|
|
50
55
|
return undefined;
|
|
51
56
|
}
|
|
52
|
-
const val = isCallbackValue(value)
|
|
57
|
+
const val = isCallbackValue(value) && !isFeatureField(confObject, slotName)
|
|
53
58
|
? evalConfigCallback(value, args, confObject)
|
|
54
59
|
: value;
|
|
55
60
|
// Fast path for primitives (most common case)
|
|
@@ -97,10 +102,9 @@ export function readConfObject(confObject, slotPath, args = {}) {
|
|
|
97
102
|
}
|
|
98
103
|
return readSlot(conf, slotPath[slotPath.length - 1], args);
|
|
99
104
|
}
|
|
100
|
-
// The plain-object half of the slot walk,
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
// reduce.
|
|
105
|
+
// The plain-object half of the slot walk, for readConfigValue. The MST half is
|
|
106
|
+
// readSlot/rawSlotValue above. A plain object has no map entries and no
|
|
107
|
+
// sub-config nodes to snapshot, so it is just a path reduce.
|
|
104
108
|
function resolveConfigValue(config, key) {
|
|
105
109
|
if (Array.isArray(key)) {
|
|
106
110
|
let val = config;
|
|
@@ -121,41 +125,3 @@ export function readConfigValue(config, key, feature, jexl) {
|
|
|
121
125
|
const raw = resolveConfigValue(config, key);
|
|
122
126
|
return (isCallbackValue(raw) ? evaluateJexl(raw, { feature }, jexl) : raw);
|
|
123
127
|
}
|
|
124
|
-
/**
|
|
125
|
-
* #api core/configuration
|
|
126
|
-
* Read a single config slot from a config that may be **either** a live MST
|
|
127
|
-
* node or a plain snapshot object, evaluating the value if it is a `jexl:`
|
|
128
|
-
* expression. For the dialogs and panels that are handed a track config without
|
|
129
|
-
* knowing which of the two they got. An About panel gets a hydrated track
|
|
130
|
-
* config from the session and a bare object from an embedded caller.
|
|
131
|
-
*
|
|
132
|
-
* Reach for `readConfObject` or `readConfigValue` when the shape is known:
|
|
133
|
-
* this one decides at runtime, and the plain branch inherits the snapshot
|
|
134
|
-
* caveat (a slot at its default is absent from a snapshot, so it reads
|
|
135
|
-
* `undefined`).
|
|
136
|
-
*
|
|
137
|
-
* @param config - live config model or plain config object
|
|
138
|
-
* @param slotPath - slot name, or path of sub-config names ending in a slot
|
|
139
|
-
* @param args - extra arguments for a callback slot, e.g. `{ feature }`
|
|
140
|
-
* @param jexl - realm jexl instance, required only to evaluate a callback slot
|
|
141
|
-
* on a plain object (a live node resolves its own from env)
|
|
142
|
-
*/
|
|
143
|
-
export function readConfSlot(config, slotPath, args = {}, jexl) {
|
|
144
|
-
if (isStateTreeNode(config)) {
|
|
145
|
-
// pass slotPath through rather than normalizing a string into a one-element
|
|
146
|
-
// array: readConfObject keeps the single-slot read allocation-free
|
|
147
|
-
return readConfObject(config, slotPath, args);
|
|
148
|
-
}
|
|
149
|
-
const value = resolveConfigValue(config, slotPath);
|
|
150
|
-
// A plain-object config has no MST env, so the realm's jexl instance can't be
|
|
151
|
-
// resolved automatically — callers reading a callback slot must pass it. Only
|
|
152
|
-
// reached when the slot actually holds a `jexl:` value (trackId/adapter/etc.
|
|
153
|
-
// never do), so non-callback readers need not supply it.
|
|
154
|
-
if (isCallbackValue(value)) {
|
|
155
|
-
if (!jexl) {
|
|
156
|
-
throw new Error(`cannot evaluate jexl config slot ${JSON.stringify(slotPath)} on a plain-object config: no jexl instance provided`);
|
|
157
|
-
}
|
|
158
|
-
return evaluateJexl(value, args, jexl);
|
|
159
|
-
}
|
|
160
|
-
return value;
|
|
161
|
-
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ConfigurationSchemaDefinition } from './configurationSchema.ts';
|
|
2
|
+
import type { IAnyType } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
/**
|
|
4
|
+
* A combination one config object cannot mean, declared once: when every slot
|
|
5
|
+
* named in `when` holds one of the listed values, each dotted path in `slots`
|
|
6
|
+
* has to name a value — a non-empty string, or a sub-schema a string lifts
|
|
7
|
+
* into. `message` says why, and `id` is the stable name a report carries.
|
|
8
|
+
* `requirementProblems` reads it for a display's notice, and the generated
|
|
9
|
+
* JSON Schema carries it as `if`/`then` with the message, which the CLI
|
|
10
|
+
* validator and an editor report.
|
|
11
|
+
*
|
|
12
|
+
* `ConfigurationSchema()` types `when`, its values and `slots` off the
|
|
13
|
+
* definition and throws at construction for what the types cannot reach: a
|
|
14
|
+
* misspelt `when` key or value would never fire, and a misspelt path would
|
|
15
|
+
* require a key `closed` then refuses.
|
|
16
|
+
*/
|
|
17
|
+
export interface ConfigurationSchemaRequirement<WHEN extends Partial<Record<string, string[]>> = Partial<Record<string, string[]>>, PATH extends string = string> {
|
|
18
|
+
id: string;
|
|
19
|
+
when: WHEN;
|
|
20
|
+
slots: PATH[];
|
|
21
|
+
message: string;
|
|
22
|
+
}
|
|
23
|
+
/** A requirement a snapshot does not meet: the slot path left empty, and why. */
|
|
24
|
+
export interface RequirementProblem {
|
|
25
|
+
id: string;
|
|
26
|
+
slot: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function checkRequirements(modelName: string, definition: ConfigurationSchemaDefinition, requires: ConfigurationSchemaRequirement[]): void;
|
|
30
|
+
/**
|
|
31
|
+
* #api core/configuration
|
|
32
|
+
* The `requires` entries of a configuration schema that `snapshot` does not
|
|
33
|
+
* meet, as a config file or `getSnapshot` spells it: a slot left off reads as
|
|
34
|
+
* its default, so a `when` value that is the default fires for an absent slot,
|
|
35
|
+
* which is what the generated JSON Schema's `if` does.
|
|
36
|
+
*/
|
|
37
|
+
export declare function requirementProblems(type: IAnyType, snapshot: Record<string, unknown>): RequirementProblem[];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { getConfigurationSchemaMetadata } from './schemaRegistry.js';
|
|
2
|
+
import { isBareConfigurationSchemaType, isSlotDefinitionEntry, } from './schemaTypes.js';
|
|
3
|
+
function memberOf(definition, name) {
|
|
4
|
+
return Object.hasOwn(definition, name) ? definition[name] : undefined;
|
|
5
|
+
}
|
|
6
|
+
function subSchemaOf(entry) {
|
|
7
|
+
return isBareConfigurationSchemaType(entry)
|
|
8
|
+
? getConfigurationSchemaMetadata(entry)
|
|
9
|
+
: undefined;
|
|
10
|
+
}
|
|
11
|
+
function requiredPathProblem(modelName, definition, path) {
|
|
12
|
+
const [head = '', ...rest] = path;
|
|
13
|
+
const entry = memberOf(definition, head);
|
|
14
|
+
const sub = subSchemaOf(entry);
|
|
15
|
+
return entry === undefined
|
|
16
|
+
? `${modelName} declares no "${head}"`
|
|
17
|
+
: rest.length > 0
|
|
18
|
+
? sub
|
|
19
|
+
? requiredPathProblem(sub.name, sub.definition, rest)
|
|
20
|
+
: `"${head}" is not a single sub-schema, so no path runs through it`
|
|
21
|
+
: isSlotDefinitionEntry(entry)
|
|
22
|
+
? entry.defaultValue === undefined ||
|
|
23
|
+
typeof entry.defaultValue === 'string'
|
|
24
|
+
? undefined
|
|
25
|
+
: `"${head}" holds no string, and a requirement is met by naming one`
|
|
26
|
+
: sub?.options.shorthand !== undefined
|
|
27
|
+
? undefined
|
|
28
|
+
: `"${head}" is neither a slot nor a sub-schema a string lifts into`;
|
|
29
|
+
}
|
|
30
|
+
export function checkRequirements(modelName, definition, requires) {
|
|
31
|
+
for (const { when, slots } of requires) {
|
|
32
|
+
for (const [slot, values = []] of Object.entries(when)) {
|
|
33
|
+
const entry = memberOf(definition, slot);
|
|
34
|
+
if (!isSlotDefinitionEntry(entry)) {
|
|
35
|
+
throw new Error(`${modelName} requires something when "${slot}" holds a value, and declares no such slot`);
|
|
36
|
+
}
|
|
37
|
+
const refused = values.filter(value => entry.model?.is(value) === false);
|
|
38
|
+
if (refused.length > 0) {
|
|
39
|
+
throw new Error(`${modelName} requires something when "${slot}" holds ${refused.join(', ')}, which the slot does not take`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const path of slots) {
|
|
43
|
+
const problem = requiredPathProblem(modelName, definition, path.split('.'));
|
|
44
|
+
if (problem) {
|
|
45
|
+
throw new Error(`${modelName} requires "${path}", and ${problem}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function namesAValue(definition, snapshot, path) {
|
|
51
|
+
const [head = '', ...rest] = path;
|
|
52
|
+
const value = typeof snapshot === 'object' && snapshot !== null
|
|
53
|
+
? snapshot[head]
|
|
54
|
+
: undefined;
|
|
55
|
+
const sub = subSchemaOf(memberOf(definition, head));
|
|
56
|
+
const shorthand = sub?.options.shorthand;
|
|
57
|
+
return rest.length > 0
|
|
58
|
+
? sub !== undefined && namesAValue(sub.definition, value, rest)
|
|
59
|
+
: typeof value === 'string'
|
|
60
|
+
? value !== ''
|
|
61
|
+
: sub !== undefined &&
|
|
62
|
+
shorthand !== undefined &&
|
|
63
|
+
namesAValue(sub.definition, value, [shorthand]);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* #api core/configuration
|
|
67
|
+
* The `requires` entries of a configuration schema that `snapshot` does not
|
|
68
|
+
* meet, as a config file or `getSnapshot` spells it: a slot left off reads as
|
|
69
|
+
* its default, so a `when` value that is the default fires for an absent slot,
|
|
70
|
+
* which is what the generated JSON Schema's `if` does.
|
|
71
|
+
*/
|
|
72
|
+
export function requirementProblems(type, snapshot) {
|
|
73
|
+
const schema = getConfigurationSchemaMetadata(type);
|
|
74
|
+
if (!schema) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
const { definition } = schema;
|
|
78
|
+
return (schema.options.requires ?? [])
|
|
79
|
+
.filter(({ when }) => Object.entries(when).every(([slot, values]) => {
|
|
80
|
+
const entry = memberOf(definition, slot);
|
|
81
|
+
const held = snapshot[slot] ??
|
|
82
|
+
(isSlotDefinitionEntry(entry) ? entry.defaultValue : undefined);
|
|
83
|
+
return typeof held === 'string' && values?.includes(held);
|
|
84
|
+
}))
|
|
85
|
+
.flatMap(({ id, slots, message }) => slots
|
|
86
|
+
.filter(path => !namesAValue(definition, snapshot, path.split('.')))
|
|
87
|
+
.map(slot => ({ id, slot, message })));
|
|
88
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ConfigurationSchemaDefinition, MergedConfigurationSchemaOptions } from './configurationSchema.ts';
|
|
2
|
-
import type { AnyConfigurationModel } from './types.ts';
|
|
2
|
+
import type { AnyConfigurationModel, AnyConfigurationSchemaType } from './types.ts';
|
|
3
3
|
import type { IAnyType } from '@jbrowse/mobx-state-tree';
|
|
4
4
|
export interface ConfigurationSchemaMetadata {
|
|
5
|
+
/** the name `ConfigurationSchema` was given, e.g. `FeatureColor` */
|
|
6
|
+
name: string;
|
|
5
7
|
/** the raw slot/sub-schema/constant table, also carrying per-slot editor metadata */
|
|
6
8
|
definition: ConfigurationSchemaDefinition;
|
|
7
9
|
/**
|
|
@@ -9,10 +11,28 @@ export interface ConfigurationSchemaMetadata {
|
|
|
9
11
|
* i.e. with any `baseConfiguration`'s hooks already composed in
|
|
10
12
|
*/
|
|
11
13
|
options: MergedConfigurationSchemaOptions<any, any>;
|
|
14
|
+
/** the frozen-family slots, the only members a snapshot's `null` is stored in */
|
|
15
|
+
storesNull: ReadonlySet<string>;
|
|
16
|
+
/** the `featureField` slots, which the reader hands over as written */
|
|
17
|
+
featureFields: ReadonlySet<string>;
|
|
18
|
+
/** the slots that refuse a `jexl:` string: every one but a callback and a featureField */
|
|
19
|
+
takesNoCallback: ReadonlyMap<string, string>;
|
|
12
20
|
}
|
|
13
21
|
export declare function registerConfigurationSchema(type: IAnyType, metadata: ConfigurationSchemaMetadata): void;
|
|
14
22
|
export declare function getConfigurationSchemaMetadata(type: IAnyType): ConfigurationSchemaMetadata | undefined;
|
|
15
23
|
export declare function isRegisteredConfigurationSchema(type: IAnyType): boolean;
|
|
24
|
+
export interface ConfigurationSchemaUnionMetadata {
|
|
25
|
+
/** the name `ConfigurationSchemaUnion` was given, e.g. `MarkTransform` */
|
|
26
|
+
name: string;
|
|
27
|
+
/** each member schema, keyed by the `type` it answers to */
|
|
28
|
+
members: Record<string, AnyConfigurationSchemaType>;
|
|
29
|
+
}
|
|
30
|
+
export declare function registerConfigurationSchemaUnion(type: IAnyType, metadata: ConfigurationSchemaUnionMetadata): void;
|
|
31
|
+
/**
|
|
32
|
+
* The name and members of a union `ConfigurationSchemaUnion` built, or
|
|
33
|
+
* undefined for any other type — a pluggable element union included.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getConfigurationSchemaUnion(type: IAnyType): ConfigurationSchemaUnionMetadata | undefined;
|
|
16
36
|
/**
|
|
17
37
|
* The slot/sub-schema/constant table for a config (includes slots merged in from
|
|
18
38
|
* `baseConfiguration` at schema construction). Undefined when the argument isn't
|
|
@@ -19,6 +19,17 @@ export function getConfigurationSchemaMetadata(type) {
|
|
|
19
19
|
export function isRegisteredConfigurationSchema(type) {
|
|
20
20
|
return schemaRegistry.has(type);
|
|
21
21
|
}
|
|
22
|
+
const unionRegistry = new WeakMap();
|
|
23
|
+
export function registerConfigurationSchemaUnion(type, metadata) {
|
|
24
|
+
unionRegistry.set(type, metadata);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The name and members of a union `ConfigurationSchemaUnion` built, or
|
|
28
|
+
* undefined for any other type — a pluggable element union included.
|
|
29
|
+
*/
|
|
30
|
+
export function getConfigurationSchemaUnion(type) {
|
|
31
|
+
return unionRegistry.get(type);
|
|
32
|
+
}
|
|
22
33
|
// The three lookups above take a schema *type*; the two below take a live config
|
|
23
34
|
// *node* and make the `getType` hop themselves, which is what every reader
|
|
24
35
|
// actually wants — a node is what they hold. Leaving the hop to the call site is
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MergedConfigurationSchemaOptions } from './configurationSchema.ts';
|
|
1
2
|
import type { ConfigSlotDefinition } from './configurationSlot.ts';
|
|
2
3
|
import type { AnyConfigurationModel, AnyConfigurationSchemaType } from './types.ts';
|
|
3
4
|
/**
|
|
@@ -20,4 +21,6 @@ export declare function isConfigurationSchemaType(thing: unknown): thing is AnyC
|
|
|
20
21
|
*/
|
|
21
22
|
export declare function isConstantEntry(def: unknown): def is string | number;
|
|
22
23
|
export declare function isSlotDefinitionEntry(def: unknown): def is ConfigSlotDefinition;
|
|
24
|
+
/** The prop an explicit or implicit identifier option installs, named `id` when the option is `true`. */
|
|
25
|
+
export declare function identifierName({ explicitIdentifier, implicitIdentifier, }: MergedConfigurationSchemaOptions<any, any>): string | undefined;
|
|
23
26
|
export declare function isConfigurationModel(thing: unknown): thing is AnyConfigurationModel;
|
|
@@ -21,6 +21,11 @@ export function getTypeNamesFromExplicitlyTypedUnion(maybeUnionType) {
|
|
|
21
21
|
if (isUnionType(resolved)) {
|
|
22
22
|
const typeNames = [];
|
|
23
23
|
for (const subType of getUnionSubTypes(resolved)) {
|
|
24
|
+
// the branch a `maybe`-like union adds so the slot can be absent, not
|
|
25
|
+
// a schema — `isConfigurationSchemaType` already skips it the same way
|
|
26
|
+
if (subType.name === 'undefined') {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
24
29
|
const resolvedSub = resolveLateType(subType);
|
|
25
30
|
// a nested union contributes its own names; otherwise the subtype is a
|
|
26
31
|
// single explicitly-typed schema whose name is its default's `type`
|
|
@@ -89,6 +94,11 @@ export function isConstantEntry(def) {
|
|
|
89
94
|
export function isSlotDefinitionEntry(def) {
|
|
90
95
|
return (typeof def === 'object' && def !== null && !isType(def) && 'type' in def);
|
|
91
96
|
}
|
|
97
|
+
/** The prop an explicit or implicit identifier option installs, named `id` when the option is `true`. */
|
|
98
|
+
export function identifierName({ explicitIdentifier, implicitIdentifier, }) {
|
|
99
|
+
const spec = explicitIdentifier || implicitIdentifier;
|
|
100
|
+
return spec ? (typeof spec === 'string' ? spec : 'id') : undefined;
|
|
101
|
+
}
|
|
92
102
|
export function isConfigurationModel(thing) {
|
|
93
103
|
return isStateTreeNode(thing) && isConfigurationSchemaType(getType(thing));
|
|
94
104
|
}
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import type PluginManager from '../PluginManager.ts';
|
|
2
2
|
import type { ConfigSlotDefinition, ConfigSlotType } from './configurationSlot.ts';
|
|
3
3
|
import type { AnyConfigurationModel } from './types.ts';
|
|
4
|
+
import type { IAnyType } from '@jbrowse/mobx-state-tree';
|
|
4
5
|
/**
|
|
5
6
|
* Whether `slotName` on a config node is a slot (vs a nested sub-schema or a
|
|
6
7
|
* string/number constant).
|
|
7
8
|
*/
|
|
8
9
|
export declare function isConfigurationSlot(node: AnyConfigurationModel, slotName: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether `slotName` on a config node is a single nested sub-schema, the kind
|
|
12
|
+
* `setSubschema` replaces whole (not an array or map of them).
|
|
13
|
+
*/
|
|
14
|
+
export declare function isConfigurationSubschema(node: AnyConfigurationModel, slotName: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* What to hand `setSubschema` for a write of `slotName`: `value` itself where
|
|
17
|
+
* the sub-schema is a channel, and the node's own snapshot with `value`'s
|
|
18
|
+
* members over it — recursing into the namespaces inside it — where it is not.
|
|
19
|
+
* `null` resets at any depth of a namespace, the way it resets a slot (ADR-146).
|
|
20
|
+
*
|
|
21
|
+
* **A `shorthand` is what tells the two apart.** A sub-schema that takes a bare
|
|
22
|
+
* string takes one written value, so `{ field: 'biotype' }` after
|
|
23
|
+
* `{ field: 'biotype', domain: [...] }` is a colour or facet with no domain,
|
|
24
|
+
* and a merge would leave the old one standing with no way to clear it. A
|
|
25
|
+
* sub-schema with no shorthand is a namespace of independent settings, where
|
|
26
|
+
* `{ scales: { y: { domainMin: 5 } } }` means "pin the bottom" and used to
|
|
27
|
+
* reset `type` and `autoscale` with it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function mergedSubschemaValue(node: AnyConfigurationModel, slotName: string, value: unknown): {};
|
|
9
30
|
/**
|
|
10
31
|
* Run `node`'s own schema `preProcessSnapshot` over a partial bag of slot
|
|
11
32
|
* values headed for that config.
|
|
@@ -19,6 +40,13 @@ export declare function isConfigurationSlot(node: AnyConfigurationModel, slotNam
|
|
|
19
40
|
* is the same shape they already tolerate.
|
|
20
41
|
*/
|
|
21
42
|
export declare function preProcessSlotValues(node: AnyConfigurationModel, values: Record<string, unknown>): Record<string, unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Why a config of type `schema` cannot hold `value` at `key`, or undefined
|
|
45
|
+
* when it can: the schema's own lift first, then the slot's type, or a
|
|
46
|
+
* sub-schema's lift and checks. Also undefined for a key the schema does not
|
|
47
|
+
* declare, which is a question for its caller.
|
|
48
|
+
*/
|
|
49
|
+
export declare function slotValueRefusal(schema: IAnyType, key: string, value: unknown): string | undefined;
|
|
22
50
|
/**
|
|
23
51
|
* The duck-typed object the config editor's leaf components consume. They never
|
|
24
52
|
* touch MST internals — only this shape (see ColorEditor.test.tsx, which passes
|
|
@@ -32,7 +60,10 @@ export interface SlotFacade {
|
|
|
32
60
|
type: ConfigSlotType;
|
|
33
61
|
contextVariable: string[];
|
|
34
62
|
defaultValue: unknown;
|
|
35
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* enum choices, present only for the enum slot types; a `stringEnumArray`'s
|
|
65
|
+
* are the choices of each entry
|
|
66
|
+
*/
|
|
36
67
|
choices?: string[];
|
|
37
68
|
pluginManager: PluginManager;
|
|
38
69
|
readonly value: unknown;
|
|
@@ -47,9 +78,9 @@ export interface SlotFacade {
|
|
|
47
78
|
}
|
|
48
79
|
/**
|
|
49
80
|
* The vocabulary an enum slot offers, or undefined for any other slot. Reads the
|
|
50
|
-
* author's own `types.enumeration` off `model` —
|
|
51
|
-
*
|
|
52
|
-
*
|
|
81
|
+
* author's own `types.enumeration` off `model` — the enum types are the only
|
|
82
|
+
* ones the editor takes choices from, so a slot typed anything else renders as
|
|
83
|
+
* free text however valid its `model` is.
|
|
53
84
|
*
|
|
54
85
|
* Shared by the config editor's facade below and by
|
|
55
86
|
* `ConfigSlotDefaults.test.ts`, which snapshots every schema's vocabularies:
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { getSnapshot } from '@jbrowse/mobx-state-tree';
|
|
1
|
+
import { getSnapshot, getType, isArrayType, isMapType, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
|
|
2
2
|
import { getEnumerationValues } from '../util/mst-reflection.js';
|
|
3
3
|
import { getEnv } from '../util/mstUtils.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import ConfigSlot, { slotWriteRefusal } from './configurationSlot.js';
|
|
5
|
+
import { getConfigurationSchemaDefinition, getConfigurationSchemaMetadata, getConfigurationSchemaOptions, } from './schemaRegistry.js';
|
|
6
|
+
import { isConfigurationSchemaType, isSlotDefinitionEntry, } from './schemaTypes.js';
|
|
7
|
+
import { preProcessSnapshotWith } from './snapshotPreprocess.js';
|
|
6
8
|
/**
|
|
7
9
|
* The slot's metadata entry, or undefined when `slotName` names a nested
|
|
8
10
|
* sub-schema or a string/number constant rather than a slot.
|
|
@@ -18,6 +20,59 @@ function slotDefinition(node, slotName) {
|
|
|
18
20
|
export function isConfigurationSlot(node, slotName) {
|
|
19
21
|
return !!slotDefinition(node, slotName);
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Whether `slotName` on a config node is a single nested sub-schema, the kind
|
|
25
|
+
* `setSubschema` replaces whole (not an array or map of them).
|
|
26
|
+
*/
|
|
27
|
+
export function isConfigurationSubschema(node, slotName) {
|
|
28
|
+
const def = getConfigurationSchemaDefinition(node)?.[slotName];
|
|
29
|
+
return isConfigurationSchemaType(def) && !isArrayType(def) && !isMapType(def);
|
|
30
|
+
}
|
|
31
|
+
function isPlainObject(v) {
|
|
32
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
33
|
+
}
|
|
34
|
+
function isNamespace(member) {
|
|
35
|
+
const options = isStateTreeNode(member)
|
|
36
|
+
? getConfigurationSchemaOptions(member)
|
|
37
|
+
: undefined;
|
|
38
|
+
return !!options && options.shorthand === undefined;
|
|
39
|
+
}
|
|
40
|
+
// JSON Merge Patch (RFC 7396) over a namespace's snapshot: a `null` member
|
|
41
|
+
// leaves the key out, which a stripDefault snapshot reads as the default
|
|
42
|
+
function mergePatch(namespace, patch) {
|
|
43
|
+
const out = { ...getSnapshot(namespace) };
|
|
44
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
45
|
+
const member = namespace[k];
|
|
46
|
+
if (v === null) {
|
|
47
|
+
delete out[k];
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
out[k] =
|
|
51
|
+
isPlainObject(v) && isNamespace(member) ? mergePatch(member, v) : v;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* What to hand `setSubschema` for a write of `slotName`: `value` itself where
|
|
58
|
+
* the sub-schema is a channel, and the node's own snapshot with `value`'s
|
|
59
|
+
* members over it — recursing into the namespaces inside it — where it is not.
|
|
60
|
+
* `null` resets at any depth of a namespace, the way it resets a slot (ADR-146).
|
|
61
|
+
*
|
|
62
|
+
* **A `shorthand` is what tells the two apart.** A sub-schema that takes a bare
|
|
63
|
+
* string takes one written value, so `{ field: 'biotype' }` after
|
|
64
|
+
* `{ field: 'biotype', domain: [...] }` is a colour or facet with no domain,
|
|
65
|
+
* and a merge would leave the old one standing with no way to clear it. A
|
|
66
|
+
* sub-schema with no shorthand is a namespace of independent settings, where
|
|
67
|
+
* `{ scales: { y: { domainMin: 5 } } }` means "pin the bottom" and used to
|
|
68
|
+
* reset `type` and `autoscale` with it.
|
|
69
|
+
*/
|
|
70
|
+
export function mergedSubschemaValue(node, slotName, value) {
|
|
71
|
+
const existing = node[slotName];
|
|
72
|
+
return isPlainObject(value) && isNamespace(existing)
|
|
73
|
+
? mergePatch(existing, value)
|
|
74
|
+
: (value ?? {});
|
|
75
|
+
}
|
|
21
76
|
/**
|
|
22
77
|
* Run `node`'s own schema `preProcessSnapshot` over a partial bag of slot
|
|
23
78
|
* values headed for that config.
|
|
@@ -31,14 +86,43 @@ export function isConfigurationSlot(node, slotName) {
|
|
|
31
86
|
* is the same shape they already tolerate.
|
|
32
87
|
*/
|
|
33
88
|
export function preProcessSlotValues(node, values) {
|
|
34
|
-
const
|
|
35
|
-
return
|
|
89
|
+
const schema = getConfigurationSchemaMetadata(getType(node));
|
|
90
|
+
return schema ? preProcessSnapshotWith(schema, values) : values;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Why a config of type `schema` cannot hold `value` at `key`, or undefined
|
|
94
|
+
* when it can: the schema's own lift first, then the slot's type, or a
|
|
95
|
+
* sub-schema's lift and checks. Also undefined for a key the schema does not
|
|
96
|
+
* declare, which is a question for its caller.
|
|
97
|
+
*/
|
|
98
|
+
export function slotValueRefusal(schema, key, value) {
|
|
99
|
+
const meta = getConfigurationSchemaMetadata(schema);
|
|
100
|
+
const entry = meta?.definition[key];
|
|
101
|
+
if (!meta || entry === undefined) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const subSchema = isConfigurationSchemaType(entry)
|
|
105
|
+
? entry
|
|
106
|
+
: undefined;
|
|
107
|
+
try {
|
|
108
|
+
const lifted = preProcessSnapshotWith(meta, { [key]: value })[key];
|
|
109
|
+
if (subSchema) {
|
|
110
|
+
subSchema.create(lifted);
|
|
111
|
+
}
|
|
112
|
+
else if (isSlotDefinitionEntry(entry) && !ConfigSlot(entry).is(lifted)) {
|
|
113
|
+
return slotWriteRefusal(`${meta.name}.${key}`, entry.type, value);
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
return e instanceof Error ? e.message : String(e);
|
|
119
|
+
}
|
|
36
120
|
}
|
|
37
121
|
/**
|
|
38
122
|
* The vocabulary an enum slot offers, or undefined for any other slot. Reads the
|
|
39
|
-
* author's own `types.enumeration` off `model` —
|
|
40
|
-
*
|
|
41
|
-
*
|
|
123
|
+
* author's own `types.enumeration` off `model` — the enum types are the only
|
|
124
|
+
* ones the editor takes choices from, so a slot typed anything else renders as
|
|
125
|
+
* free text however valid its `model` is.
|
|
42
126
|
*
|
|
43
127
|
* Shared by the config editor's facade below and by
|
|
44
128
|
* `ConfigSlotDefaults.test.ts`, which snapshots every schema's vocabularies:
|
|
@@ -47,7 +131,10 @@ export function preProcessSlotValues(node, values) {
|
|
|
47
131
|
*/
|
|
48
132
|
export function slotChoices(def) {
|
|
49
133
|
const { type, model } = def;
|
|
50
|
-
return (type === 'stringEnum' ||
|
|
134
|
+
return (type === 'stringEnum' ||
|
|
135
|
+
type === 'maybeStringEnum' ||
|
|
136
|
+
type === 'stringEnumArray') &&
|
|
137
|
+
model
|
|
51
138
|
? getEnumerationValues(model)
|
|
52
139
|
: undefined;
|
|
53
140
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ConfigurationSchemaMetadata } from './schemaRegistry.ts';
|
|
2
|
+
import type { IAnyType } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
export declare function listed(keys: readonly string[]): string;
|
|
4
|
+
/**
|
|
5
|
+
* The bare value a schema's `shorthand` lifts: a number where the slot it
|
|
6
|
+
* names holds one (`rules: [7.3]`), a string otherwise (`color: 'red'`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function shorthandForm({ definition, options, }: ConfigurationSchemaMetadata): 'string' | 'number' | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* What a schema does to every snapshot on its way in, whichever door it
|
|
11
|
+
* arrives by (`create`, `applySnapshot`, `setSubschema`, a settings bag): a
|
|
12
|
+
* bare string or number lifts into the declared `shorthand` slot, beside any
|
|
13
|
+
* `shorthandWith` slots, and `null` into the empty object that clears it; a
|
|
14
|
+
* `null` member reads as unset, except in a frozen-family slot, which stores
|
|
15
|
+
* it; a `closed` schema refuses a key it does not declare, then the schema's
|
|
16
|
+
* own `preProcessSnapshot` runs, and a `jexl:` callback in a slot declaring no
|
|
17
|
+
* `contextVariable` is refused. A bare value the shorthand does not lift
|
|
18
|
+
* passes through for MST to refuse.
|
|
19
|
+
*/
|
|
20
|
+
export declare function preProcessSnapshotWith(schema: ConfigurationSchemaMetadata, snapshot: unknown): Record<string, unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* #api core/configuration
|
|
23
|
+
* A snapshot as `type` admits it: the same lift and checks `type.create`
|
|
24
|
+
* applies, so a dialog or a validator refuses exactly what a config file
|
|
25
|
+
* cannot hold. Throws what the schema's `preProcessSnapshot` throws.
|
|
26
|
+
*/
|
|
27
|
+
export declare function preProcessConfigSnapshot(type: IAnyType, snapshot: unknown): Record<string, unknown>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { isJexl } from '../util/jexlStrings.js';
|
|
2
|
+
import { slotWriteRefusal } from './configurationSlot.js';
|
|
3
|
+
import { getConfigurationSchemaMetadata } from './schemaRegistry.js';
|
|
4
|
+
import { identifierName, isConstantEntry, isSlotDefinitionEntry, } from './schemaTypes.js';
|
|
5
|
+
// the keys a config file may annotate any object with, as the JSON schema's
|
|
6
|
+
// `patternProperties` admits them
|
|
7
|
+
const COMMENT_KEY = /^_+comment/;
|
|
8
|
+
export function listed(keys) {
|
|
9
|
+
return keys.length > 1
|
|
10
|
+
? `${keys.slice(0, -1).join(', ')} and ${keys.at(-1)}`
|
|
11
|
+
: (keys[0] ?? 'nothing');
|
|
12
|
+
}
|
|
13
|
+
function refuseUndeclaredKeys({ name, definition, options }, snapshot) {
|
|
14
|
+
const id = identifierName(options);
|
|
15
|
+
const declared = [
|
|
16
|
+
...Object.keys(definition).filter(key => !isConstantEntry(definition[key])),
|
|
17
|
+
...(options.explicitlyTyped ? ['type'] : []),
|
|
18
|
+
...(id ? [id] : []),
|
|
19
|
+
];
|
|
20
|
+
const unknown = typeof snapshot === 'string'
|
|
21
|
+
? [JSON.stringify(snapshot)]
|
|
22
|
+
: Object.keys(snapshot ?? {}).filter(key => !declared.includes(key) && !COMMENT_KEY.test(key));
|
|
23
|
+
if (unknown.length > 0) {
|
|
24
|
+
throw new Error(`${name} takes ${listed(declared)}, not ${unknown.join(', ')}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Checked here as well as by each slot's MST type because this runs on every
|
|
28
|
+
// create, where MST's own check is off in a build that has not enabled it
|
|
29
|
+
function refuseCallbacks({ name, takesNoCallback }, snapshot) {
|
|
30
|
+
if (typeof snapshot === 'object' && snapshot !== null) {
|
|
31
|
+
for (const key in snapshot) {
|
|
32
|
+
const type = takesNoCallback.get(key);
|
|
33
|
+
const value = snapshot[key];
|
|
34
|
+
if (type !== undefined && isJexl(value)) {
|
|
35
|
+
throw new Error(slotWriteRefusal(`${name}.${key}`, type, value));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const NUMBER_SLOT_TYPES = new Set(['number', 'integer', 'maybeNumber']);
|
|
41
|
+
/**
|
|
42
|
+
* The bare value a schema's `shorthand` lifts: a number where the slot it
|
|
43
|
+
* names holds one (`rules: [7.3]`), a string otherwise (`color: 'red'`).
|
|
44
|
+
*/
|
|
45
|
+
export function shorthandForm({ definition, options, }) {
|
|
46
|
+
const { shorthand } = options;
|
|
47
|
+
const entry = shorthand === undefined ? undefined : definition[shorthand];
|
|
48
|
+
return shorthand === undefined
|
|
49
|
+
? undefined
|
|
50
|
+
: isSlotDefinitionEntry(entry) && NUMBER_SLOT_TYPES.has(entry.type)
|
|
51
|
+
? 'number'
|
|
52
|
+
: 'string';
|
|
53
|
+
}
|
|
54
|
+
// ADR-146's reset, on the snapshot path: the member keeps its key, so a
|
|
55
|
+
// settings bag still resets it, and `create` reads `undefined` as the default
|
|
56
|
+
function nullMembersAsUnset(snapshot, storesNull) {
|
|
57
|
+
let out = snapshot;
|
|
58
|
+
for (const key in snapshot) {
|
|
59
|
+
if (snapshot[key] === null && !storesNull.has(key)) {
|
|
60
|
+
out = out === snapshot ? { ...snapshot } : out;
|
|
61
|
+
out[key] = undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* What a schema does to every snapshot on its way in, whichever door it
|
|
68
|
+
* arrives by (`create`, `applySnapshot`, `setSubschema`, a settings bag): a
|
|
69
|
+
* bare string or number lifts into the declared `shorthand` slot, beside any
|
|
70
|
+
* `shorthandWith` slots, and `null` into the empty object that clears it; a
|
|
71
|
+
* `null` member reads as unset, except in a frozen-family slot, which stores
|
|
72
|
+
* it; a `closed` schema refuses a key it does not declare, then the schema's
|
|
73
|
+
* own `preProcessSnapshot` runs, and a `jexl:` callback in a slot declaring no
|
|
74
|
+
* `contextVariable` is refused. A bare value the shorthand does not lift
|
|
75
|
+
* passes through for MST to refuse.
|
|
76
|
+
*/
|
|
77
|
+
export function preProcessSnapshotWith(schema, snapshot) {
|
|
78
|
+
const { shorthand, shorthandWith, closed, preProcessSnapshot } = schema.options;
|
|
79
|
+
const lifted = snapshot === null
|
|
80
|
+
? {}
|
|
81
|
+
: shorthand !== undefined && typeof snapshot === shorthandForm(schema)
|
|
82
|
+
? { ...shorthandWith, [shorthand]: snapshot }
|
|
83
|
+
: nullMembersAsUnset(snapshot, schema.storesNull);
|
|
84
|
+
if (closed) {
|
|
85
|
+
refuseUndeclaredKeys(schema, lifted);
|
|
86
|
+
}
|
|
87
|
+
const processed = preProcessSnapshot ? preProcessSnapshot(lifted) : lifted;
|
|
88
|
+
refuseCallbacks(schema, processed);
|
|
89
|
+
return processed;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* #api core/configuration
|
|
93
|
+
* A snapshot as `type` admits it: the same lift and checks `type.create`
|
|
94
|
+
* applies, so a dialog or a validator refuses exactly what a config file
|
|
95
|
+
* cannot hold. Throws what the schema's `preProcessSnapshot` throws.
|
|
96
|
+
*/
|
|
97
|
+
export function preProcessConfigSnapshot(type, snapshot) {
|
|
98
|
+
const schema = getConfigurationSchemaMetadata(type);
|
|
99
|
+
return schema
|
|
100
|
+
? preProcessSnapshotWith(schema, snapshot)
|
|
101
|
+
: snapshot;
|
|
102
|
+
}
|