@jbrowse/core 2.13.1 → 2.15.0
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/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +2 -2
- package/BaseFeatureWidget/BaseFeatureDetail/BasicValue.js +1 -1
- package/BaseFeatureWidget/BaseFeatureDetail/DataGridDetails.js +3 -1
- package/BaseFeatureWidget/BaseFeatureDetail/index.js +23 -51
- package/BaseFeatureWidget/BaseFeatureDetail/util.js +1 -1
- package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.js +11 -5
- package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +1 -1
- package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.js +11 -7
- package/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.js +1 -1
- package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/HelpDialog.js +6 -2
- package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceDialog.js +11 -5
- package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceFeatureMenu.js +15 -5
- package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceTypeSelector.js +4 -2
- package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SettingsDialog.js +15 -5
- package/BaseFeatureWidget/SequenceFeatureDetails/hooks.js +2 -2
- package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDNASequence.js +2 -2
- package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/SequenceDisplay.js +5 -3
- package/BaseFeatureWidget/stateModelFactory.js +0 -2
- package/PluginLoader.d.ts +1 -2
- package/PluginLoader.js +16 -6
- package/PluginManager.d.ts +13 -13
- package/PluginManager.js +7 -2
- package/ReExports/modules.js +2 -11
- package/assemblyManager/assembly.d.ts +18 -12
- package/assemblyManager/assembly.js +75 -52
- package/assemblyManager/assemblyConfigSchema.d.ts +9 -7
- package/assemblyManager/assemblyConfigSchema.js +15 -16
- package/assemblyManager/assemblyManager.d.ts +109 -81
- package/assemblyManager/assemblyManager.js +3 -6
- package/configuration/configurationSchema.d.ts +1 -1
- package/configuration/configurationSchema.js +1 -2
- package/configuration/configurationSlot.js +7 -8
- package/configuration/util.js +0 -7
- package/data_adapters/BaseAdapter/BaseAdapter.d.ts +2 -1
- package/data_adapters/BaseAdapter/BaseAdapter.js +2 -1
- package/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +6 -6
- package/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +6 -6
- package/data_adapters/BaseAdapter/BaseRefNameAliasAdapter.d.ts +1 -0
- package/data_adapters/CytobandAdapter/CytobandAdapter.d.ts +0 -1
- package/data_adapters/CytobandAdapter/CytobandAdapter.js +4 -8
- package/data_adapters/dataAdapterCache.d.ts +9 -6
- package/data_adapters/dataAdapterCache.js +16 -22
- package/package.json +5 -5
- package/pluggableElementTypes/AddTrackWorkflowType.js +0 -6
- package/pluggableElementTypes/ConnectionType.js +0 -6
- package/pluggableElementTypes/DisplayType.js +0 -20
- package/pluggableElementTypes/InternetAccountType.js +0 -11
- package/pluggableElementTypes/RpcMethodType.d.ts +1 -1
- package/pluggableElementTypes/TextSearchAdapterType.js +0 -3
- package/pluggableElementTypes/TrackType.js +0 -11
- package/pluggableElementTypes/ViewType.js +0 -6
- package/pluggableElementTypes/WidgetType.js +0 -6
- package/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +4 -3
- package/pluggableElementTypes/models/BaseConnectionModelFactory.js +1 -3
- package/pluggableElementTypes/models/BaseDisplayModel.d.ts +4 -5
- package/pluggableElementTypes/models/BaseDisplayModel.js +6 -14
- package/pluggableElementTypes/models/BaseTrackModel.js +8 -5
- package/pluggableElementTypes/models/InternetAccountModel.d.ts +1 -1
- package/pluggableElementTypes/models/InternetAccountModel.js +19 -13
- package/pluggableElementTypes/models/baseTrackConfig.js +2 -5
- package/pluggableElementTypes/renderers/BoxRendererType.d.ts +10 -4
- package/pluggableElementTypes/renderers/BoxRendererType.js +10 -26
- package/pluggableElementTypes/renderers/CircularChordRendererType.d.ts +1 -1
- package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.d.ts +9 -12
- package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.js +12 -19
- package/pluggableElementTypes/renderers/FeatureRendererType.d.ts +5 -5
- package/pluggableElementTypes/renderers/FeatureRendererType.js +6 -13
- package/pluggableElementTypes/renderers/RendererType.js +0 -10
- package/pluggableElementTypes/renderers/RpcRenderedSvgGroup.d.ts +1 -1
- package/pluggableElementTypes/renderers/RpcRenderedSvgGroup.js +11 -9
- package/pluggableElementTypes/renderers/ServerSideRenderedContent.js +14 -14
- package/pluggableElementTypes/renderers/ServerSideRendererType.d.ts +4 -4
- package/pluggableElementTypes/renderers/ServerSideRendererType.js +7 -5
- package/pluggableElementTypes/renderers/util/serializableFilterChain.js +0 -1
- package/rpc/BaseRpcDriver.d.ts +1 -1
- package/rpc/BaseRpcDriver.js +12 -11
- package/rpc/MainThreadRpcDriver.d.ts +2 -2
- package/rpc/MainThreadRpcDriver.js +3 -0
- package/rpc/RpcManager.d.ts +1 -1
- package/rpc/RpcManager.js +11 -8
- package/rpc/configSchema.js +0 -1
- package/rpc/methods/CoreFreeResources.d.ts +2 -2
- package/rpc/methods/CoreGetFeatureDensityStats.d.ts +2 -2
- package/rpc/methods/CoreGetFeatureDetails.d.ts +1 -1
- package/rpc/methods/CoreGetFeatureDetails.js +3 -3
- package/rpc/methods/CoreGetFeatures.d.ts +1 -1
- package/rpc/methods/CoreGetFileInfo.d.ts +1 -1
- package/rpc/methods/CoreGetMetadata.d.ts +1 -1
- package/rpc/methods/CoreGetRefNames.d.ts +1 -1
- package/rpc/methods/util.d.ts +2 -2
- package/rpc/methods/util.js +0 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/ui/AssemblySelector.js +3 -1
- package/ui/CascadingMenu.js +2 -1
- package/ui/CascadingMenuButton.js +3 -1
- package/ui/ColorPicker.js +14 -4
- package/ui/DropDownMenu.js +3 -1
- package/ui/EditableTypography.js +6 -2
- package/ui/ErrorMessage.d.ts +2 -2
- package/ui/ErrorMessage.js +37 -20
- package/ui/ErrorMessageStackTraceDialog.js +11 -9
- package/ui/FactoryResetDialog.d.ts +1 -1
- package/ui/FactoryResetDialog.js +9 -3
- package/ui/FatalErrorDialog.js +9 -3
- package/ui/FileSelector/FileSelector.js +8 -4
- package/ui/FileSelector/LocalFileChooser.js +7 -6
- package/ui/LoadingEllipses.js +1 -1
- package/ui/Menu.d.ts +4 -4
- package/ui/Menu.js +6 -4
- package/ui/MenuButton.js +6 -2
- package/ui/PrerenderedCanvas.js +8 -5
- package/ui/RedErrorMessageBox.js +13 -8
- package/ui/ResizeHandle.d.ts +1 -1
- package/ui/ReturnToImportFormDialog.js +3 -1
- package/ui/SanitizedHTML.js +1 -3
- package/ui/SnackbarModel.d.ts +12 -1
- package/ui/SnackbarModel.js +19 -3
- package/ui/theme.js +10 -7
- package/util/Base1DViewModel.js +3 -1
- package/util/QuickLRU.js +8 -8
- package/util/TimeTraveller.js +12 -4
- package/util/aborting.js +1 -1
- package/util/analytics.js +0 -1
- package/util/blockTypes.js +5 -9
- package/util/calculateStaticBlocks.d.ts +1 -1
- package/util/compositeMap.js +2 -2
- package/util/idMaker.js +0 -1
- package/util/index.d.ts +9 -8
- package/util/index.js +92 -51
- package/util/io/RemoteFileWithRangeCache.js +1 -3
- package/util/io/index.js +3 -5
- package/util/jexlStrings.js +5 -8
- package/util/layouts/GranularRectLayout.js +1 -4
- package/util/layouts/SceneGraph.d.ts +1 -1
- package/util/layouts/SceneGraph.js +2 -6
- package/util/map-obj.js +15 -7
- package/util/mst-reflection.js +1 -2
- package/util/nanoid.js +9 -8
- package/util/offscreenCanvasPonyfill.d.ts +1 -1
- package/util/offscreenCanvasPonyfill.js +7 -10
- package/util/offscreenCanvasUtils.d.ts +1 -1
- package/util/offscreenCanvasUtils.js +1 -3
- package/util/rxjs.js +5 -5
- package/util/simpleFeature.d.ts +2 -3
- package/util/simpleFeature.js +9 -12
- package/util/stats.js +3 -1
- package/util/tracks.d.ts +4 -2
- package/util/tracks.js +10 -11
- package/util/types/index.d.ts +5 -5
- package/util/types/index.js +8 -1
- package/util/types/mst.js +1 -0
- package/util/when.js +7 -2
|
@@ -36,8 +36,7 @@ class LayoutSession {
|
|
|
36
36
|
* @returns true if the given layout is a valid one to use for this session
|
|
37
37
|
*/
|
|
38
38
|
cachedLayoutIsValid(cachedLayout) {
|
|
39
|
-
return (cachedLayout &&
|
|
40
|
-
cachedLayout.layout.subLayoutConstructorArgs.pitchX === this.bpPerPx &&
|
|
39
|
+
return (cachedLayout.layout.subLayoutConstructorArgs.pitchX === this.bpPerPx &&
|
|
41
40
|
(0, fast_deep_equal_1.default)((0, configuration_1.readConfObject)(this.config), cachedLayout.config) &&
|
|
42
41
|
(0, fast_deep_equal_1.default)(this.filters, cachedLayout.filters));
|
|
43
42
|
}
|
|
@@ -67,18 +66,9 @@ class BoxRendererType extends FeatureRendererType_1.default {
|
|
|
67
66
|
session.update(props);
|
|
68
67
|
return session;
|
|
69
68
|
}
|
|
70
|
-
// expands region for glyphs to use
|
|
71
69
|
getExpandedRegion(region, renderArgs) {
|
|
72
|
-
if (!region) {
|
|
73
|
-
return region;
|
|
74
|
-
}
|
|
75
70
|
const { bpPerPx, config } = renderArgs;
|
|
76
|
-
const maxFeatureGlyphExpansion = config
|
|
77
|
-
? 0
|
|
78
|
-
: (0, configuration_1.readConfObject)(config, 'maxFeatureGlyphExpansion');
|
|
79
|
-
if (!maxFeatureGlyphExpansion) {
|
|
80
|
-
return region;
|
|
81
|
-
}
|
|
71
|
+
const maxFeatureGlyphExpansion = (0, configuration_1.readConfObject)(config, 'maxFeatureGlyphExpansion') || 0;
|
|
82
72
|
const bpExpansion = Math.round(maxFeatureGlyphExpansion * bpPerPx);
|
|
83
73
|
return {
|
|
84
74
|
...region,
|
|
@@ -92,16 +82,12 @@ class BoxRendererType extends FeatureRendererType_1.default {
|
|
|
92
82
|
async freeResourcesInClient(rpcManager, args) {
|
|
93
83
|
const { regions } = args;
|
|
94
84
|
const key = (0, util_1.getLayoutId)(args);
|
|
95
|
-
let freed = 0;
|
|
96
85
|
const session = this.sessions[key];
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
if (session && regions) {
|
|
102
|
-
session.layout.discardRange(regions[0].refName, regions[0].start, regions[0].end);
|
|
86
|
+
if (session) {
|
|
87
|
+
const region = regions[0];
|
|
88
|
+
session.layout.discardRange(region.refName, region.start, region.end);
|
|
103
89
|
}
|
|
104
|
-
return
|
|
90
|
+
return await super.freeResourcesInClient(rpcManager, args);
|
|
105
91
|
}
|
|
106
92
|
deserializeLayoutInClient(json) {
|
|
107
93
|
return new PrecomputedLayout_1.default(json);
|
|
@@ -117,13 +103,11 @@ class BoxRendererType extends FeatureRendererType_1.default {
|
|
|
117
103
|
}
|
|
118
104
|
serializeResultsInWorker(results, args) {
|
|
119
105
|
const serialized = super.serializeResultsInWorker(results, args);
|
|
120
|
-
const
|
|
106
|
+
const region = args.regions[0];
|
|
121
107
|
serialized.layout = results.layout.serializeRegion(this.getExpandedRegion(region, args));
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
}
|
|
108
|
+
serialized.features = serialized.features.filter(f => {
|
|
109
|
+
return Boolean(serialized.layout.rectangles[f.uniqueId]);
|
|
110
|
+
});
|
|
127
111
|
serialized.maxHeightReached = serialized.layout.maxHeightReached;
|
|
128
112
|
return serialized;
|
|
129
113
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { Feature } from '../../util/simpleFeature';
|
|
2
|
+
import { Region } from '../../util/types';
|
|
2
3
|
import ServerSideRenderer, { RenderArgs as ServerSideRenderArgs, RenderArgsSerialized as ServerSideRenderArgsSerialized, RenderArgsDeserialized as ServerSideRenderArgsDeserialized, ResultsSerialized as ServerSideResultsSerialized, ResultsDeserialized as ServerSideResultsDeserialized } from './ServerSideRendererType';
|
|
3
4
|
import RpcManager from '../../rpc/RpcManager';
|
|
5
|
+
import { AnyConfigurationModel } from '../../configuration';
|
|
4
6
|
export interface RenderArgs extends ServerSideRenderArgs {
|
|
5
|
-
displayModel: {};
|
|
6
7
|
blockKey: string;
|
|
7
8
|
}
|
|
8
9
|
export interface RenderArgsSerialized extends ServerSideRenderArgsSerialized {
|
|
9
|
-
displayModel: {};
|
|
10
10
|
blockKey: string;
|
|
11
11
|
}
|
|
12
12
|
export interface RenderArgsDeserialized extends ServerSideRenderArgsDeserialized {
|
|
13
|
-
displayModel: {};
|
|
14
13
|
blockKey: string;
|
|
15
14
|
}
|
|
16
15
|
export type ResultsSerialized = ServerSideResultsSerialized;
|
|
@@ -25,14 +24,8 @@ export interface ResultsSerializedSvgExport extends ResultsSerialized {
|
|
|
25
24
|
}
|
|
26
25
|
export default class ComparativeServerSideRenderer extends ServerSideRenderer {
|
|
27
26
|
/**
|
|
28
|
-
* directly modifies the render arguments to prepare
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* the base class replaces the `displayModel` param
|
|
32
|
-
* (which on the client is a MST model) with a stub
|
|
33
|
-
* that only contains the `selectedFeature`, since
|
|
34
|
-
* this is the only part of the track model that most
|
|
35
|
-
* renderers read.
|
|
27
|
+
* directly modifies the render arguments to prepare them to be serialized
|
|
28
|
+
* and sent to the worker.
|
|
36
29
|
*
|
|
37
30
|
* @param args - the arguments passed to render
|
|
38
31
|
* @returns the same object
|
|
@@ -51,6 +44,10 @@ export default class ComparativeServerSideRenderer extends ServerSideRenderer {
|
|
|
51
44
|
* @returns true if this feature passes all configured filters
|
|
52
45
|
*/
|
|
53
46
|
featurePassesFilters(renderArgs: RenderArgsDeserialized, feature: Feature): boolean;
|
|
54
|
-
getFeatures(renderArgs:
|
|
47
|
+
getFeatures(renderArgs: {
|
|
48
|
+
regions: Region[];
|
|
49
|
+
sessionId: string;
|
|
50
|
+
adapterConfig: AnyConfigurationModel;
|
|
51
|
+
}): Promise<Feature[]>;
|
|
55
52
|
}
|
|
56
53
|
export { type RenderResults } from './ServerSideRendererType';
|
|
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
6
|
const operators_1 = require("rxjs/operators");
|
|
8
7
|
const ServerSideRendererType_1 = __importDefault(require("./ServerSideRendererType"));
|
|
9
8
|
const dataAdapterCache_1 = require("../../data_adapters/dataAdapterCache");
|
|
@@ -14,14 +13,8 @@ function isSvgExport(e) {
|
|
|
14
13
|
}
|
|
15
14
|
class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
|
|
16
15
|
/**
|
|
17
|
-
* directly modifies the render arguments to prepare
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* the base class replaces the `displayModel` param
|
|
21
|
-
* (which on the client is a MST model) with a stub
|
|
22
|
-
* that only contains the `selectedFeature`, since
|
|
23
|
-
* this is the only part of the track model that most
|
|
24
|
-
* renderers read.
|
|
16
|
+
* directly modifies the render arguments to prepare them to be serialized
|
|
17
|
+
* and sent to the worker.
|
|
25
18
|
*
|
|
26
19
|
* @param args - the arguments passed to render
|
|
27
20
|
* @returns the same object
|
|
@@ -32,14 +25,17 @@ class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
|
|
|
32
25
|
serializeArgsInClient(args) {
|
|
33
26
|
const deserializedArgs = {
|
|
34
27
|
...args,
|
|
35
|
-
displayModel:
|
|
28
|
+
displayModel: undefined,
|
|
36
29
|
};
|
|
37
30
|
return super.serializeArgsInClient(deserializedArgs);
|
|
38
31
|
}
|
|
39
32
|
// deserialize some of the results that came back from the worker
|
|
40
33
|
deserializeResultsInClient(result, args) {
|
|
41
34
|
const deserialized = super.deserializeResultsInClient(result, args);
|
|
42
|
-
return {
|
|
35
|
+
return {
|
|
36
|
+
...deserialized,
|
|
37
|
+
blockKey: args.blockKey,
|
|
38
|
+
};
|
|
43
39
|
}
|
|
44
40
|
/**
|
|
45
41
|
* Render method called on the client. Serializes args, then
|
|
@@ -49,7 +45,7 @@ class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
|
|
|
49
45
|
const results = (await rpcManager.call(args.sessionId, 'ComparativeRender', args));
|
|
50
46
|
if (isSvgExport(results)) {
|
|
51
47
|
results.html = await (0, util_1.getSerializedSvg)(results);
|
|
52
|
-
|
|
48
|
+
results.reactElement = undefined;
|
|
53
49
|
}
|
|
54
50
|
return results;
|
|
55
51
|
}
|
|
@@ -65,13 +61,8 @@ class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
|
|
|
65
61
|
}
|
|
66
62
|
async getFeatures(renderArgs) {
|
|
67
63
|
const pm = this.pluginManager;
|
|
68
|
-
const { sessionId, adapterConfig } = renderArgs;
|
|
64
|
+
const { regions, sessionId, adapterConfig } = renderArgs;
|
|
69
65
|
const { dataAdapter } = await (0, dataAdapterCache_1.getAdapter)(pm, sessionId, adapterConfig);
|
|
70
|
-
const regions = renderArgs.regions;
|
|
71
|
-
if (!regions || regions.length === 0) {
|
|
72
|
-
console.warn('no regions supplied to comparative renderer');
|
|
73
|
-
return [];
|
|
74
|
-
}
|
|
75
66
|
const requestRegions = regions.map(r => {
|
|
76
67
|
// make sure the requested region's start and end are integers, if
|
|
77
68
|
// there is a region specification.
|
|
@@ -87,7 +78,9 @@ class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
|
|
|
87
78
|
// note that getFeaturesInMultipleRegions does not do glyph expansion
|
|
88
79
|
const res = await (0, rxjs_1.firstValueFrom)(dataAdapter
|
|
89
80
|
.getFeaturesInMultipleRegions(requestRegions, renderArgs)
|
|
90
|
-
.pipe(
|
|
81
|
+
.pipe(
|
|
82
|
+
// @ts-expect-error
|
|
83
|
+
(0, operators_1.filter)(f => this.featurePassesFilters(renderArgs, f)), (0, operators_1.toArray)()));
|
|
91
84
|
// dedupe needed xref https://github.com/GMOD/jbrowse-components/pull/3404/
|
|
92
85
|
return (0, util_1.dedupe)(res, f => f.id());
|
|
93
86
|
}
|
|
@@ -3,7 +3,7 @@ import { AugmentedRegion as Region } from '../../util/types';
|
|
|
3
3
|
import ServerSideRendererType, { RenderArgs as ServerSideRenderArgs, RenderArgsSerialized as ServerSideRenderArgsSerialized, RenderArgsDeserialized as ServerSideRenderArgsDeserialized, RenderResults as ServerSideRenderResults, ResultsDeserialized as ServerSideResultsDeserialized, ResultsSerialized as ServerSideResultsSerialized } from './ServerSideRendererType';
|
|
4
4
|
import { AnyConfigurationModel } from '../../configuration';
|
|
5
5
|
export interface RenderArgs extends ServerSideRenderArgs {
|
|
6
|
-
displayModel
|
|
6
|
+
displayModel?: {
|
|
7
7
|
id: string;
|
|
8
8
|
selectedFeatureId?: string;
|
|
9
9
|
};
|
|
@@ -11,7 +11,7 @@ export interface RenderArgs extends ServerSideRenderArgs {
|
|
|
11
11
|
blockKey: string;
|
|
12
12
|
}
|
|
13
13
|
export interface RenderArgsSerialized extends ServerSideRenderArgsSerialized {
|
|
14
|
-
displayModel
|
|
14
|
+
displayModel?: {
|
|
15
15
|
id: string;
|
|
16
16
|
selectedFeatureId?: string;
|
|
17
17
|
};
|
|
@@ -40,9 +40,9 @@ export interface ResultsDeserialized extends ServerSideResultsDeserialized {
|
|
|
40
40
|
export default class FeatureRendererType extends ServerSideRendererType {
|
|
41
41
|
/**
|
|
42
42
|
* replaces the `displayModel` param (which on the client is a MST model)
|
|
43
|
-
* with a stub that only contains the `selectedFeature`, since this is the
|
|
44
|
-
* part of the track model that most renderers read. also serializes the
|
|
45
|
-
* and regions to JSON from MST objects.
|
|
43
|
+
* with a stub that only contains the `selectedFeature`, since this is the
|
|
44
|
+
* only part of the track model that most renderers read. also serializes the
|
|
45
|
+
* config and regions to JSON from MST objects.
|
|
46
46
|
*
|
|
47
47
|
* @param args - the arguments passed to render
|
|
48
48
|
*/
|
|
@@ -15,20 +15,17 @@ const BaseAdapter_1 = require("../../data_adapters/BaseAdapter");
|
|
|
15
15
|
class FeatureRendererType extends ServerSideRendererType_1.default {
|
|
16
16
|
/**
|
|
17
17
|
* replaces the `displayModel` param (which on the client is a MST model)
|
|
18
|
-
* with a stub that only contains the `selectedFeature`, since this is the
|
|
19
|
-
* part of the track model that most renderers read. also serializes the
|
|
20
|
-
* and regions to JSON from MST objects.
|
|
18
|
+
* with a stub that only contains the `selectedFeature`, since this is the
|
|
19
|
+
* only part of the track model that most renderers read. also serializes the
|
|
20
|
+
* config and regions to JSON from MST objects.
|
|
21
21
|
*
|
|
22
22
|
* @param args - the arguments passed to render
|
|
23
23
|
*/
|
|
24
24
|
serializeArgsInClient(args) {
|
|
25
|
-
const {
|
|
25
|
+
const { regions } = args;
|
|
26
26
|
const serializedArgs = {
|
|
27
27
|
...args,
|
|
28
|
-
displayModel:
|
|
29
|
-
id: displayModel.id,
|
|
30
|
-
selectedFeatureId: displayModel.selectedFeatureId,
|
|
31
|
-
},
|
|
28
|
+
displayModel: undefined,
|
|
32
29
|
regions: (0, clone_1.default)(regions),
|
|
33
30
|
};
|
|
34
31
|
return super.serializeArgsInClient(serializedArgs);
|
|
@@ -88,13 +85,9 @@ class FeatureRendererType extends ServerSideRendererType_1.default {
|
|
|
88
85
|
if (!(0, BaseAdapter_1.isFeatureAdapter)(dataAdapter)) {
|
|
89
86
|
throw new Error('Adapter does not support retrieving features');
|
|
90
87
|
}
|
|
91
|
-
const features = new Map();
|
|
92
|
-
if (!regions || regions.length === 0) {
|
|
93
|
-
return features;
|
|
94
|
-
}
|
|
95
88
|
// make sure the requested region's start and end are integers, if
|
|
96
89
|
// there is a region specification.
|
|
97
|
-
const requestRegions = regions.map(
|
|
90
|
+
const requestRegions = regions.map(r => {
|
|
98
91
|
const requestRegion = { ...r };
|
|
99
92
|
if (requestRegion.start) {
|
|
100
93
|
requestRegion.start = Math.floor(requestRegion.start);
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
|
-
const mst_reflection_1 = require("../../util/mst-reflection");
|
|
8
7
|
const PluggableElementBase_1 = __importDefault(require("../PluggableElementBase"));
|
|
9
8
|
class RendererType extends PluggableElementBase_1.default {
|
|
10
9
|
constructor(stuff) {
|
|
@@ -13,15 +12,6 @@ class RendererType extends PluggableElementBase_1.default {
|
|
|
13
12
|
this.ReactComponent = stuff.ReactComponent;
|
|
14
13
|
this.configSchema = stuff.configSchema;
|
|
15
14
|
this.pluginManager = stuff.pluginManager;
|
|
16
|
-
if (!this.ReactComponent) {
|
|
17
|
-
throw new Error(`no ReactComponent defined for renderer ${this.name}`);
|
|
18
|
-
}
|
|
19
|
-
if (!(0, mst_reflection_1.getDefaultValue)(this.configSchema).type) {
|
|
20
|
-
throw new Error(`${this.name} config schema ${this.configSchema.name} is not explicitlyTyped`);
|
|
21
|
-
}
|
|
22
|
-
if (!this.pluginManager) {
|
|
23
|
-
throw new Error(`no plugin manager defined for renderer ${this.name}`);
|
|
24
|
-
}
|
|
25
15
|
}
|
|
26
16
|
async render(props) {
|
|
27
17
|
return {
|
|
@@ -36,9 +36,7 @@ const NewHydrate = (0, mobx_react_1.observer)(function RpcRenderedSvgGroup(props
|
|
|
36
36
|
const { html, theme, RenderingComponent, ...rest } = props;
|
|
37
37
|
const ref = (0, react_1.useRef)(null);
|
|
38
38
|
// this `any` is a react-dom/client::Root
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
39
|
const rootRef = (0, react_1.useRef)();
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
40
|
const root = (0, mobx_state_tree_1.getRoot)(props.displayModel);
|
|
43
41
|
const hydrateRoot = root.hydrateFn;
|
|
44
42
|
(0, react_1.useEffect)(() => {
|
|
@@ -53,15 +51,17 @@ const NewHydrate = (0, mobx_react_1.observer)(function RpcRenderedSvgGroup(props
|
|
|
53
51
|
react_1.default.createElement(RenderingComponent, { ...rest })));
|
|
54
52
|
});
|
|
55
53
|
return () => {
|
|
56
|
-
|
|
54
|
+
if (renderTimeout !== undefined) {
|
|
55
|
+
clearTimeout(renderTimeout);
|
|
56
|
+
}
|
|
57
57
|
const root = rootRef.current;
|
|
58
58
|
rootRef.current = undefined;
|
|
59
59
|
setTimeout(() => {
|
|
60
60
|
root === null || root === void 0 ? void 0 : root.unmount();
|
|
61
61
|
});
|
|
62
62
|
};
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
64
|
+
}, [RenderingComponent, hydrateRoot, theme, rest]);
|
|
65
65
|
return react_1.default.createElement("g", { ref: ref, dangerouslySetInnerHTML: { __html: html } });
|
|
66
66
|
});
|
|
67
67
|
const OldHydrate = (0, mobx_react_1.observer)(function OldHydrate(props) {
|
|
@@ -72,16 +72,18 @@ const OldHydrate = (0, mobx_react_1.observer)(function OldHydrate(props) {
|
|
|
72
72
|
function doHydrate() {
|
|
73
73
|
if (domNode && html) {
|
|
74
74
|
if (domNode.innerHTML) {
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
75
76
|
(0, react_dom_1.unmountComponentAtNode)(domNode);
|
|
76
77
|
}
|
|
77
78
|
// setting outline:none fixes react "focusable" element issue. see
|
|
78
79
|
// https://github.com/GMOD/jbrowse-components/issues/2160
|
|
79
80
|
domNode.style.outline = 'none';
|
|
80
81
|
domNode.innerHTML = html;
|
|
81
|
-
// use requestIdleCallback to defer main-thread rendering
|
|
82
|
-
//
|
|
83
|
-
//
|
|
82
|
+
// use requestIdleCallback to defer main-thread rendering and
|
|
83
|
+
// hydration for when we have some free time. helps keep the
|
|
84
|
+
// framerate up.
|
|
84
85
|
(0, util_1.rIC)(() => {
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
85
87
|
(0, react_dom_1.hydrate)(react_1.default.createElement(RenderingComponent, { ...props }), domNode);
|
|
86
88
|
});
|
|
87
89
|
}
|
|
@@ -89,6 +91,7 @@ const OldHydrate = (0, mobx_react_1.observer)(function OldHydrate(props) {
|
|
|
89
91
|
doHydrate();
|
|
90
92
|
return () => {
|
|
91
93
|
if (domNode) {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
92
95
|
(0, react_dom_1.unmountComponentAtNode)(domNode);
|
|
93
96
|
}
|
|
94
97
|
};
|
|
@@ -96,7 +99,6 @@ const OldHydrate = (0, mobx_react_1.observer)(function OldHydrate(props) {
|
|
|
96
99
|
return react_1.default.createElement("g", { ref: ref });
|
|
97
100
|
});
|
|
98
101
|
const RpcRenderedSvgGroup = (0, mobx_react_1.observer)(function (props) {
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
102
|
const root = (0, mobx_state_tree_1.getRoot)(props.displayModel);
|
|
101
103
|
return root.hydrateFn ? react_1.default.createElement(NewHydrate, { ...props }) : react_1.default.createElement(OldHydrate, { ...props });
|
|
102
104
|
});
|
|
@@ -34,14 +34,12 @@ const react_dom_1 = require("react-dom");
|
|
|
34
34
|
const util_1 = require("../../util");
|
|
35
35
|
const NewHydrate = (0, mobx_react_1.observer)(function ServerSideRenderedContent({ theme, html, RenderingComponent, ...rest }) {
|
|
36
36
|
const ref = (0, react_1.useRef)(null);
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
37
|
const rootRef = (0, react_1.useRef)();
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
38
|
const { hydrateFn } = (0, mobx_state_tree_1.getRoot)(rest.displayModel);
|
|
41
39
|
(0, react_1.useEffect)(() => {
|
|
42
|
-
// requestIdleCallback here helps to avoid hydration mismatch
|
|
43
|
-
//
|
|
44
|
-
//
|
|
40
|
+
// requestIdleCallback here helps to avoid hydration mismatch because it
|
|
41
|
+
// provides time for dangerouslySetInnerHTML to set the innerHTML contents
|
|
42
|
+
// of the node, otherwise ref.current.innerHTML can be empty
|
|
45
43
|
const renderTimeout = (0, util_1.rIC)(() => {
|
|
46
44
|
var _a;
|
|
47
45
|
if (!ref.current) {
|
|
@@ -57,17 +55,18 @@ const NewHydrate = (0, mobx_react_1.observer)(function ServerSideRenderedContent
|
|
|
57
55
|
react_1.default.createElement(RenderingComponent, { ...rest })));
|
|
58
56
|
});
|
|
59
57
|
return () => {
|
|
60
|
-
|
|
58
|
+
if (renderTimeout !== undefined) {
|
|
59
|
+
clearTimeout(renderTimeout);
|
|
60
|
+
}
|
|
61
61
|
const root = rootRef.current;
|
|
62
62
|
rootRef.current = undefined;
|
|
63
63
|
setTimeout(() => {
|
|
64
64
|
root === null || root === void 0 ? void 0 : root.unmount();
|
|
65
65
|
});
|
|
66
66
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
dangerouslySetInnerHTML: { __html: html } }));
|
|
67
|
+
/* biome-ignore lint/correctness/useExhaustiveDependencies: */
|
|
68
|
+
}, [theme, rest, hydrateFn, RenderingComponent]);
|
|
69
|
+
return (react_1.default.createElement("div", { "data-testid": "hydrationContainer", ref: ref, dangerouslySetInnerHTML: { __html: html } }));
|
|
71
70
|
});
|
|
72
71
|
const OldHydrate = (0, mobx_react_1.observer)(function ({ theme, html, RenderingComponent, ...rest }) {
|
|
73
72
|
const ref = (0, react_1.useRef)(null);
|
|
@@ -76,11 +75,11 @@ const OldHydrate = (0, mobx_react_1.observer)(function ({ theme, html, Rendering
|
|
|
76
75
|
const domNode = ref.current;
|
|
77
76
|
function doHydrate() {
|
|
78
77
|
if (domNode) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
79
|
+
(0, react_dom_1.unmountComponentAtNode)(domNode);
|
|
82
80
|
domNode.innerHTML = html;
|
|
83
81
|
(0, util_1.rIC)(() => {
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
84
83
|
(0, react_dom_1.hydrate)(react_1.default.createElement(styles_1.ThemeProvider, { theme: jbrowseTheme },
|
|
85
84
|
react_1.default.createElement(RenderingComponent, { ...rest })), domNode);
|
|
86
85
|
});
|
|
@@ -89,14 +88,15 @@ const OldHydrate = (0, mobx_react_1.observer)(function ({ theme, html, Rendering
|
|
|
89
88
|
doHydrate();
|
|
90
89
|
return () => {
|
|
91
90
|
if (domNode) {
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
92
92
|
(0, react_dom_1.unmountComponentAtNode)(domNode);
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
|
+
/* biome-ignore lint/correctness/useExhaustiveDependencies: */
|
|
95
96
|
}, [html, jbrowseTheme, rest, RenderingComponent]);
|
|
96
97
|
return react_1.default.createElement("div", { ref: ref });
|
|
97
98
|
});
|
|
98
99
|
const ServerSideRenderedContent = (0, mobx_react_1.observer)(function (props) {
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
100
|
const root = (0, mobx_state_tree_1.getRoot)(props.displayModel);
|
|
101
101
|
return root.hydrateFn ? react_1.default.createElement(NewHydrate, { ...props }) : react_1.default.createElement(OldHydrate, { ...props });
|
|
102
102
|
});
|
|
@@ -8,22 +8,22 @@ interface BaseRenderArgs extends RenderProps {
|
|
|
8
8
|
sessionId: string;
|
|
9
9
|
signal?: AbortSignal;
|
|
10
10
|
theme: ThemeOptions;
|
|
11
|
-
exportSVG
|
|
11
|
+
exportSVG?: {
|
|
12
12
|
rasterizeLayers?: boolean;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
export interface RenderArgs extends BaseRenderArgs {
|
|
16
16
|
config: SnapshotOrInstance<AnyConfigurationModel>;
|
|
17
|
-
filters
|
|
17
|
+
filters?: SerializableFilterChain;
|
|
18
18
|
}
|
|
19
19
|
export interface RenderArgsSerialized extends BaseRenderArgs {
|
|
20
20
|
statusCallback?: (arg: string) => void;
|
|
21
21
|
config: SnapshotIn<AnyConfigurationModel>;
|
|
22
|
-
filters
|
|
22
|
+
filters?: SerializedFilterChain;
|
|
23
23
|
}
|
|
24
24
|
export interface RenderArgsDeserialized extends BaseRenderArgs {
|
|
25
25
|
config: AnyConfigurationModel;
|
|
26
|
-
filters
|
|
26
|
+
filters?: SerializableFilterChain;
|
|
27
27
|
}
|
|
28
28
|
export interface ResultsSerialized extends Omit<RenderResults, 'reactElement'> {
|
|
29
29
|
html: string;
|
|
@@ -72,9 +72,11 @@ class ServerSideRenderer extends RendererType_1.default {
|
|
|
72
72
|
deserialized.config = this.configSchema.create(args.config || {}, {
|
|
73
73
|
pluginManager: this.pluginManager,
|
|
74
74
|
});
|
|
75
|
-
deserialized.filters =
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
deserialized.filters = args.filters
|
|
76
|
+
? new serializableFilterChain_1.default({
|
|
77
|
+
filters: args.filters,
|
|
78
|
+
})
|
|
79
|
+
: undefined;
|
|
78
80
|
return deserialized;
|
|
79
81
|
}
|
|
80
82
|
/**
|
|
@@ -87,7 +89,7 @@ class ServerSideRenderer extends RendererType_1.default {
|
|
|
87
89
|
*/
|
|
88
90
|
serializeResultsInWorker(results, args) {
|
|
89
91
|
const html = (0, server_1.renderToString)(react_1.default.createElement(styles_1.ThemeProvider, { theme: (0, ui_1.createJBrowseTheme)(args.theme) }, results.reactElement));
|
|
90
|
-
|
|
92
|
+
results.reactElement = undefined;
|
|
91
93
|
return { ...results, html };
|
|
92
94
|
}
|
|
93
95
|
/**
|
|
@@ -101,7 +103,7 @@ class ServerSideRenderer extends RendererType_1.default {
|
|
|
101
103
|
const results = (await rpcManager.call(args.sessionId, 'CoreRender', args));
|
|
102
104
|
if (isSvgExport(results)) {
|
|
103
105
|
results.html = await (0, util_1.getSerializedSvg)(results);
|
|
104
|
-
|
|
106
|
+
results.reactElement = undefined;
|
|
105
107
|
}
|
|
106
108
|
return results;
|
|
107
109
|
}
|
package/rpc/BaseRpcDriver.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import PluginManager from '../PluginManager';
|
|
|
2
2
|
import { AnyConfigurationModel } from '../configuration';
|
|
3
3
|
export interface WorkerHandle {
|
|
4
4
|
status?: string;
|
|
5
|
-
error?:
|
|
5
|
+
error?: unknown;
|
|
6
6
|
on?: (channel: string, callback: (message: unknown) => void) => void;
|
|
7
7
|
off?: (channel: string, callback: (message: unknown) => void) => void;
|
|
8
8
|
destroy(): void;
|
package/rpc/BaseRpcDriver.js
CHANGED
|
@@ -12,7 +12,7 @@ function isClonable(thing) {
|
|
|
12
12
|
// the worker times out
|
|
13
13
|
async function watchWorker(worker, pingTime, rpcDriverClassName) {
|
|
14
14
|
// after first ping succeeds, apply wait for timeout
|
|
15
|
-
// eslint-disable-next-line no-
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
16
16
|
while (true) {
|
|
17
17
|
await worker.call('ping', [], {
|
|
18
18
|
timeout: pingTime * 2,
|
|
@@ -38,19 +38,17 @@ class LazyWorker {
|
|
|
38
38
|
this.workerP = this.driver
|
|
39
39
|
.makeWorker()
|
|
40
40
|
.then(worker => {
|
|
41
|
-
watchWorker(worker, this.driver.maxPingTime, this.driver.name).catch(error => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.workerP = undefined;
|
|
49
|
-
}
|
|
41
|
+
watchWorker(worker, this.driver.maxPingTime, this.driver.name).catch((error) => {
|
|
42
|
+
console.error('worker did not respond, killing and generating new one');
|
|
43
|
+
console.error(error);
|
|
44
|
+
worker.destroy();
|
|
45
|
+
worker.status = 'killed';
|
|
46
|
+
worker.error = error;
|
|
47
|
+
this.workerP = undefined;
|
|
50
48
|
});
|
|
51
49
|
return worker;
|
|
52
50
|
})
|
|
53
|
-
.catch(e => {
|
|
51
|
+
.catch((e) => {
|
|
54
52
|
this.workerP = undefined;
|
|
55
53
|
throw e;
|
|
56
54
|
});
|
|
@@ -133,6 +131,9 @@ class BaseRpcDriver {
|
|
|
133
131
|
const unextendedWorker = await this.getWorker(sessionId);
|
|
134
132
|
const worker = pluginManager.evaluateExtensionPoint('Core-extendWorker', unextendedWorker);
|
|
135
133
|
const rpcMethod = pluginManager.getRpcMethodType(functionName);
|
|
134
|
+
if (!rpcMethod) {
|
|
135
|
+
throw new Error(`unknown RPC method ${functionName}`);
|
|
136
|
+
}
|
|
136
137
|
const serializedArgs = await rpcMethod.serializeArguments(args, this.name);
|
|
137
138
|
const filteredAndSerializedArgs = this.filterArgs(serializedArgs, sessionId);
|
|
138
139
|
// now actually call the worker
|
|
@@ -2,7 +2,7 @@ import BaseRpcDriver, { RpcDriverConstructorArgs } from './BaseRpcDriver';
|
|
|
2
2
|
import PluginManager from '../PluginManager';
|
|
3
3
|
declare class DummyHandle {
|
|
4
4
|
destroy(): void;
|
|
5
|
-
call(_functionName: string, _filteredArgs?:
|
|
5
|
+
call(_functionName: string, _filteredArgs?: Record<string, unknown>, _options?: {}): Promise<unknown>;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Stub RPC driver class that runs RPC functions in-band in the main thread.
|
|
@@ -13,6 +13,6 @@ export default class MainThreadRpcDriver extends BaseRpcDriver {
|
|
|
13
13
|
name: string;
|
|
14
14
|
makeWorker: () => Promise<DummyHandle>;
|
|
15
15
|
constructor(args: RpcDriverConstructorArgs);
|
|
16
|
-
call(pm: PluginManager, sessionId: string, funcName: string, args:
|
|
16
|
+
call(pm: PluginManager, sessionId: string, funcName: string, args: Record<string, unknown>): Promise<unknown>;
|
|
17
17
|
}
|
|
18
18
|
export {};
|
|
@@ -26,6 +26,9 @@ class MainThreadRpcDriver extends BaseRpcDriver_1.default {
|
|
|
26
26
|
throw new TypeError('sessionId is required');
|
|
27
27
|
}
|
|
28
28
|
const rpcMethod = pm.getRpcMethodType(funcName);
|
|
29
|
+
if (!rpcMethod) {
|
|
30
|
+
throw new Error(`unknown RPC method ${funcName}`);
|
|
31
|
+
}
|
|
29
32
|
const serializedArgs = await rpcMethod.serializeArguments(args, this.name);
|
|
30
33
|
const result = await rpcMethod.execute(serializedArgs, this.name);
|
|
31
34
|
return rpcMethod.deserializeReturn(result, args, this.name);
|
package/rpc/RpcManager.d.ts
CHANGED
|
@@ -29,6 +29,6 @@ export default class RpcManager {
|
|
|
29
29
|
getDriverForCall(_sessionId: string, _functionName: string, args: {
|
|
30
30
|
rpcDriverName?: string;
|
|
31
31
|
}): Promise<DriverClass>;
|
|
32
|
-
call(sessionId: string, functionName: string, args:
|
|
32
|
+
call(sessionId: string, functionName: string, args: Record<string, unknown>, opts?: {}): Promise<unknown>;
|
|
33
33
|
}
|
|
34
34
|
export {};
|