@jbrowse/core 5.0.0-beta.2 → 5.0.0-beta.3
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 +70 -40
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
- package/esm/BaseFeatureWidget/index.d.ts +1 -1
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
- package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
- package/esm/BaseFeatureWidget/types.d.ts +10 -2
- package/esm/PluginManager.d.ts +30 -1
- package/esm/PluginManager.js +107 -70
- package/esm/ReExports/BaseFeatureDetails.js +1 -1
- package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
- package/esm/ReExports/MuiDataGridReExports.js +2 -2
- package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
- package/esm/ReExports/barrelOnlyNames.js +63 -0
- package/esm/ReExports/modules.js +28 -56
- package/esm/ReExports/publicTracks.d.ts +1 -0
- package/esm/ReExports/publicTracks.js +14 -0
- package/esm/ReExports/publicUi.d.ts +4 -0
- package/esm/ReExports/publicUi.js +33 -0
- package/esm/ReExports/publicUtil.d.ts +1 -1
- package/esm/ReExports/publicUtil.js +8 -4
- package/esm/ReExports/sharedModules.d.ts +1 -1
- package/esm/ReExports/sharedModules.js +8 -1
- package/esm/ReExports/uiStub.d.ts +1 -0
- package/esm/ReExports/uiStub.js +6 -8
- package/esm/ReExports/workerModules.js +9 -4
- package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
- package/esm/ReExports/workerNamespaceNames.js +281 -0
- package/esm/configuration/configurationSchema.js +11 -0
- package/esm/configuration/index.d.ts +2 -2
- package/esm/configuration/index.js +1 -1
- package/esm/configuration/promotableDefaults.d.ts +54 -19
- package/esm/configuration/promotableDefaults.js +108 -45
- package/esm/configuration/promotablePin.d.ts +50 -40
- package/esm/configuration/promotableResolve.d.ts +1 -1
- package/esm/configuration/promotableResolve.js +1 -1
- package/esm/configuration/tabixIndexFields.d.ts +2 -2
- package/esm/configuration/tabixIndexFields.js +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +4 -12
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +12 -0
- package/esm/data_adapters/BaseAdapter/featureDensity.js +15 -0
- package/esm/data_adapters/BaseAdapter/index.d.ts +2 -2
- package/esm/data_adapters/BaseAdapter/index.js +1 -1
- package/esm/data_adapters/BaseAdapter/types.d.ts +2 -8
- package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
- package/esm/pluggableElementTypes/AdapterType.js +1 -1
- package/esm/pluggableElementTypes/DisplayType.d.ts +3 -10
- package/esm/pluggableElementTypes/DisplayType.js +3 -45
- package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
- package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
- package/esm/pluggableElementTypes/ViewType.d.ts +3 -10
- package/esm/pluggableElementTypes/ViewType.js +6 -51
- package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
- package/esm/pluggableElementTypes/extendElementType.js +1 -2
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +3 -3
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +1 -1
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +1 -4
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +34 -34
- package/esm/pluggableElementTypes/models/BaseViewModel.js +19 -30
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +4 -3
- package/esm/pluggableElementTypes/models/assertDisplayContract.js +2 -2
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
- package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
- package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
- package/esm/ui/ExportSvgDialog.d.ts +1 -1
- package/esm/ui/MenuTypes.d.ts +3 -3
- package/esm/ui/PinAdornment.js +22 -40
- package/esm/ui/ScrollChrome.d.ts +16 -0
- package/esm/ui/ScrollChrome.js +12 -0
- package/esm/ui/ScrollZoomToggle.d.ts +4 -3
- package/esm/ui/ScrollZoomToggle.js +4 -3
- package/esm/ui/SizeSliderRow.js +1 -1
- package/esm/ui/index.d.ts +2 -2
- package/esm/ui/index.js +3 -3
- package/esm/ui/legendMenuItem.d.ts +9 -15
- package/esm/ui/legendMenuItem.js +8 -19
- package/esm/ui/menuItemAdornment.d.ts +2 -3
- package/esm/ui/menuItemAdornment.js +2 -3
- package/esm/ui/menuItems.d.ts +1 -2
- package/esm/ui/menuItems.js +0 -1
- package/esm/ui/palette.d.ts +11 -11
- package/esm/ui/palette.js +11 -11
- package/esm/ui/promotablePinCoverage.d.ts +16 -2
- package/esm/ui/promotablePinCoverage.js +38 -2
- package/esm/ui/theme.js +5 -0
- package/esm/ui/toggleMenuItems.d.ts +13 -6
- package/esm/ui/toggleMenuItems.js +32 -15
- package/esm/util/Base1DUtils.d.ts +4 -2
- package/esm/util/Base1DUtils.js +12 -4
- package/esm/util/SvgCanvas.js +4 -3
- package/esm/util/adapterConfigKey.d.ts +12 -0
- package/esm/util/adapterConfigKey.js +14 -0
- package/esm/util/adapterMetadata.js +2 -1
- package/esm/util/analytics.js +4 -5
- package/esm/util/clampToContig.d.ts +17 -0
- package/esm/util/clampToContig.js +19 -0
- package/esm/util/colorBits.d.ts +2 -1
- package/esm/util/colorBits.js +2 -5
- package/esm/util/createStopTokenRotation.d.ts +8 -7
- package/esm/util/featureTypes.d.ts +24 -0
- package/esm/util/featureTypes.js +35 -0
- package/esm/util/fetchPhases.d.ts +1 -1
- package/esm/util/index.d.ts +4 -2
- package/esm/util/index.js +3 -1
- package/esm/util/installFetch.d.ts +29 -18
- package/esm/util/installFetch.js +17 -17
- package/esm/util/installInitAutorun.d.ts +6 -5
- package/esm/util/installInitAutorun.js +2 -2
- package/esm/util/installPrerequisiteFetch.d.ts +86 -0
- package/esm/util/installPrerequisiteFetch.js +73 -0
- package/esm/util/openFeatureWidget.d.ts +5 -0
- package/esm/util/openFeatureWidget.js +1 -0
- package/esm/util/openViews.d.ts +16 -0
- package/esm/util/openViews.js +22 -0
- package/esm/util/parentWalk.d.ts +1 -1
- package/esm/util/parentWalk.js +1 -1
- package/esm/util/renderToStaticMarkup.js +10 -0
- package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
- package/esm/util/scheduleDetachedDestroy.js +24 -0
- package/esm/util/scrollLatch.d.ts +1 -0
- package/esm/util/scrollLatch.js +8 -0
- package/esm/util/stopToken.d.ts +6 -5
- package/esm/util/trackConfigDelta.d.ts +6 -6
- package/esm/util/trackConfigDelta.js +3 -3
- package/esm/util/types/index.d.ts +25 -20
- package/esm/util/usePanelVirtualScroll.d.ts +6 -2
- package/esm/util/usePanelVirtualScroll.js +6 -2
- package/esm/util/useRowVirtualScroll.d.ts +1 -1
- package/esm/util/useRowVirtualScroll.js +1 -1
- package/esm/util/useVirtualScrollWheel.js +11 -1
- package/esm/util/wheelZoom.d.ts +3 -1
- package/esm/util/wheelZoom.js +39 -14
- package/esm/util/withLaunchInput.d.ts +47 -2
- package/esm/util/withLaunchInput.js +56 -11
- package/package.json +10 -5
- package/esm/ui/promotableMenuItems.d.ts +0 -19
- package/esm/ui/promotableMenuItems.js +0 -91
package/esm/util/colorBits.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { abgrToCssRgba } from '@jbrowse/render-core/marks/colorFill';
|
|
1
2
|
import { getAlpha, getBlue, getGreen, getRed, newColor, parse, } from './color-bits/index.js';
|
|
2
3
|
import { namedColorToHex } from './color/cssColorsLevel4.js';
|
|
4
|
+
export { abgrToCssRgba };
|
|
3
5
|
export { alpha, blend, darken, formatHEX, formatHEXA, formatRGBA, getAlpha, getBlue, getGreen, getLuminance, getRed, lighten, newColor, parse, toHSLA, toRGBA, } from './color-bits/index.js';
|
|
4
6
|
// Magenta sentinel for invalid input. User-written jexl color callbacks can
|
|
5
7
|
// legitimately return undefined (e.g. when a feature lacks the field they
|
|
@@ -143,7 +145,6 @@ export function normalizedRgbToCss(c) {
|
|
|
143
145
|
export function normalizedRgbToCssRgba(c, alpha) {
|
|
144
146
|
return `rgba(${Math.round(c[0] * 255)},${Math.round(c[1] * 255)},${Math.round(c[2] * 255)},${alpha})`;
|
|
145
147
|
}
|
|
146
|
-
// Set fillStyle from an ABGR-packed u32.
|
|
147
148
|
export function setAbgrFill(ctx, c) {
|
|
148
149
|
ctx.fillStyle = abgrToCssRgba(c);
|
|
149
150
|
}
|
|
@@ -165,10 +166,6 @@ export function abgrBlue(c) {
|
|
|
165
166
|
export function abgrAlpha(c) {
|
|
166
167
|
return (c >>> 24) & 0xff;
|
|
167
168
|
}
|
|
168
|
-
// Format an ABGR-packed u32 as a CSS rgba() string.
|
|
169
|
-
export function abgrToCssRgba(c) {
|
|
170
|
-
return `rgba(${abgrRed(c)},${abgrGreen(c)},${abgrBlue(c)},${abgrAlpha(c) / 255})`;
|
|
171
|
-
}
|
|
172
169
|
export function cssColorToNormalizedRgba(color) {
|
|
173
170
|
const c = parseCssColor(color);
|
|
174
171
|
return [
|
|
@@ -13,19 +13,20 @@ import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
|
13
13
|
*/
|
|
14
14
|
export type StatusReporter = {
|
|
15
15
|
/**
|
|
16
|
-
* The host's own window, present on any display composing
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* The host's own window, present on any display composing `FetchMixin`.
|
|
17
|
+
* The rotation reports through it rather than opening a SECOND on the
|
|
18
|
+
* same status field — which is what one-window-per-owner exists to
|
|
19
19
|
* prevent.
|
|
20
20
|
*/
|
|
21
21
|
statusWindow: StatusWindow;
|
|
22
22
|
setStatusMessage?: never;
|
|
23
23
|
} | {
|
|
24
24
|
/**
|
|
25
|
-
* The sink for the window the rotation opens for itself
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* {@link createStatusChannel} holder.
|
|
25
|
+
* The sink for the window the rotation opens for itself: the mode of a
|
|
26
|
+
* fetch on a host with no window of its own — the prerequisite reads,
|
|
27
|
+
* chord, the breakpoint overlay — along with every
|
|
28
|
+
* {@link createStatusChannel} holder. The comparative displays this
|
|
29
|
+
* helper was written for lend a window now (ADR-105).
|
|
29
30
|
*/
|
|
30
31
|
setStatusMessage: (status?: RpcStatus) => void;
|
|
31
32
|
statusWindow?: never;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classification of a feature from its `type` string alone, for the plugins
|
|
3
|
+
* that decide something about a feature they did not parse. A type is the only
|
|
4
|
+
* thing a display, a menu or a widget can ask about a feature without knowing
|
|
5
|
+
* which adapter produced it, so these live in core rather than beside any one
|
|
6
|
+
* of their callers.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Whether the type names a unit of transcription — a gene, a transcript, or an
|
|
10
|
+
* RNA, including the pseudogene and V(D)J segment spellings. This is the
|
|
11
|
+
* question "does this feature have exons", not "can this feature be spliced":
|
|
12
|
+
* an alignment splices too and is deliberately not gene-like, because a caller
|
|
13
|
+
* that means to launch a protein view or read a CDS would be wrong about it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isGeneLikeType(type: string | undefined): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the type names a sequence alignment — SO `match` and its subtypes
|
|
18
|
+
* (`cDNA_match`, `EST_match`, `nucleotide_match`, `protein_match`,
|
|
19
|
+
* `translated_nucleotide_match`), whose `match_part` children are the aligned
|
|
20
|
+
* blocks and whose gaps between them are introns when the aligned sequence was
|
|
21
|
+
* a transcript. Separate from `isGeneLikeType` on purpose: an EST alignment is
|
|
22
|
+
* evidence for a gene, not one.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isSequenceMatchType(type: string | undefined): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classification of a feature from its `type` string alone, for the plugins
|
|
3
|
+
* that decide something about a feature they did not parse. A type is the only
|
|
4
|
+
* thing a display, a menu or a widget can ask about a feature without knowing
|
|
5
|
+
* which adapter produced it, so these live in core rather than beside any one
|
|
6
|
+
* of their callers.
|
|
7
|
+
*/
|
|
8
|
+
// Anchored at the end for gene and RNA so 'intergenic_region' is not a gene and
|
|
9
|
+
// 'rnapol_binding_site' is not an RNA. Unanchored for transcript, which SO
|
|
10
|
+
// spells both ways ('transcript', 'pseudogenic_transcript', 'transcript_region').
|
|
11
|
+
const GENE_LIKE_TYPE = /gene(_segment)?$|rna$|transcript/;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the type names a unit of transcription — a gene, a transcript, or an
|
|
14
|
+
* RNA, including the pseudogene and V(D)J segment spellings. This is the
|
|
15
|
+
* question "does this feature have exons", not "can this feature be spliced":
|
|
16
|
+
* an alignment splices too and is deliberately not gene-like, because a caller
|
|
17
|
+
* that means to launch a protein view or read a CDS would be wrong about it.
|
|
18
|
+
*/
|
|
19
|
+
export function isGeneLikeType(type) {
|
|
20
|
+
return type !== undefined && GENE_LIKE_TYPE.test(type.toLowerCase());
|
|
21
|
+
}
|
|
22
|
+
// SO `match` and every subtype of it is spelled `<something>_match`, so the
|
|
23
|
+
// suffix is the family. `match_part`, the child, is excluded by the anchor.
|
|
24
|
+
const SEQUENCE_MATCH_TYPE = /(^|_)match$/;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the type names a sequence alignment — SO `match` and its subtypes
|
|
27
|
+
* (`cDNA_match`, `EST_match`, `nucleotide_match`, `protein_match`,
|
|
28
|
+
* `translated_nucleotide_match`), whose `match_part` children are the aligned
|
|
29
|
+
* blocks and whose gaps between them are introns when the aligned sequence was
|
|
30
|
+
* a transcript. Separate from `isGeneLikeType` on purpose: an EST alignment is
|
|
31
|
+
* evidence for a gene, not one.
|
|
32
|
+
*/
|
|
33
|
+
export function isSequenceMatchType(type) {
|
|
34
|
+
return type !== undefined && SEQUENCE_MATCH_TYPE.test(type.toLowerCase());
|
|
35
|
+
}
|
|
@@ -43,7 +43,7 @@ export interface FetchPhases<TArgs, TResult, TCtx> {
|
|
|
43
43
|
* gets a dead Retry button — see there.
|
|
44
44
|
*
|
|
45
45
|
* What it must **not** do is move a trigger read of its own under a bail-out.
|
|
46
|
-
* See
|
|
46
|
+
* See reference/FETCH_SKELETON.md §"The global-fetch trigger list must be read
|
|
47
47
|
* unconditionally".
|
|
48
48
|
*/
|
|
49
49
|
prepare: () => TArgs | undefined;
|
package/esm/util/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export { MAX_ZOOM_RATE_PER_MS, SCROLL_ZOOM_FACTOR_DIVISOR, ZOOM_ACTIVE_WINDOW_MS
|
|
|
22
22
|
export { avg, clamp, getDisplayStr, getNumberGrouping, max, maxFinite, min, minmax, polarToCartesian, radToDeg, reducePrecision, setNumberGrouping, sum, toLocale, } from './numericUtils.ts';
|
|
23
23
|
export { type MinimalRegion, bpSpanPx, bpToPx, bytesForRegions, featureSpanPx, getBpDisplayStr, getTickDisplayStr, parseBpString, } from './bpUtils.ts';
|
|
24
24
|
export { type BasicFeature, gatherOverlaps, mergeIntervals, } from './intervals.ts';
|
|
25
|
-
export { clampToContig } from './clampToContig.ts';
|
|
25
|
+
export { clampToContig, clampToListedContig } from './clampToContig.ts';
|
|
26
26
|
export { animationAllowed } from './animationAllowed.ts';
|
|
27
27
|
export { springAnimate } from './springAnimate.ts';
|
|
28
28
|
export { localStorageAvailable, localStorageGetBoolean, localStorageGetItem, localStorageGetJSON, localStorageGetNumber, localStorageGetStringArray, localStorageRemoveItem, localStorageSetBoolean, localStorageSetItem, localStorageSetJSON, localStorageSetNumber, notifyLocalStorageKey, subscribeToLocalStorageKey, } from './localStorage.ts';
|
|
@@ -44,7 +44,7 @@ export { downloadPhase, getLocationUri, resolveUri } from './getLocationUri.ts';
|
|
|
44
44
|
export { measureGridWidth, resolveSelectedIds } from './dataGridUtils.ts';
|
|
45
45
|
export { isRpcResult } from './rpc.ts';
|
|
46
46
|
export { aesDecrypt, aesEncrypt, sha256, sha256Base64, sha256Base64Url, toBase64, toBase64Url, } from './crypto.ts';
|
|
47
|
-
export { type FeatureWidgetTypeRef, notifyFeatureDetailsMiss, openFeatureWidget, } from './openFeatureWidget.ts';
|
|
47
|
+
export { type FeatureWidgetTypeRef, type ParentFeatureSummary, notifyFeatureDetailsMiss, openFeatureWidget, } from './openFeatureWidget.ts';
|
|
48
48
|
export { withFeatureDetails } from './withFeatureDetails.ts';
|
|
49
49
|
export { canonicalizeViewRefName, findParentThat, findParentThatIs, getAssemblyHost, getContainingDisplay, getContainingTrack, getContainingView, getEnv, getRenderingServices, launchOrReplaceView, getSession, hashCode, objectHash, } from './mstUtils.ts';
|
|
50
50
|
export { getDialogHost, getNotificationSink, getPaletteHost, getRpcHost, getSessionServices, } from './sessionServices.ts';
|
|
@@ -68,9 +68,11 @@ export { saveAs } from './FileSaver/index.ts';
|
|
|
68
68
|
export { type SaveSvgAsImageOptions, saveSvgAsImage, svgHtmlToPngBlob, } from '../svg/saveSvgAsImage.ts';
|
|
69
69
|
export { type ActiveFetch, type StatusChannel, type StatusReporter, createStatusChannel, createStopTokenRotation, } from './createStopTokenRotation.ts';
|
|
70
70
|
export { createSharedSetup } from './cachedSetup.ts';
|
|
71
|
+
export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.ts';
|
|
71
72
|
export { isDataCurrent } from './isDataCurrent.ts';
|
|
72
73
|
export { handleFetchError, isAbortException, makeAbortError, } from './aborting.ts';
|
|
73
74
|
export { linkify } from './linkify.ts';
|
|
75
|
+
export { isGeneLikeType, isSequenceMatchType } from './featureTypes.ts';
|
|
74
76
|
export { locStringsToRegions } from './locStringsToRegions.ts';
|
|
75
77
|
export type { RefNameSource } from './locStringsToRegions.ts';
|
|
76
78
|
export { type ParsedLocString, UnknownRefNameError, assembleLocString, assembleLocStringRaw, assembleLocStrings, compareLocStrings, compareLocs, parseLocString, parseLocStringOneBased, stringify, } from './locString.ts';
|
package/esm/util/index.js
CHANGED
|
@@ -29,7 +29,7 @@ export { MAX_ZOOM_RATE_PER_MS, SCROLL_ZOOM_FACTOR_DIVISOR, ZOOM_ACTIVE_WINDOW_MS
|
|
|
29
29
|
export { avg, clamp, getDisplayStr, getNumberGrouping, max, maxFinite, min, minmax, polarToCartesian, radToDeg, reducePrecision, setNumberGrouping, sum, toLocale, } from './numericUtils.js';
|
|
30
30
|
export { bpSpanPx, bpToPx, bytesForRegions, featureSpanPx, getBpDisplayStr, getTickDisplayStr, parseBpString, } from './bpUtils.js';
|
|
31
31
|
export { gatherOverlaps, mergeIntervals, } from './intervals.js';
|
|
32
|
-
export { clampToContig } from './clampToContig.js';
|
|
32
|
+
export { clampToContig, clampToListedContig } from './clampToContig.js';
|
|
33
33
|
export { animationAllowed } from './animationAllowed.js';
|
|
34
34
|
export { springAnimate } from './springAnimate.js';
|
|
35
35
|
export { localStorageAvailable, localStorageGetBoolean, localStorageGetItem, localStorageGetJSON, localStorageGetNumber, localStorageGetStringArray, localStorageRemoveItem, localStorageSetBoolean, localStorageSetItem, localStorageSetJSON, localStorageSetNumber, notifyLocalStorageKey, subscribeToLocalStorageKey, } from './localStorage.js';
|
|
@@ -141,9 +141,11 @@ export { createStatusChannel, createStopTokenRotation, } from './createStopToken
|
|
|
141
141
|
// through `fetchContext.ts`, which imports this barrel, so exporting it makes
|
|
142
142
|
// the barrel initialize itself. Import it from `@jbrowse/core/util/installFetch`.
|
|
143
143
|
export { createSharedSetup } from './cachedSetup.js';
|
|
144
|
+
export { scheduleDetachedDestroy } from './scheduleDetachedDestroy.js';
|
|
144
145
|
export { isDataCurrent } from './isDataCurrent.js';
|
|
145
146
|
export { handleFetchError, isAbortException, makeAbortError, } from './aborting.js';
|
|
146
147
|
export { linkify } from './linkify.js';
|
|
148
|
+
export { isGeneLikeType, isSequenceMatchType } from './featureTypes.js';
|
|
147
149
|
export { locStringsToRegions } from './locStringsToRegions.js';
|
|
148
150
|
export { UnknownRefNameError, assembleLocString, assembleLocStringRaw, assembleLocStrings, compareLocStrings, compareLocs, parseLocString, parseLocStringOneBased, stringify, } from './locString.js';
|
|
149
151
|
export { checkStopToken, checkStopTokenThrottled, createStopToken, createStopTokenChecker, hasSharedArrayBuffer, isStopToken, isStopped, markStopTokenStopped, registerStopTokenBroadcaster, stopStopToken, stopTokenSignal, withStopTokenCheck, withStopTokenSignal, } from './stopToken.js';
|
|
@@ -25,7 +25,7 @@ export interface FetchLifecycle {
|
|
|
25
25
|
/**
|
|
26
26
|
* Runs synchronously as the fetch starts, after the rotation has superseded
|
|
27
27
|
* whatever it replaced: the loading flag (`FetchMixin`'s `activeStopToken`,
|
|
28
|
-
*
|
|
28
|
+
* through `fetchMixinLifecycle`), and anything a display blanks
|
|
29
29
|
* because it has no freshness signature to keep stale data honest with
|
|
30
30
|
* (chord's refName map).
|
|
31
31
|
*
|
|
@@ -127,7 +127,7 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
|
|
|
127
127
|
* also be invalidated by `reload()`, or Retry re-runs the body straight into
|
|
128
128
|
* the same decline and the button is dead. Every layer that has one made
|
|
129
129
|
* that pairing structural in the end — the global family after arc shipped
|
|
130
|
-
* the bug (`GlobalFetchMixin.reload` drops `
|
|
130
|
+
* the bug (`GlobalFetchMixin.reload` drops `loadedFetchKey` in the same
|
|
131
131
|
* action as the bump) — and this is that move for the skeleton: a run whose
|
|
132
132
|
* `reloadCounter` has advanced since the run that last ISSUED a fetch ignores
|
|
133
133
|
* this gate, so nothing has to remember to clear anything. The multi-way
|
|
@@ -146,10 +146,10 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
|
|
|
146
146
|
*/
|
|
147
147
|
fetchKey?: (args: TArgs) => string;
|
|
148
148
|
/**
|
|
149
|
-
* The key of the data already committed, when the host keeps one —
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
149
|
+
* The key of the data already committed, when the host keeps one —
|
|
150
|
+
* `KeyedFetchMixin` stamps `loadedFetchKey`, which its `dataCurrent` reads
|
|
151
|
+
* too, so a second stamp would be one more thing to disagree with it.
|
|
152
|
+
* Omitted, the skeleton stamps its own at commit.
|
|
153
153
|
*
|
|
154
154
|
* **Either way the stamp is observable**, and the read is tracked. Zoom A→B
|
|
155
155
|
* issues a fetch for B; zoom back to A before B commits and the re-run
|
|
@@ -157,7 +157,21 @@ interface InstallFetchOptionsBase<TArgs, TResult> extends FetchPhases<TArgs, TRe
|
|
|
157
157
|
* write is what wakes the autorun to fetch A again. A closure variable would
|
|
158
158
|
* leave data B under viewport A until the next input moved.
|
|
159
159
|
*/
|
|
160
|
-
|
|
160
|
+
loadedKey?: () => string | undefined;
|
|
161
|
+
/**
|
|
162
|
+
* The predicate form of the freshness gate, for a fetch whose "I have exactly
|
|
163
|
+
* this already" is not string equality: the density tier holds bins over a
|
|
164
|
+
* buffered read and answers a viewport those bins *contain*, which no key can
|
|
165
|
+
* spell. Same rules as `fetchKey` — declined runs report `declined`, and a
|
|
166
|
+
* `reloadCounter` advanced since the last issued fetch overrides it — so the
|
|
167
|
+
* comparison lives here and not in `prepare`, where a reload could not reach
|
|
168
|
+
* it. Runs inside the autorun, so what it reads is tracked: read the
|
|
169
|
+
* committed state off an observable, and the commit that changes the answer
|
|
170
|
+
* wakes the declined run.
|
|
171
|
+
*
|
|
172
|
+
* Either this or `fetchKey`, not both.
|
|
173
|
+
*/
|
|
174
|
+
heldAnswers?: (args: TArgs) => boolean;
|
|
161
175
|
/**
|
|
162
176
|
* Install the two display-contract checks under this name. Omitted
|
|
163
177
|
* by a **secondary** fetch on a host whose primary foundation already
|
|
@@ -197,12 +211,13 @@ export type InstallFetchOptions<TArgs, TResult> = InstallFetchOptionsBase<TArgs,
|
|
|
197
211
|
* unconditional trigger reads, the gates, and {@link runFetchOnce} under them.
|
|
198
212
|
*
|
|
199
213
|
* Every fetch in the tree is this shape except one family — the prerequisite
|
|
200
|
-
* reads (HiC's header, the multi-sample sample list), the
|
|
201
|
-
* (`installGlobalFetchAutorun
|
|
202
|
-
* `rotation` option so `cancelFetch`
|
|
203
|
-
*
|
|
204
|
-
* fetch and the multi-way synteny display's two
|
|
205
|
-
* lane links, each gated on the key its own
|
|
214
|
+
* reads (HiC's header, the multi-sample sample list), the two keyed families
|
|
215
|
+
* (`installGlobalFetchAutorun` and `installComparativeFetchAutorun`, which lend
|
|
216
|
+
* `FetchMixin`'s rotation through the `rotation` option so `cancelFetch` and
|
|
217
|
+
* the Cancel button reach the fetch they install), the circular view's chord
|
|
218
|
+
* fetch, the breakpoint overlay fetch and the multi-way synteny display's two
|
|
219
|
+
* DEPENDENT fetches (lane genes, lane links, each gated on the key its own
|
|
220
|
+
* commit stamps) all take it. The
|
|
206
221
|
* exception is the per-region family's `FetchMixin.runFetch`: its trigger is
|
|
207
222
|
* `planRegionFetch`'s autorun and its commits stream per region through
|
|
208
223
|
* `ctx.commitRegion`, so it holds `runFetchOnce` directly and the autorun above
|
|
@@ -211,10 +226,6 @@ export type InstallFetchOptions<TArgs, TResult> = InstallFetchOptionsBase<TArgs,
|
|
|
211
226
|
* What a caller supplies is exactly what differs between them: which reads wake
|
|
212
227
|
* it (`prepare`, plus `gate`), what a round trip commits, where the loading
|
|
213
228
|
* flag lives (`onBegin` / `onEnd`) and where the status goes (`report`).
|
|
214
|
-
*
|
|
215
|
-
* Returns the rotation's `cancel`, for a family whose model owns the user-facing
|
|
216
|
-
* Cancel button: the flag alone is not a cancel — nothing rotates the token, the
|
|
217
|
-
* stopped RPC stays current, and it commits over the load the user just stopped.
|
|
218
229
|
*/
|
|
219
|
-
export declare function installFetch<TArgs, TResult>(self: FetchSkeletonHost, opts: InstallFetchOptions<TArgs, TResult>):
|
|
230
|
+
export declare function installFetch<TArgs, TResult>(self: FetchSkeletonHost, opts: InstallFetchOptions<TArgs, TResult>): void;
|
|
220
231
|
export {};
|
package/esm/util/installFetch.js
CHANGED
|
@@ -90,12 +90,13 @@ function ownRotation(self, report) {
|
|
|
90
90
|
* unconditional trigger reads, the gates, and {@link runFetchOnce} under them.
|
|
91
91
|
*
|
|
92
92
|
* Every fetch in the tree is this shape except one family — the prerequisite
|
|
93
|
-
* reads (HiC's header, the multi-sample sample list), the
|
|
94
|
-
* (`installGlobalFetchAutorun
|
|
95
|
-
* `rotation` option so `cancelFetch`
|
|
96
|
-
*
|
|
97
|
-
* fetch and the multi-way synteny display's two
|
|
98
|
-
* lane links, each gated on the key its own
|
|
93
|
+
* reads (HiC's header, the multi-sample sample list), the two keyed families
|
|
94
|
+
* (`installGlobalFetchAutorun` and `installComparativeFetchAutorun`, which lend
|
|
95
|
+
* `FetchMixin`'s rotation through the `rotation` option so `cancelFetch` and
|
|
96
|
+
* the Cancel button reach the fetch they install), the circular view's chord
|
|
97
|
+
* fetch, the breakpoint overlay fetch and the multi-way synteny display's two
|
|
98
|
+
* DEPENDENT fetches (lane genes, lane links, each gated on the key its own
|
|
99
|
+
* commit stamps) all take it. The
|
|
99
100
|
* exception is the per-region family's `FetchMixin.runFetch`: its trigger is
|
|
100
101
|
* `planRegionFetch`'s autorun and its commits stream per region through
|
|
101
102
|
* `ctx.commitRegion`, so it holds `runFetchOnce` directly and the autorun above
|
|
@@ -104,13 +105,9 @@ function ownRotation(self, report) {
|
|
|
104
105
|
* What a caller supplies is exactly what differs between them: which reads wake
|
|
105
106
|
* it (`prepare`, plus `gate`), what a round trip commits, where the loading
|
|
106
107
|
* flag lives (`onBegin` / `onEnd`) and where the status goes (`report`).
|
|
107
|
-
*
|
|
108
|
-
* Returns the rotation's `cancel`, for a family whose model owns the user-facing
|
|
109
|
-
* Cancel button: the flag alone is not a cancel — nothing rotates the token, the
|
|
110
|
-
* stopped RPC stays current, and it commits over the load the user just stopped.
|
|
111
108
|
*/
|
|
112
109
|
export function installFetch(self, opts) {
|
|
113
|
-
const { name, delay, gate, contract, fetchKey,
|
|
110
|
+
const { name, delay, gate, contract, fetchKey, loadedKey, heldAnswers, prepare, run, commit, setError, onBegin, onEnd, } = opts;
|
|
114
111
|
const noteFetchAutorunRun = contract === undefined ? undefined : installContractChecks(self, contract);
|
|
115
112
|
const lent = opts.rotation;
|
|
116
113
|
const rotation = lent === undefined ? ownRotation(self, opts.report) : lent;
|
|
@@ -122,10 +119,16 @@ export function installFetch(self, opts) {
|
|
|
122
119
|
// The skeleton's own stamp exists only where there is a key to stamp — a
|
|
123
120
|
// fetch with no `fetchKey` never reads it, so allocating one would only feed
|
|
124
121
|
// it `undefined` on every commit.
|
|
125
|
-
const stamp =
|
|
122
|
+
const stamp = loadedKey === undefined && fetchKey !== undefined
|
|
126
123
|
? observable.box()
|
|
127
124
|
: undefined;
|
|
128
|
-
const heldKey =
|
|
125
|
+
const heldKey = loadedKey ?? (() => stamp?.get());
|
|
126
|
+
// the freshness gate in whichever form the caller declared it
|
|
127
|
+
const held = heldAnswers !== undefined
|
|
128
|
+
? heldAnswers
|
|
129
|
+
: fetchKey !== undefined
|
|
130
|
+
? (args) => isDataCurrent(heldKey(), fetchKey(args))
|
|
131
|
+
: undefined;
|
|
129
132
|
const commitAndStamp = stamp
|
|
130
133
|
? (result, args) => {
|
|
131
134
|
runInAction(() => {
|
|
@@ -173,9 +176,7 @@ export function installFetch(self, opts) {
|
|
|
173
176
|
// consuming the retry here costs nothing — while a reload landing
|
|
174
177
|
// mid-flight is answered by the re-run the counter read above already
|
|
175
178
|
// guarantees.
|
|
176
|
-
if (
|
|
177
|
-
isDataCurrent(heldKey(), fetchKey(args)) &&
|
|
178
|
-
reloadEpoch === issuedEpoch) {
|
|
179
|
+
if (held !== undefined && held(args) && reloadEpoch === issuedEpoch) {
|
|
179
180
|
noteFetchAutorunRun?.('declined');
|
|
180
181
|
return false;
|
|
181
182
|
}
|
|
@@ -202,5 +203,4 @@ export function installFetch(self, opts) {
|
|
|
202
203
|
},
|
|
203
204
|
// #endregion
|
|
204
205
|
{ name, delay });
|
|
205
|
-
return rotation.cancel;
|
|
206
206
|
}
|
|
@@ -26,9 +26,10 @@ interface InitAutorunOptions<T> {
|
|
|
26
26
|
*/
|
|
27
27
|
ready: () => boolean;
|
|
28
28
|
/**
|
|
29
|
-
* Whether the view has materialized — the
|
|
30
|
-
*
|
|
31
|
-
* synteny: rows built). Decides the failure policy, see
|
|
29
|
+
* Whether the view has materialized — the line `withLaunchInput`'s
|
|
30
|
+
* `materialized` draws for persistence, read from the live node (dotplot:
|
|
31
|
+
* assemblyNames set; synteny: rows built). Decides the failure policy, see
|
|
32
|
+
* below.
|
|
32
33
|
*/
|
|
33
34
|
materialized: () => boolean;
|
|
34
35
|
/** Apply one init blob. Owns the ordered steps; never clears `init`. */
|
|
@@ -40,8 +41,8 @@ interface InitAutorunOptions<T> {
|
|
|
40
41
|
* the readiness gate, the serialized drain, the identity-checked clear, the
|
|
41
42
|
* isAlive guards, and one failure policy.
|
|
42
43
|
*
|
|
43
|
-
* The failure policy keys off `materialized`, the same line
|
|
44
|
-
*
|
|
44
|
+
* The failure policy keys off `materialized`, the same line `withLaunchInput`
|
|
45
|
+
* draws for persistence:
|
|
45
46
|
*
|
|
46
47
|
* - Not materialized — nothing is on screen and `launch` is still persisted, so
|
|
47
48
|
* keep it for a reload retry and `setError`. That flips the view onto its
|
|
@@ -58,8 +58,8 @@ async function drainInit(self, opts) {
|
|
|
58
58
|
* the readiness gate, the serialized drain, the identity-checked clear, the
|
|
59
59
|
* isAlive guards, and one failure policy.
|
|
60
60
|
*
|
|
61
|
-
* The failure policy keys off `materialized`, the same line
|
|
62
|
-
*
|
|
61
|
+
* The failure policy keys off `materialized`, the same line `withLaunchInput`
|
|
62
|
+
* draws for persistence:
|
|
63
63
|
*
|
|
64
64
|
* - Not materialized — nothing is on screen and `launch` is still persisted, so
|
|
65
65
|
* keep it for a reload retry and `setError`. That flips the view onto its
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { StatusReporter } from './createStopTokenRotation.ts';
|
|
2
|
+
import type { FetchContext } from './fetchContext.ts';
|
|
3
|
+
import type { FetchSkeletonHost } from './installFetch.ts';
|
|
4
|
+
/**
|
|
5
|
+
* What a prerequisite read needs of the display it runs on, beside the
|
|
6
|
+
* skeleton's own three. Duck-typed rather than a foundation's `Instance` type,
|
|
7
|
+
* because the hosts compose different foundations — one per fetch family, and
|
|
8
|
+
* the comparative displays compose none of them — and this is the only thing
|
|
9
|
+
* they have in common.
|
|
10
|
+
*/
|
|
11
|
+
export interface PrerequisiteFetchHost extends FetchSkeletonHost {
|
|
12
|
+
/**
|
|
13
|
+
* Read in `prepare`, so it is **tracked**: an adapter edited in the config
|
|
14
|
+
* editor has to re-read, and `run`'s own reads are untracked by contract.
|
|
15
|
+
*/
|
|
16
|
+
adapterConfig: Record<string, unknown>;
|
|
17
|
+
isMinimized: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A **prerequisite read**: one RPC about the adapter itself, beside the
|
|
21
|
+
* display's primary fetch. Three in the tree — HiC's `CoreGetInfo` header read,
|
|
22
|
+
* whose `resolutions` every contacts fetch waits on; the multi-sample sample
|
|
23
|
+
* list, which `fetchNeeded` declines until; and the tiered alignment file's
|
|
24
|
+
* `CoreGetInfo` header, which decides the LOD tier a synteny fetch asks for —
|
|
25
|
+
* and they sit on three different fetch foundations, which is why this sits in
|
|
26
|
+
* core beside the skeleton and not beside any of them.
|
|
27
|
+
*
|
|
28
|
+
* They had the shape below hand-copied, comment for comment, and each term is a
|
|
29
|
+
* rule rather than a preference:
|
|
30
|
+
*
|
|
31
|
+
* - **the adapter config is the whole trigger and the whole key.** Tracked in
|
|
32
|
+
* `prepare` so a config-editor edit re-reads; keyed on the same value so an
|
|
33
|
+
* un-minimize over the same file re-reads nothing. Getting one without the
|
|
34
|
+
* other gives either a stale header or a walk of a `.hic` norm-vector index on
|
|
35
|
+
* every expand.
|
|
36
|
+
* - **minimized is the gate**, and a display with a second condition of its own
|
|
37
|
+
* passes `gate` — the sample-list read waits for the LGV to be measured as
|
|
38
|
+
* well, so a full-file scan does not start ahead of the display's own first
|
|
39
|
+
* fetch, and the tier read waits on the track declaring a tier threshold at
|
|
40
|
+
* all.
|
|
41
|
+
* - **no `contract`.** This is the second fetch on a display whose foundation
|
|
42
|
+
* installed both checks already: `assertDisplayContract` would report the
|
|
43
|
+
* double-attach it exists to catch, and a second retry check would consume the
|
|
44
|
+
* same `reloadCounter` bumps as the first.
|
|
45
|
+
* - **where the status goes is the caller's** (`report`). The two LGV reads
|
|
46
|
+
* lend the display's own status window, so the read takes a slot beside the
|
|
47
|
+
* primary fetch rather than opening a second writer over the one status field
|
|
48
|
+
* (ADR-081) — and it matters more here than for most fetches: a prerequisite
|
|
49
|
+
* runs inside the pre-first-paint window, where the scrim is up because
|
|
50
|
+
* nothing is drawn rather than because `isLoading` is, so `statusMessage` is
|
|
51
|
+
* the only thing that can say what is happening. The tier read narrates
|
|
52
|
+
* nothing; a header is not a load.
|
|
53
|
+
*
|
|
54
|
+
* `createAdapterMetadataFetch` keys on the same adapter config and is
|
|
55
|
+
* deliberately NOT one of these: no trigger, no stop token and no status,
|
|
56
|
+
* because it is fetched lazily when a details widget opens and the widget opens
|
|
57
|
+
* on the result. A prerequisite read is the one a display's own fetch waits on.
|
|
58
|
+
*
|
|
59
|
+
* **A declaration, not the skeleton this name used to be.** There was an
|
|
60
|
+
* `installPrerequisiteFetch` until 2026-08-23, and `3c5aa7fce2` deleted it for
|
|
61
|
+
* a good reason: it carried a `runOne` of its own — a fifth copy of begin →
|
|
62
|
+
* clear → run → commit-if-current → `handleFetchError` → end — and once
|
|
63
|
+
* `installFetch` owned that sequence, a second one was pure drift surface. This
|
|
64
|
+
* one adds no sequence, no rotation and no error rule; it is terms handed to
|
|
65
|
+
* `installFetch`, the same shape `installGlobalFetchAutorun` and
|
|
66
|
+
* `installComparativeFetchAutorun` are. Add nothing here that a family could
|
|
67
|
+
* not state as an option to the skeleton.
|
|
68
|
+
*
|
|
69
|
+
* Everything the skeleton gives it is the point of going through the skeleton:
|
|
70
|
+
* the latest-wins rotation (so a superseding read aborts the one it replaced,
|
|
71
|
+
* and only a superseding read does — a user cancel of the primary fetch cannot
|
|
72
|
+
* strand the display the way sharing its token would), the clear at the start,
|
|
73
|
+
* the currency-guarded error rule, the unconditional `reloadCounter` read that
|
|
74
|
+
* makes the chrome's Retry re-run this, and the retired status slot that keeps a
|
|
75
|
+
* failed read from leaving a progress chip up for good.
|
|
76
|
+
*/
|
|
77
|
+
export declare function installPrerequisiteFetch<TResult>(self: PrerequisiteFetchHost, { name, delay, report, gate, run, commit, setError, }: {
|
|
78
|
+
name: string;
|
|
79
|
+
delay: number;
|
|
80
|
+
report: StatusReporter;
|
|
81
|
+
/** an extra term of the display's own, ANDed under `!isMinimized` */
|
|
82
|
+
gate?: () => boolean;
|
|
83
|
+
run: (adapterConfig: Record<string, unknown>, ctx: FetchContext) => Promise<TResult | undefined>;
|
|
84
|
+
commit: (result: TResult) => void;
|
|
85
|
+
setError: (error?: unknown) => void;
|
|
86
|
+
}): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { adapterConfigKey } from './adapterConfigKey.js';
|
|
2
|
+
import { installFetch } from './installFetch.js';
|
|
3
|
+
/**
|
|
4
|
+
* A **prerequisite read**: one RPC about the adapter itself, beside the
|
|
5
|
+
* display's primary fetch. Three in the tree — HiC's `CoreGetInfo` header read,
|
|
6
|
+
* whose `resolutions` every contacts fetch waits on; the multi-sample sample
|
|
7
|
+
* list, which `fetchNeeded` declines until; and the tiered alignment file's
|
|
8
|
+
* `CoreGetInfo` header, which decides the LOD tier a synteny fetch asks for —
|
|
9
|
+
* and they sit on three different fetch foundations, which is why this sits in
|
|
10
|
+
* core beside the skeleton and not beside any of them.
|
|
11
|
+
*
|
|
12
|
+
* They had the shape below hand-copied, comment for comment, and each term is a
|
|
13
|
+
* rule rather than a preference:
|
|
14
|
+
*
|
|
15
|
+
* - **the adapter config is the whole trigger and the whole key.** Tracked in
|
|
16
|
+
* `prepare` so a config-editor edit re-reads; keyed on the same value so an
|
|
17
|
+
* un-minimize over the same file re-reads nothing. Getting one without the
|
|
18
|
+
* other gives either a stale header or a walk of a `.hic` norm-vector index on
|
|
19
|
+
* every expand.
|
|
20
|
+
* - **minimized is the gate**, and a display with a second condition of its own
|
|
21
|
+
* passes `gate` — the sample-list read waits for the LGV to be measured as
|
|
22
|
+
* well, so a full-file scan does not start ahead of the display's own first
|
|
23
|
+
* fetch, and the tier read waits on the track declaring a tier threshold at
|
|
24
|
+
* all.
|
|
25
|
+
* - **no `contract`.** This is the second fetch on a display whose foundation
|
|
26
|
+
* installed both checks already: `assertDisplayContract` would report the
|
|
27
|
+
* double-attach it exists to catch, and a second retry check would consume the
|
|
28
|
+
* same `reloadCounter` bumps as the first.
|
|
29
|
+
* - **where the status goes is the caller's** (`report`). The two LGV reads
|
|
30
|
+
* lend the display's own status window, so the read takes a slot beside the
|
|
31
|
+
* primary fetch rather than opening a second writer over the one status field
|
|
32
|
+
* (ADR-081) — and it matters more here than for most fetches: a prerequisite
|
|
33
|
+
* runs inside the pre-first-paint window, where the scrim is up because
|
|
34
|
+
* nothing is drawn rather than because `isLoading` is, so `statusMessage` is
|
|
35
|
+
* the only thing that can say what is happening. The tier read narrates
|
|
36
|
+
* nothing; a header is not a load.
|
|
37
|
+
*
|
|
38
|
+
* `createAdapterMetadataFetch` keys on the same adapter config and is
|
|
39
|
+
* deliberately NOT one of these: no trigger, no stop token and no status,
|
|
40
|
+
* because it is fetched lazily when a details widget opens and the widget opens
|
|
41
|
+
* on the result. A prerequisite read is the one a display's own fetch waits on.
|
|
42
|
+
*
|
|
43
|
+
* **A declaration, not the skeleton this name used to be.** There was an
|
|
44
|
+
* `installPrerequisiteFetch` until 2026-08-23, and `3c5aa7fce2` deleted it for
|
|
45
|
+
* a good reason: it carried a `runOne` of its own — a fifth copy of begin →
|
|
46
|
+
* clear → run → commit-if-current → `handleFetchError` → end — and once
|
|
47
|
+
* `installFetch` owned that sequence, a second one was pure drift surface. This
|
|
48
|
+
* one adds no sequence, no rotation and no error rule; it is terms handed to
|
|
49
|
+
* `installFetch`, the same shape `installGlobalFetchAutorun` and
|
|
50
|
+
* `installComparativeFetchAutorun` are. Add nothing here that a family could
|
|
51
|
+
* not state as an option to the skeleton.
|
|
52
|
+
*
|
|
53
|
+
* Everything the skeleton gives it is the point of going through the skeleton:
|
|
54
|
+
* the latest-wins rotation (so a superseding read aborts the one it replaced,
|
|
55
|
+
* and only a superseding read does — a user cancel of the primary fetch cannot
|
|
56
|
+
* strand the display the way sharing its token would), the clear at the start,
|
|
57
|
+
* the currency-guarded error rule, the unconditional `reloadCounter` read that
|
|
58
|
+
* makes the chrome's Retry re-run this, and the retired status slot that keeps a
|
|
59
|
+
* failed read from leaving a progress chip up for good.
|
|
60
|
+
*/
|
|
61
|
+
export function installPrerequisiteFetch(self, { name, delay, report, gate = () => true, run, commit, setError, }) {
|
|
62
|
+
installFetch(self, {
|
|
63
|
+
name,
|
|
64
|
+
delay,
|
|
65
|
+
report,
|
|
66
|
+
gate: () => !self.isMinimized && gate(),
|
|
67
|
+
prepare: () => ({ adapterConfig: self.adapterConfig }),
|
|
68
|
+
fetchKey: ({ adapterConfig }) => adapterConfigKey(adapterConfig),
|
|
69
|
+
run: ({ adapterConfig }, ctx) => run(adapterConfig, ctx),
|
|
70
|
+
commit,
|
|
71
|
+
setError,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -5,10 +5,15 @@ export interface FeatureWidgetTypeRef {
|
|
|
5
5
|
type: string;
|
|
6
6
|
id: string;
|
|
7
7
|
}
|
|
8
|
+
export interface ParentFeatureSummary {
|
|
9
|
+
name: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
}
|
|
8
12
|
export declare function openFeatureWidget(node: IAnyStateTreeNode, featureData: SimpleFeatureSerialized, opts?: {
|
|
9
13
|
widget?: FeatureWidgetTypeRef;
|
|
10
14
|
extra?: Record<string, unknown>;
|
|
11
15
|
feature?: Feature;
|
|
16
|
+
parentFeature?: ParentFeatureSummary;
|
|
12
17
|
}): Widget | undefined;
|
|
13
18
|
/**
|
|
14
19
|
* The other half of the flow above: the details lookup came back with nothing,
|
|
@@ -32,6 +32,7 @@ export function openFeatureWidget(node, featureData, opts = {}) {
|
|
|
32
32
|
const { type, id } = opts.widget ?? DEFAULT_FEATURE_WIDGET;
|
|
33
33
|
const widget = session.addWidget(type, id, {
|
|
34
34
|
featureData,
|
|
35
|
+
parentFeature: opts.parentFeature,
|
|
35
36
|
view: getContainingView(node),
|
|
36
37
|
track: getContainingTrack(node),
|
|
37
38
|
...opts.extra,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AbstractSessionModel, AbstractTrackModel, AbstractViewModel } from './types/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* "What is open" — the reduction four consumers wanted and each used to walk
|
|
4
|
+
* for itself (AppReadyMarker, jbApi, and capture's session gate and busy
|
|
5
|
+
* check), on different and drifting spellings of the view nesting.
|
|
6
|
+
*
|
|
7
|
+
* The recursion lives here, once. What each view contributes lives on the view,
|
|
8
|
+
* once, as `ownViews`/`ownTracks`. Neither half guesses at the other: the
|
|
9
|
+
* census is declared intent, not a shape that can be discovered, because the
|
|
10
|
+
* two things that look enumerable are not — the dotplot's `views` prop holds
|
|
11
|
+
* view-shaped axis models the user never opened, and react-msaview's `tracks`
|
|
12
|
+
* getter holds annotation rows that are not tracks.
|
|
13
|
+
*/
|
|
14
|
+
export declare function openViews(session: AbstractSessionModel): AbstractViewModel[];
|
|
15
|
+
/** Every track on every open view. */
|
|
16
|
+
export declare function openTracks(session: AbstractSessionModel): AbstractTrackModel[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "What is open" — the reduction four consumers wanted and each used to walk
|
|
3
|
+
* for itself (AppReadyMarker, jbApi, and capture's session gate and busy
|
|
4
|
+
* check), on different and drifting spellings of the view nesting.
|
|
5
|
+
*
|
|
6
|
+
* The recursion lives here, once. What each view contributes lives on the view,
|
|
7
|
+
* once, as `ownViews`/`ownTracks`. Neither half guesses at the other: the
|
|
8
|
+
* census is declared intent, not a shape that can be discovered, because the
|
|
9
|
+
* two things that look enumerable are not — the dotplot's `views` prop holds
|
|
10
|
+
* view-shaped axis models the user never opened, and react-msaview's `tracks`
|
|
11
|
+
* getter holds annotation rows that are not tracks.
|
|
12
|
+
*/
|
|
13
|
+
export function openViews(session) {
|
|
14
|
+
return session.views.flatMap(withNested);
|
|
15
|
+
}
|
|
16
|
+
/** Every track on every open view. */
|
|
17
|
+
export function openTracks(session) {
|
|
18
|
+
return openViews(session).flatMap(v => v.ownTracks ?? []);
|
|
19
|
+
}
|
|
20
|
+
function withNested(view) {
|
|
21
|
+
return [view, ...(view.ownViews ?? []).flatMap(withNested)];
|
|
22
|
+
}
|
package/esm/util/parentWalk.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare function findParentThatIs<T extends (a: IAnyStateTreeNode) => boo
|
|
|
14
14
|
* Keying on the node is safe because nothing re-parents one — both `detach`
|
|
15
15
|
* call sites hand the node straight to `scheduleDetachedDestroy` (ADR-069), so
|
|
16
16
|
* a cached ancestor can only go stale by dying, which the `isAlive` check
|
|
17
|
-
* catches. That is the difference from the three memos
|
|
17
|
+
* catches. That is the difference from the three memos agent-docs/architecture-decision-records/ records
|
|
18
18
|
* removing: each keyed on something its caller had just allocated.
|
|
19
19
|
*/
|
|
20
20
|
export declare function cachedParent<T>(cache: WeakMap<IAnyStateTreeNode, T>, node: IAnyStateTreeNode, finder: () => T, errorMsg: string): T;
|
package/esm/util/parentWalk.js
CHANGED
|
@@ -39,7 +39,7 @@ export function findParentThatIs(node, predicate) {
|
|
|
39
39
|
* Keying on the node is safe because nothing re-parents one — both `detach`
|
|
40
40
|
* call sites hand the node straight to `scheduleDetachedDestroy` (ADR-069), so
|
|
41
41
|
* a cached ancestor can only go stale by dying, which the `isAlive` check
|
|
42
|
-
* catches. That is the difference from the three memos
|
|
42
|
+
* catches. That is the difference from the three memos agent-docs/architecture-decision-records/ records
|
|
43
43
|
* removing: each keyed on something its caller had just allocated.
|
|
44
44
|
*/
|
|
45
45
|
export function cachedParent(cache, node, finder, errorMsg) {
|