@jbrowse/product-core 4.2.1 → 5.0.0-beta.1
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/esm/RootModel/BaseRootModel.d.ts +629 -304
- package/esm/RootModel/BaseRootModel.js +138 -14
- package/esm/RootModel/HierarchicalConfig.d.ts +57 -21
- package/esm/RootModel/HierarchicalConfig.js +36 -0
- package/esm/RootModel/InternetAccounts.d.ts +18 -1
- package/esm/RootModel/InternetAccounts.js +120 -22
- package/esm/RootModel/PreferencesConfig.d.ts +53 -0
- package/esm/RootModel/PreferencesConfig.js +61 -0
- package/esm/RootModel/createConfigModel.d.ts +232 -0
- package/esm/RootModel/createConfigModel.js +56 -0
- package/esm/RootModel/index.d.ts +10 -5
- package/esm/RootModel/index.js +10 -5
- package/esm/RootModel/menuItems.d.ts +24 -0
- package/esm/RootModel/menuItems.js +143 -0
- package/esm/Session/BaseSession.d.ts +310 -11
- package/esm/Session/BaseSession.js +448 -14
- package/esm/Session/Connections.d.ts +114 -8
- package/esm/Session/Connections.js +195 -74
- package/esm/Session/DrawerWidgets.d.ts +115 -12
- package/esm/Session/DrawerWidgets.js +161 -42
- package/esm/Session/MultipleViews.d.ts +1266 -1128
- package/esm/Session/MultipleViews.js +357 -66
- package/esm/Session/Preferences.d.ts +1665 -0
- package/esm/Session/Preferences.js +54 -0
- package/esm/Session/ReferenceManagement.d.ts +28 -3
- package/esm/Session/ReferenceManagement.js +56 -41
- package/esm/Session/SessionTracks.d.ts +1275 -1138
- package/esm/Session/SessionTracks.js +532 -35
- package/esm/Session/Themes.d.ts +87 -2
- package/esm/Session/Themes.js +156 -23
- package/esm/Session/TrackMenu.d.ts +112 -0
- package/esm/Session/TrackMenu.js +200 -0
- package/esm/Session/TrackMenuSessionMixin.d.ts +27 -0
- package/esm/Session/TrackMenuSessionMixin.js +41 -0
- package/esm/Session/Tracks.d.ts +1169 -1117
- package/esm/Session/Tracks.js +160 -20
- package/esm/Session/assertSessionModel.d.ts +21 -0
- package/esm/Session/assertSessionModel.js +1 -0
- package/esm/Session/finalizeSession.d.ts +16 -0
- package/esm/Session/finalizeSession.js +29 -0
- package/esm/Session/index.d.ts +22 -10
- package/esm/Session/index.js +13 -10
- package/esm/Session/shareableSnapshot.d.ts +77 -0
- package/esm/Session/shareableSnapshot.js +196 -0
- package/esm/Session/temporaryAssemblyTracks.d.ts +23 -0
- package/esm/Session/temporaryAssemblyTracks.js +38 -0
- package/esm/assertExtends.d.ts +55 -0
- package/esm/assertExtends.js +1 -0
- package/esm/controllerTracks.d.ts +56 -0
- package/esm/controllerTracks.js +77 -0
- package/esm/destroyViewState.d.ts +21 -0
- package/esm/destroyViewState.js +29 -0
- package/esm/index.d.ts +31 -4
- package/esm/index.js +31 -4
- package/esm/loadPlugins.d.ts +33 -0
- package/esm/loadPlugins.js +38 -0
- package/esm/localFiles.d.ts +74 -0
- package/esm/localFiles.js +156 -0
- package/esm/observeSession.d.ts +56 -0
- package/esm/observeSession.js +91 -0
- package/esm/pluginInput.d.ts +32 -0
- package/esm/pluginInput.js +19 -0
- package/esm/pruneUnbuildableNodes.d.ts +109 -0
- package/esm/pruneUnbuildableNodes.js +568 -0
- package/esm/resolveAssemblies.d.ts +44 -0
- package/esm/resolveAssemblies.js +55 -0
- package/esm/rpcWorker.d.ts +26 -0
- package/esm/rpcWorker.js +96 -15
- package/esm/scheduleDetachedDestroy.d.ts +18 -0
- package/esm/scheduleDetachedDestroy.js +24 -0
- package/esm/sessionMigrations/index.d.ts +53 -0
- package/esm/sessionMigrations/index.js +432 -0
- package/esm/sessionUrl.d.ts +41 -0
- package/esm/sessionUrl.js +53 -0
- package/esm/sessionUtils.d.ts +69 -0
- package/esm/sessionUtils.js +613 -0
- package/esm/siblingCast.d.ts +14 -0
- package/esm/siblingCast.js +16 -0
- package/esm/snapshotUtils.d.ts +8 -0
- package/esm/snapshotUtils.js +12 -0
- package/esm/ui/AboutDialog.d.ts +3 -6
- package/esm/ui/AboutDialog.js +4 -4
- package/esm/ui/AboutDialogContents.d.ts +2 -6
- package/esm/ui/AboutDialogContents.js +34 -13
- package/esm/ui/AssemblyInfoPanel.d.ts +5 -0
- package/esm/ui/AssemblyInfoPanel.js +69 -0
- package/esm/ui/DisplayDefaultsSection.d.ts +36 -0
- package/esm/ui/DisplayDefaultsSection.js +65 -0
- package/esm/ui/Drawer.d.ts +21 -0
- package/esm/ui/Drawer.js +60 -0
- package/esm/ui/DrawerControls.d.ts +5 -0
- package/esm/ui/DrawerControls.js +28 -0
- package/esm/ui/DrawerHeader.d.ts +6 -0
- package/esm/ui/DrawerHeader.js +36 -0
- package/esm/ui/DrawerWidget.d.ts +5 -0
- package/esm/ui/DrawerWidget.js +12 -0
- package/esm/ui/DrawerWidgetSelector.d.ts +5 -0
- package/esm/ui/DrawerWidgetSelector.js +40 -0
- package/esm/ui/FileInfoPanel.d.ts +3 -6
- package/esm/ui/FileInfoPanel.js +35 -26
- package/esm/ui/HeaderButtons.d.ts +7 -1
- package/esm/ui/HeaderButtons.js +23 -18
- package/esm/ui/ModalWidget.d.ts +12 -0
- package/esm/ui/ModalWidget.js +33 -0
- package/esm/ui/ModalWidgetAppBar.d.ts +8 -0
- package/esm/ui/ModalWidgetAppBar.js +9 -0
- package/esm/ui/PreferencesDialog.d.ts +56 -0
- package/esm/ui/PreferencesDialog.js +145 -0
- package/esm/ui/PreferencesResetDialog.d.ts +8 -0
- package/esm/ui/PreferencesResetDialog.js +19 -0
- package/esm/ui/RefNameAliasesDialog.d.ts +9 -0
- package/esm/ui/RefNameAliasesDialog.js +65 -0
- package/esm/ui/RefNameInfoDialog.d.ts +3 -6
- package/esm/ui/RefNameInfoDialog.js +57 -63
- package/esm/ui/WidgetBody.d.ts +18 -0
- package/esm/ui/WidgetBody.js +22 -0
- package/esm/ui/WidgetHeading.d.ts +7 -0
- package/esm/ui/WidgetHeading.js +7 -0
- package/esm/ui/drawerLayout.d.ts +18 -0
- package/esm/ui/drawerLayout.js +22 -0
- package/esm/ui/index.d.ts +13 -1
- package/esm/ui/index.js +12 -1
- package/esm/ui/util.d.ts +37 -4
- package/esm/ui/util.js +35 -38
- package/esm/useEngineLifecycle.d.ts +13 -0
- package/esm/useEngineLifecycle.js +22 -0
- package/package.json +11 -15
- package/esm/RootModel/FormatAbout.d.ts +0 -12
- package/esm/RootModel/FormatAbout.js +0 -15
- package/esm/RootModel/FormatDetails.d.ts +0 -24
- package/esm/RootModel/FormatDetails.js +0 -27
- package/esm/Session/DialogQueue.d.ts +0 -17
- package/esm/Session/DialogQueue.js +0 -31
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { namesTemporaryAssembly } from '@jbrowse/core/util';
|
|
2
|
+
/**
|
|
3
|
+
* Dev-only check that a track config being written into a session or config list
|
|
4
|
+
* is one something can still draw tomorrow. No-op in production.
|
|
5
|
+
*
|
|
6
|
+
* A config naming nothing but a temporary assembly is dead the moment its view
|
|
7
|
+
* closes, and no list outside that view has anyone to sweep it — which is the
|
|
8
|
+
* whole of ADR-084. A track only one view can draw carries its config on the
|
|
9
|
+
* track instead (`showTrackGeneric`'s `inlineConf`), so reaching a session list
|
|
10
|
+
* with one is the mistake, not the cleanup afterwards.
|
|
11
|
+
*
|
|
12
|
+
* **This reports a write, not a click.** The two flows a user can drive into it
|
|
13
|
+
* are answered before they get here — the track menu greys its copy actions, and
|
|
14
|
+
* `addTrackFromWidget` opens the track inline instead of adding it — so what
|
|
15
|
+
* survives to report is a caller that had `inlineConf` available and did not
|
|
16
|
+
* take it. That is the reading the message is written for.
|
|
17
|
+
*
|
|
18
|
+
* `console.error` and never `throw`, matching `assertDisplayContract`: these
|
|
19
|
+
* writes happen inside launchers and menu handlers where an exception is caught
|
|
20
|
+
* and reported as a failed track, which would hide the violation. The jest gate
|
|
21
|
+
* (`config/jest/contractGate.js`) is what listens.
|
|
22
|
+
*/
|
|
23
|
+
export function assertTrackConfOutlivesItsAssemblies(session, trackConf, destination) {
|
|
24
|
+
if (process.env.NODE_ENV === 'production') {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!namesTemporaryAssembly(session, trackConf)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const { trackId } = trackConf;
|
|
31
|
+
console.error(`[jbrowse session contract] ${destination} was given "${trackId}", ` +
|
|
32
|
+
`which names a temporary assembly — one a comparative view synthesized ` +
|
|
33
|
+
`and gives back when it closes, so this config outlives the only ` +
|
|
34
|
+
`assembly that could draw it and nothing sweeps the list it landed in. ` +
|
|
35
|
+
`A track only one view can draw passes its config to that view's ` +
|
|
36
|
+
`showTrack as \`inlineConf\` instead, which puts it on the track and ` +
|
|
37
|
+
`takes it out with the view. See ADR-084.`);
|
|
38
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time assertion that `Actual` is assignable to `Expected`, evaluating
|
|
3
|
+
* to `Actual`. There is no runtime component — referencing the alias forces the
|
|
4
|
+
* check, and a mismatch surfaces as a type error at the reference site.
|
|
5
|
+
*
|
|
6
|
+
* The main use is binding a hand-written "shadow" contract to the real type it
|
|
7
|
+
* shadows so the two can't silently drift. MST's `getParent<T>(self)` is an
|
|
8
|
+
* unchecked assertion (`T` has no structural link to the actual parent), so a
|
|
9
|
+
* child model that reaches into its parent via a local shape can keep compiling
|
|
10
|
+
* after the real parent renames or drops a member — until it throws at runtime.
|
|
11
|
+
* Pinning `AssertExtends<RealRootModel, ShadowParent>` turns that into a build
|
|
12
|
+
* error:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* interface SessionModelParent {
|
|
16
|
+
* version: string
|
|
17
|
+
* assemblyManager: AssemblyManager
|
|
18
|
+
* }
|
|
19
|
+
* // real root must satisfy the shadow the session reaches for
|
|
20
|
+
* export type _Check = AssertExtends<ViewModel, SessionModelParent>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type AssertExtends<Actual extends Expected, Expected> = Actual;
|
|
24
|
+
/**
|
|
25
|
+
* Compile-time assertion that a type has not degraded to `any`. Pass it the
|
|
26
|
+
* `IsAny` of the type you are pinning; a failure reads `Type 'true' does not
|
|
27
|
+
* satisfy the constraint 'false'`.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* export type _ViewIsTyped = AssertNotAny<IsAny<ViewModel['session']['view']>>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* This is the one check the others cannot make for you. `any` satisfies every
|
|
34
|
+
* `AssertExtends`, implements every `SessionWith*` contract, and passes tsc,
|
|
35
|
+
* jest and lint — so a surface that silently becomes `any` switches off type
|
|
36
|
+
* checking everywhere downstream while every gate stays green.
|
|
37
|
+
*
|
|
38
|
+
* Composed MST models are where it happens here. `types.compose`'s overloads
|
|
39
|
+
* are declared over `IModelType<P, O, FC, FS>`, so a model passed in as a naked
|
|
40
|
+
* type parameter has nothing to infer those four from and the composed result
|
|
41
|
+
* degrades.
|
|
42
|
+
*
|
|
43
|
+
* Naming `any` twice at the call site is not an oversight. It takes the computed
|
|
44
|
+
* boolean because the constraint has to be checked where it is concrete, and all
|
|
45
|
+
* three single-argument spellings were tried and fail:
|
|
46
|
+
*
|
|
47
|
+
* - `AssertNotAny<T> = AssertExtends<IsAny<T>, false>` — unbound, `IsAny<T>` is
|
|
48
|
+
* `boolean`, so the alias fails at its own declaration.
|
|
49
|
+
* - `AssertNotAny<T, _ extends false = IsAny<T>> = T` — the tempting one. Same
|
|
50
|
+
* declaration-site failure, and it does not even catch: instantiated at `any`
|
|
51
|
+
* it reports nothing.
|
|
52
|
+
* - `AssertNotAny<T extends IsAny<T> extends true ? never : unknown>` — TS2313,
|
|
53
|
+
* circular constraint.
|
|
54
|
+
*/
|
|
55
|
+
export type AssertNotAny<IsItAny extends false> = IsItAny;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { BlobLocation } from '@jbrowse/core/util';
|
|
2
|
+
import type { LooseTrackInput } from '@jbrowse/core/util/tracks';
|
|
3
|
+
import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
4
|
+
export type TrackConf = Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* What a controller accepts per track: a full config, a bare data-file URL, or
|
|
7
|
+
* `{ uri, index?, ...extra }`. The loose forms expand through core's
|
|
8
|
+
* `guessTrackConf`, the same inference the "Add track" flow runs.
|
|
9
|
+
*/
|
|
10
|
+
export type TrackInput = string | TrackConf;
|
|
11
|
+
interface ControllerView {
|
|
12
|
+
tracks: {
|
|
13
|
+
configuration: {
|
|
14
|
+
trackId: string;
|
|
15
|
+
};
|
|
16
|
+
}[];
|
|
17
|
+
showTrack: (trackId: string) => unknown;
|
|
18
|
+
hideTrack: (trackId: string) => unknown;
|
|
19
|
+
}
|
|
20
|
+
export interface ControllerSession extends IStateTreeNode {
|
|
21
|
+
view: ControllerView;
|
|
22
|
+
getTrackById: (trackId: string) => unknown;
|
|
23
|
+
addSessionTrackConf: (conf: TrackConf) => unknown;
|
|
24
|
+
}
|
|
25
|
+
export declare function isLooseTrack(track: TrackInput): track is string | LooseTrackInput;
|
|
26
|
+
/**
|
|
27
|
+
* Stamp the view's assembly onto a full-config track that omits
|
|
28
|
+
* `assemblyNames`. A single-view embed has exactly one assembly, so it is
|
|
29
|
+
* unambiguous — and doing it here frees every host (R htmlwidgets, anywidget,
|
|
30
|
+
* vanilla JS) from computing the name itself, which it often cannot: the
|
|
31
|
+
* assembly may have arrived as a hub name only the view resolved. Loose tracks
|
|
32
|
+
* take the same name through `guessTrackConf`'s `assemblyName` argument.
|
|
33
|
+
*/
|
|
34
|
+
export declare function withAssemblyName(track: TrackConf, assemblyName?: string): TrackConf;
|
|
35
|
+
/**
|
|
36
|
+
* Expand every loose entry into a full track config; stamp the assembly name
|
|
37
|
+
* onto the ones already written out. `node` is any node of the live tree — the
|
|
38
|
+
* pluginManager whose format plugins drive the guess comes off its env.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveTracks(tracks: TrackInput[], node: IStateTreeNode, assemblyName?: string, localFiles?: Record<string, BlobLocation>): TrackConf[];
|
|
41
|
+
/**
|
|
42
|
+
* Register each track config only if the session cannot already resolve it, then
|
|
43
|
+
* show it. `getTrackById` resolves catalog + connection + session tracks, so a
|
|
44
|
+
* config already seeded into the catalog is left alone rather than shadowed by a
|
|
45
|
+
* duplicate in `sessionTracks` — which is also what `addSessionTrackConf`
|
|
46
|
+
* dedupes on, so this states the intent rather than supplying it.
|
|
47
|
+
*
|
|
48
|
+
* Session-scoped: these are the host's declared tracks for one embed, not a
|
|
49
|
+
* catalog an admin curates.
|
|
50
|
+
*/
|
|
51
|
+
export declare function openTracks(session: ControllerSession, tracks: TrackConf[]): void;
|
|
52
|
+
/** Open every wanted track and close any others the view currently shows. */
|
|
53
|
+
export declare function reconcileTracks(session: ControllerSession, tracks: TrackConf[]): void;
|
|
54
|
+
/** Merge a hub's own search adapters with the ones the caller supplied. */
|
|
55
|
+
export declare function mergeSearchAdapters<T>(a: readonly T[] | undefined, b: readonly T[] | undefined): T[] | undefined;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { getEnv } from '@jbrowse/core/util';
|
|
2
|
+
import { guessTrackConf } from '@jbrowse/core/util/tracks';
|
|
3
|
+
import { resolveLocalFileUris } from './localFiles.js';
|
|
4
|
+
export function isLooseTrack(track) {
|
|
5
|
+
return typeof track === 'string' || (!('adapter' in track) && 'uri' in track);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Stamp the view's assembly onto a full-config track that omits
|
|
9
|
+
* `assemblyNames`. A single-view embed has exactly one assembly, so it is
|
|
10
|
+
* unambiguous — and doing it here frees every host (R htmlwidgets, anywidget,
|
|
11
|
+
* vanilla JS) from computing the name itself, which it often cannot: the
|
|
12
|
+
* assembly may have arrived as a hub name only the view resolved. Loose tracks
|
|
13
|
+
* take the same name through `guessTrackConf`'s `assemblyName` argument.
|
|
14
|
+
*/
|
|
15
|
+
export function withAssemblyName(track, assemblyName) {
|
|
16
|
+
return assemblyName !== undefined && !('assemblyNames' in track)
|
|
17
|
+
? { ...track, assemblyNames: [assemblyName] }
|
|
18
|
+
: track;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Expand every loose entry into a full track config; stamp the assembly name
|
|
22
|
+
* onto the ones already written out. `node` is any node of the live tree — the
|
|
23
|
+
* pluginManager whose format plugins drive the guess comes off its env.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveTracks(tracks, node, assemblyName, localFiles) {
|
|
26
|
+
const { pluginManager } = getEnv(node);
|
|
27
|
+
return tracks.map(track => {
|
|
28
|
+
const conf = isLooseTrack(track)
|
|
29
|
+
? guessTrackConf(track, pluginManager, assemblyName)
|
|
30
|
+
: // full configs are stamped here too, not just in the build() catalog
|
|
31
|
+
// seed: a config that first appears through addTrack never passes
|
|
32
|
+
// through that seed, and would otherwise reach addSessionTrackConf with no
|
|
33
|
+
// assemblyNames and silently fail to display
|
|
34
|
+
withAssemblyName(track, assemblyName);
|
|
35
|
+
// after the guess, so the adapter has already derived its index sibling
|
|
36
|
+
// from the uri string and both get swapped for blobs together
|
|
37
|
+
return localFiles ? resolveLocalFileUris(conf, localFiles) : conf;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Register each track config only if the session cannot already resolve it, then
|
|
42
|
+
* show it. `getTrackById` resolves catalog + connection + session tracks, so a
|
|
43
|
+
* config already seeded into the catalog is left alone rather than shadowed by a
|
|
44
|
+
* duplicate in `sessionTracks` — which is also what `addSessionTrackConf`
|
|
45
|
+
* dedupes on, so this states the intent rather than supplying it.
|
|
46
|
+
*
|
|
47
|
+
* Session-scoped: these are the host's declared tracks for one embed, not a
|
|
48
|
+
* catalog an admin curates.
|
|
49
|
+
*/
|
|
50
|
+
export function openTracks(session, tracks) {
|
|
51
|
+
for (const conf of tracks) {
|
|
52
|
+
const trackId = conf.trackId;
|
|
53
|
+
if (!session.getTrackById(trackId)) {
|
|
54
|
+
session.addSessionTrackConf(conf);
|
|
55
|
+
}
|
|
56
|
+
session.view.showTrack(trackId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Open every wanted track and close any others the view currently shows. */
|
|
60
|
+
export function reconcileTracks(session, tracks) {
|
|
61
|
+
const { view } = session;
|
|
62
|
+
const wanted = new Set(tracks.map(t => t.trackId));
|
|
63
|
+
openTracks(session, tracks);
|
|
64
|
+
// materialize the ids first: hideTrack splices view.tracks, so iterating it
|
|
65
|
+
// live would skip entries
|
|
66
|
+
const unwanted = view.tracks
|
|
67
|
+
.map(track => track.configuration.trackId)
|
|
68
|
+
.filter(trackId => !wanted.has(trackId));
|
|
69
|
+
for (const trackId of unwanted) {
|
|
70
|
+
view.hideTrack(trackId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Merge a hub's own search adapters with the ones the caller supplied. */
|
|
74
|
+
export function mergeSearchAdapters(a, b) {
|
|
75
|
+
const merged = [...(a ?? []), ...(b ?? [])];
|
|
76
|
+
return merged.length ? merged : undefined;
|
|
77
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
export interface EmbeddedRoot extends IStateTreeNode {
|
|
3
|
+
session?: unknown;
|
|
4
|
+
rpcManager: {
|
|
5
|
+
destroy: () => void;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tear down an engine built by an embedded product's `createViewState`:
|
|
10
|
+
* terminate its RPC worker threads and destroy the MST tree so its
|
|
11
|
+
* `addDisposer`'d autoruns stop.
|
|
12
|
+
*
|
|
13
|
+
* Unmounting the React tree is not enough — the engine is not owned by React.
|
|
14
|
+
* A host that builds and discards engines (a Jupyter cell re-run, an SPA route
|
|
15
|
+
* change, a controller's `destroy()`) otherwise orphans a whole worker pool and
|
|
16
|
+
* a live autorun set per discarded engine. A component that owns one engine for
|
|
17
|
+
* the lifetime of the page never needs this.
|
|
18
|
+
*
|
|
19
|
+
* Idempotent: destroying an already-destroyed engine is a no-op.
|
|
20
|
+
*/
|
|
21
|
+
export declare function destroyViewState(viewState: EmbeddedRoot): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { destroy, isAlive } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
/**
|
|
3
|
+
* Tear down an engine built by an embedded product's `createViewState`:
|
|
4
|
+
* terminate its RPC worker threads and destroy the MST tree so its
|
|
5
|
+
* `addDisposer`'d autoruns stop.
|
|
6
|
+
*
|
|
7
|
+
* Unmounting the React tree is not enough — the engine is not owned by React.
|
|
8
|
+
* A host that builds and discards engines (a Jupyter cell re-run, an SPA route
|
|
9
|
+
* change, a controller's `destroy()`) otherwise orphans a whole worker pool and
|
|
10
|
+
* a live autorun set per discarded engine. A component that owns one engine for
|
|
11
|
+
* the lifetime of the page never needs this.
|
|
12
|
+
*
|
|
13
|
+
* Idempotent: destroying an already-destroyed engine is a no-op.
|
|
14
|
+
*/
|
|
15
|
+
export function destroyViewState(viewState) {
|
|
16
|
+
if (isAlive(viewState)) {
|
|
17
|
+
// Materialize the session before killing the tree. MST snapshots each dying
|
|
18
|
+
// node on the way down, and snapshotting a node that was never observed
|
|
19
|
+
// instantiates it right then — running its afterAttach during death
|
|
20
|
+
// finalization, where creating a further observable (the config it reads)
|
|
21
|
+
// throws "the creation of the observable instance must be done on the
|
|
22
|
+
// initializing phase". Reachable whenever an engine is destroyed before it
|
|
23
|
+
// ever rendered, which is exactly what React StrictMode does to the
|
|
24
|
+
// build-in-a-ref-callback pattern: mount, clean up, mount again.
|
|
25
|
+
void viewState.session;
|
|
26
|
+
viewState.rpcManager.destroy();
|
|
27
|
+
destroy(viewState);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
1
|
+
export type { AssertExtends, AssertNotAny } from './assertExtends.ts';
|
|
2
|
+
export { asRoot, asSession } from './siblingCast.ts';
|
|
3
|
+
export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.ts';
|
|
4
|
+
export { BaseRootModelFactory, FormatAboutConfigSchemaFactory, FormatDetailsConfigSchemaFactory, HierarchicalConfigSchemaFactory, InternetAccountsRootModelMixin, PreferencesConfigSchemaFactory, createConfigModel, exportSessionMenuItem, importSessionMenuItem, isRootModel, newSessionMenuItem, openConnectionMenuItem, openTrackMenuItem, pluginStoreMenuItem, preferencesMenuItem, redoMenuItem, undoMenuItem, workspacesMenuItem, } from './RootModel/index.ts';
|
|
5
|
+
export type { BaseRootModel, BaseRootModelType, RootConfigurationSnapshot, RootModelWithInternetAccounts, RootModelWithInternetAccountsType, } from './RootModel/index.ts';
|
|
6
|
+
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem, bakePromotedDefaultsIntoSnapshot, bakeSessionCascades, getShareableSessionSnapshot, copyTrackSnapshot, finalizeSession, isBaseSession, isSession, isSessionWithConnections, isSessionWithDrawerWidgets, isSessionWithMultipleViews, isSessionWithReferenceManagement, isSessionWithThemes, isSessionWithTracks, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './Session/index.ts';
|
|
7
|
+
export type { AssertSessionModel, BaseSession, BaseSessionType, ConnectionTrackConfigEntry, EditableTrackConfig, PlainTrackConfig, ReferringNode, SessionWithConnections, SessionWithConnectionsType, SessionWithDrawerWidgets, SessionWithDrawerWidgetsType, SessionWithMultipleViews, SessionWithMultipleViewsType, SessionWithReferenceManagement, SessionWithReferenceManagementType, SessionWithSessionTracks, SessionWithSessionTracksType, SessionWithThemes, SessionWithThemesType, SessionWithTracks, SessionWithTracksType, } from './Session/index.ts';
|
|
8
|
+
export { AboutDialog, Drawer, DrawerControls, DrawerHeader, DrawerWidget, DrawerWidgetSelector, ModalWidget, ModalWidgetAppBar, PreferencesDialog, WidgetBody, WidgetHeading, drawerGridTemplateColumns, } from './ui/index.ts';
|
|
9
|
+
export type { PreferencesDialogSession, PreferencesPanelDescriptor, } from './ui/index.ts';
|
|
10
|
+
export { initializeWorker } from './rpcWorker.ts';
|
|
11
|
+
export { toPluginLoadRecord } from './pluginInput.ts';
|
|
12
|
+
export type { PluginInput } from './pluginInput.ts';
|
|
13
|
+
export { loadRuntimePlugins } from './loadPlugins.ts';
|
|
14
|
+
export type { LoadPluginsArgs } from './loadPlugins.ts';
|
|
15
|
+
export { decodeSessionFromUrl, encodeSessionToUrl } from './sessionUrl.ts';
|
|
16
|
+
export type { SessionSnapshot } from './sessionUrl.ts';
|
|
17
|
+
export { mergeLocalFiles, normalizeAdapterSnapshots, registerLocalFiles, resolveLocalFileUris, } from './localFiles.ts';
|
|
18
|
+
export type { LocalFileInput } from './localFiles.ts';
|
|
19
|
+
export { isLooseTrack, mergeSearchAdapters, openTracks, reconcileTracks, resolveTracks, withAssemblyName, } from './controllerTracks.ts';
|
|
20
|
+
export type { ControllerSession, TrackConf, TrackInput, } from './controllerTracks.ts';
|
|
21
|
+
export { resolveAssemblies, resolveAssembly } from './resolveAssemblies.ts';
|
|
22
|
+
export type { AssemblyInput, ResolvedAssemblies } from './resolveAssemblies.ts';
|
|
23
|
+
export { destroyViewState } from './destroyViewState.ts';
|
|
24
|
+
export { useCreateOnce, useDestroyOnUnmount } from './useEngineLifecycle.ts';
|
|
25
|
+
export { getSessionSnapshot, observeSession } from './observeSession.ts';
|
|
26
|
+
export type { SessionObservers, ViewLocation } from './observeSession.ts';
|
|
27
|
+
export { MIGRATED_DISPLAY_INSTANCE_KEYS, migrateConfigSnapshot, migrateSessionSnapshot, } from './sessionMigrations/index.ts';
|
|
28
|
+
export { DEFAULT_WEB_BASE_URL, analyzeWebPortability, buildWebExportUrl, filterSessionInPlace, planWebExport, } from './sessionUtils.ts';
|
|
29
|
+
export type { AssemblySnapshot, DroppedSessionNode, HostedBaseConfig, NonPortableLocation, SelfContainedReason, TrackSnapshot, WebExportInput, WebExportPlan, WebPortabilityReport, } from './sessionUtils.ts';
|
|
30
|
+
export { describeUnbuildableNodes, pruneUnbuildableNodes, } from './pruneUnbuildableNodes.ts';
|
|
31
|
+
export type { HeldNode, UnbuildableNode } from './pruneUnbuildableNodes.ts';
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
1
|
+
export { asRoot, asSession } from './siblingCast.js';
|
|
2
|
+
export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.js';
|
|
3
|
+
export { BaseRootModelFactory, FormatAboutConfigSchemaFactory, FormatDetailsConfigSchemaFactory, HierarchicalConfigSchemaFactory, InternetAccountsRootModelMixin, PreferencesConfigSchemaFactory, createConfigModel, exportSessionMenuItem, importSessionMenuItem, isRootModel, newSessionMenuItem, openConnectionMenuItem, openTrackMenuItem, pluginStoreMenuItem, preferencesMenuItem, redoMenuItem, undoMenuItem, workspacesMenuItem, } from './RootModel/index.js';
|
|
4
|
+
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem, bakePromotedDefaultsIntoSnapshot, bakeSessionCascades, getShareableSessionSnapshot, copyTrackSnapshot, finalizeSession, isBaseSession, isSession, isSessionWithConnections, isSessionWithDrawerWidgets, isSessionWithMultipleViews, isSessionWithReferenceManagement, isSessionWithThemes, isSessionWithTracks, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './Session/index.js';
|
|
5
|
+
export { AboutDialog, Drawer, DrawerControls, DrawerHeader, DrawerWidget, DrawerWidgetSelector, ModalWidget, ModalWidgetAppBar, PreferencesDialog, WidgetBody, WidgetHeading, drawerGridTemplateColumns, } from './ui/index.js';
|
|
6
|
+
export { initializeWorker } from './rpcWorker.js';
|
|
7
|
+
export { toPluginLoadRecord } from './pluginInput.js';
|
|
8
|
+
export { loadRuntimePlugins } from './loadPlugins.js';
|
|
9
|
+
export { decodeSessionFromUrl, encodeSessionToUrl } from './sessionUrl.js';
|
|
10
|
+
// in-memory files as tracks, for hosts whose data lives in a process rather
|
|
11
|
+
// than at a URL (a notebook kernel, an R session) — read by byte range, so an
|
|
12
|
+
// indexed file stays indexed
|
|
13
|
+
export { mergeLocalFiles, normalizeAdapterSnapshots, registerLocalFiles, resolveLocalFileUris, } from './localFiles.js';
|
|
14
|
+
// the track half of an imperative controller: loose track specs -> configs, and
|
|
15
|
+
// opening exactly the wanted set
|
|
16
|
+
export { isLooseTrack, mergeSearchAdapters, openTracks, reconcileTracks, resolveTracks, withAssemblyName, } from './controllerTracks.js';
|
|
17
|
+
// hub names, sequence URIs and hub configs -> assembly configs, so every
|
|
18
|
+
// product takes the same assembly vocabulary
|
|
19
|
+
export { resolveAssemblies, resolveAssembly } from './resolveAssemblies.js';
|
|
20
|
+
// engine teardown, for a host that builds and discards engines — React unmount
|
|
21
|
+
// alone leaves the RPC workers and autoruns running
|
|
22
|
+
export { destroyViewState } from './destroyViewState.js';
|
|
23
|
+
// the two halves of "React owns this engine", both of which have a StrictMode
|
|
24
|
+
// trap in them that the obvious spelling walks straight into
|
|
25
|
+
export { useCreateOnce, useDestroyOnUnmount } from './useEngineLifecycle.js';
|
|
26
|
+
// the JS -> host direction of an embedded controller: where each view is
|
|
27
|
+
// looking, what got selected, and the layout as plain JSON
|
|
28
|
+
export { getSessionSnapshot, observeSession } from './observeSession.js';
|
|
29
|
+
export { MIGRATED_DISPLAY_INSTANCE_KEYS, migrateConfigSnapshot, migrateSessionSnapshot, } from './sessionMigrations/index.js';
|
|
30
|
+
export { DEFAULT_WEB_BASE_URL, analyzeWebPortability, buildWebExportUrl, filterSessionInPlace, planWebExport, } from './sessionUtils.js';
|
|
31
|
+
export { describeUnbuildableNodes, pruneUnbuildableNodes, } from './pruneUnbuildableNodes.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LoadedPlugin } from '@jbrowse/core/PluginLoader';
|
|
2
|
+
import type { PluginDefinition } from '@jbrowse/core/pluginDefinitions';
|
|
3
|
+
export interface LoadPluginsArgs {
|
|
4
|
+
fetchESM?: (url: string) => Promise<LoadedPlugin>;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve relative plugin urls against this instead of the page. A config
|
|
7
|
+
* fetched from somewhere else names its plugins relative to itself, so pass
|
|
8
|
+
* that config's url — otherwise a `"url": "umd_plugin.js"` entry is looked
|
|
9
|
+
* for next to your own app and 404s.
|
|
10
|
+
*/
|
|
11
|
+
baseUri?: string;
|
|
12
|
+
/** @deprecated the pre-4.4 spelling of `baseUri` */
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The body of every embedded product's `loadPlugins`. Each product keeps its own
|
|
17
|
+
* one-line wrapper, because the doc comment on it is the published API surface
|
|
18
|
+
* and names that product's own entry points — but the behavior is here, so the
|
|
19
|
+
* two things that differed between the copies can't drift again: react-app's
|
|
20
|
+
* accepted no `baseUrl`, and only two of the three defaulted the base url at
|
|
21
|
+
* all.
|
|
22
|
+
*
|
|
23
|
+
* `dropVendored` is the one difference that is real, so it is a required
|
|
24
|
+
* argument rather than a default. A product that bundles the vendored plugins
|
|
25
|
+
* (see `vendoredPluginNames`) must drop a config's entry for them or it installs
|
|
26
|
+
* a second copy beside its own; a product that does not bundle them — the
|
|
27
|
+
* circular-genome-view build has neither MafViewer nor GWAS in its corePlugins —
|
|
28
|
+
* must still fetch one a config names, or the config silently loses the plugin.
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadRuntimePlugins(pluginDefinitions: PluginDefinition[], { dropVendored, jbrowseVersion, ...args }: LoadPluginsArgs & {
|
|
31
|
+
dropVendored: boolean;
|
|
32
|
+
jbrowseVersion: string;
|
|
33
|
+
}): Promise<import("@jbrowse/core/PluginLoader").PluginRecord[]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import PluginLoader from '@jbrowse/core/PluginLoader';
|
|
2
|
+
import { dropVendoredPlugins } from '@jbrowse/core/pluginDefinitions';
|
|
3
|
+
import { resolveStorePluginRefs } from '@jbrowse/core/util';
|
|
4
|
+
/**
|
|
5
|
+
* The body of every embedded product's `loadPlugins`. Each product keeps its own
|
|
6
|
+
* one-line wrapper, because the doc comment on it is the published API surface
|
|
7
|
+
* and names that product's own entry points — but the behavior is here, so the
|
|
8
|
+
* two things that differed between the copies can't drift again: react-app's
|
|
9
|
+
* accepted no `baseUrl`, and only two of the three defaulted the base url at
|
|
10
|
+
* all.
|
|
11
|
+
*
|
|
12
|
+
* `dropVendored` is the one difference that is real, so it is a required
|
|
13
|
+
* argument rather than a default. A product that bundles the vendored plugins
|
|
14
|
+
* (see `vendoredPluginNames`) must drop a config's entry for them or it installs
|
|
15
|
+
* a second copy beside its own; a product that does not bundle them — the
|
|
16
|
+
* circular-genome-view build has neither MafViewer nor GWAS in its corePlugins —
|
|
17
|
+
* must still fetch one a config names, or the config silently loses the plugin.
|
|
18
|
+
*/
|
|
19
|
+
export async function loadRuntimePlugins(pluginDefinitions, { dropVendored, jbrowseVersion, ...args }) {
|
|
20
|
+
// Before dropVendoredPlugins, which matches on the UMD name a ref does not
|
|
21
|
+
// carry until the store supplies it. `jbrowseVersion` is required rather than
|
|
22
|
+
// defaulted so a product that forgets it fails to compile instead of quietly
|
|
23
|
+
// resolving every range against the wrong host.
|
|
24
|
+
const { definitions, failures } = await resolveStorePluginRefs(pluginDefinitions, jbrowseVersion);
|
|
25
|
+
// This path ends in `load`, which is all-or-nothing (see below) — so a ref
|
|
26
|
+
// that resolved to nothing is a failure now rather than a plugin the embedder
|
|
27
|
+
// silently never receives.
|
|
28
|
+
if (failures[0]) {
|
|
29
|
+
throw failures[0].error;
|
|
30
|
+
}
|
|
31
|
+
const pluginLoader = new PluginLoader(dropVendored ? dropVendoredPlugins(definitions) : definitions, args);
|
|
32
|
+
pluginLoader.installGlobalReExports(window);
|
|
33
|
+
// the default matters: `new URL('umd_plugin.js', undefined)` throws, so a
|
|
34
|
+
// relative plugin url used to fail outright instead of resolving against the
|
|
35
|
+
// page the way every other relative url does
|
|
36
|
+
const base = args.baseUri ?? args.baseUrl;
|
|
37
|
+
return pluginLoader.load(base ?? window.location.href);
|
|
38
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
|
+
import type { BlobLocation } from '@jbrowse/core/util';
|
|
3
|
+
/**
|
|
4
|
+
* Bytes for one browser-local file, keyed by the name a track config refers to
|
|
5
|
+
* it by. `Blob`/`File` pass through; anything else (a `Uint8Array` from a
|
|
6
|
+
* notebook kernel's binary channel, an `ArrayBuffer` from a fetch) is wrapped.
|
|
7
|
+
*/
|
|
8
|
+
export type LocalFileInput = Record<string, Blob | BufferSource>;
|
|
9
|
+
/**
|
|
10
|
+
* Register in-memory bytes as browser-local files JBrowse can read, returning
|
|
11
|
+
* the `name -> BlobLocation` map {@link resolveLocalFileUris} substitutes with.
|
|
12
|
+
*
|
|
13
|
+
* This is the escape from "the data has to be on a web server first". A
|
|
14
|
+
* `BlobLocation` opens as a `BlobFile`, which serves byte ranges out of
|
|
15
|
+
* `Blob.slice()` — so a bgzipped+tabixed file, a BAM with its `.bai`, or a
|
|
16
|
+
* bigWig is *seeked into* exactly as if it were remote, and only the bytes the
|
|
17
|
+
* current view needs are ever touched. That is the whole point of doing this
|
|
18
|
+
* rather than inlining features into a config: a 200k-feature table is ~20MB of
|
|
19
|
+
* JSON to serialize, ship, and hold in memory, while the same data as a tabix
|
|
20
|
+
* file is a few MB the view reads a few KB of at a time.
|
|
21
|
+
*
|
|
22
|
+
* For hosts that hold their data in a process rather than at a URL — a notebook
|
|
23
|
+
* kernel, an R session, a desktop app — this is the way in, and it needs no web
|
|
24
|
+
* server, no CORS, and no temporary public bucket.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerLocalFiles(files: LocalFileInput): {
|
|
27
|
+
[k: string]: BlobLocation;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Fold newly-offered files into a controller's registered map, registering only
|
|
31
|
+
* the names it has not seen. Registering is what mints the blobIds, so a host
|
|
32
|
+
* re-stating its whole file set on every update — which is what a declarative
|
|
33
|
+
* host does — pays for each file once rather than once per update.
|
|
34
|
+
*
|
|
35
|
+
* Only ever adds: a name already registered keeps its existing blob, because a
|
|
36
|
+
* live track config points at that blobId and swapping it underneath would
|
|
37
|
+
* leave the track reading bytes nothing else references.
|
|
38
|
+
*/
|
|
39
|
+
export declare function mergeLocalFiles(current: Record<string, BlobLocation>, files: LocalFileInput): {
|
|
40
|
+
[x: string]: BlobLocation;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Expand every shorthand adapter snapshot (`{ type, uri }`) in a config to the
|
|
44
|
+
* canonical location keys its config schema declares, using that adapter type's
|
|
45
|
+
* own `normalizeSnapshot` — the hook that exists so "downstream code can read
|
|
46
|
+
* location keys without knowing each shorthand".
|
|
47
|
+
*
|
|
48
|
+
* {@link resolveLocalFileUris} has to run on the expanded form, and this is the
|
|
49
|
+
* difference between `localFiles` working and silently doing nothing: the
|
|
50
|
+
* shorthand puts `uri` on the *adapter*, so substituting there would replace
|
|
51
|
+
* `{ type: 'BamAdapter', uri: 'x.bam' }` with a bare BlobLocation and take the
|
|
52
|
+
* adapter's type with it. Expanding first moves the name onto `bamLocation`,
|
|
53
|
+
* where it is a location node and substitution is what it looks like. The
|
|
54
|
+
* expansion also derives the conventional index sibling (`.bai`/`.tbi`/`.crai`)
|
|
55
|
+
* from the same string, so registering `x.bam` and `x.bam.bai` is enough and no
|
|
56
|
+
* caller has to know which adapter wanted which file.
|
|
57
|
+
*
|
|
58
|
+
* Idempotent, and a no-op for an already-canonical config or an adapter type
|
|
59
|
+
* that declares no shorthand.
|
|
60
|
+
*/
|
|
61
|
+
export declare function normalizeAdapterSnapshots<T>(config: T, pluginManager: PluginManager): T;
|
|
62
|
+
/**
|
|
63
|
+
* Rewrite every `{ uri: <a registered name> }` in a track config to that file's
|
|
64
|
+
* `BlobLocation`, in place of nothing else — unregistered URIs are left alone,
|
|
65
|
+
* so a config can mix local and remote files freely.
|
|
66
|
+
*
|
|
67
|
+
* Runs on a config whose locations are already canonical, which is what
|
|
68
|
+
* `guessTrackConf` (for a loose track spec) and {@link normalizeAdapterSnapshots}
|
|
69
|
+
* (for a written-out one) each produce. So a host registers `peaks.bed.gz` and
|
|
70
|
+
* `peaks.bed.gz.tbi` under their plain names, the config names both under
|
|
71
|
+
* `bedGzLocation` and `index.location`, and this swaps both for blobs — index
|
|
72
|
+
* and all, with no host-side knowledge of which adapter wanted which sibling.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveLocalFileUris<T>(config: T, locations: Record<string, BlobLocation>): T;
|