@genome-spy/core 0.68.0 → 0.69.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.
Files changed (163) hide show
  1. package/dist/bundle/index.es.js +12119 -10681
  2. package/dist/bundle/index.js +119 -119
  3. package/dist/schema.json +6224 -6319
  4. package/dist/src/data/dataFlow.d.ts.map +1 -1
  5. package/dist/src/data/dataFlow.js +10 -0
  6. package/dist/src/data/flowNode.d.ts +25 -10
  7. package/dist/src/data/flowNode.d.ts.map +1 -1
  8. package/dist/src/data/flowNode.js +66 -13
  9. package/dist/src/data/flowTestUtils.d.ts +2 -2
  10. package/dist/src/data/flowTestUtils.d.ts.map +1 -1
  11. package/dist/src/data/flowTestUtils.js +5 -4
  12. package/dist/src/data/sources/dataSource.js +2 -2
  13. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  14. package/dist/src/data/sources/lazy/bigBedSource.js +11 -10
  15. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  16. package/dist/src/data/sources/lazy/bigWigSource.js +11 -10
  17. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +1 -1
  18. package/dist/src/data/sources/lazy/tabixSource.d.ts +0 -1
  19. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  20. package/dist/src/data/sources/lazy/tabixSource.js +41 -11
  21. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  22. package/dist/src/data/sources/sequenceSource.js +5 -3
  23. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  24. package/dist/src/data/sources/urlSource.js +7 -3
  25. package/dist/src/data/transforms/filter.d.ts +4 -4
  26. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  27. package/dist/src/data/transforms/filter.js +13 -7
  28. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  29. package/dist/src/data/transforms/filterScoredLabels.js +11 -6
  30. package/dist/src/data/transforms/filterScoredLabels.test.d.ts +2 -0
  31. package/dist/src/data/transforms/filterScoredLabels.test.d.ts.map +1 -0
  32. package/dist/src/data/transforms/formula.d.ts +4 -4
  33. package/dist/src/data/transforms/formula.d.ts.map +1 -1
  34. package/dist/src/data/transforms/formula.js +12 -6
  35. package/dist/src/data/transforms/measureText.d.ts +2 -2
  36. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  37. package/dist/src/data/transforms/measureText.js +16 -12
  38. package/dist/src/data/transforms/transform.d.ts +2 -2
  39. package/dist/src/data/transforms/transform.d.ts.map +1 -1
  40. package/dist/src/data/transforms/transform.js +3 -3
  41. package/dist/src/encoder/accessor.d.ts +8 -4
  42. package/dist/src/encoder/accessor.d.ts.map +1 -1
  43. package/dist/src/encoder/accessor.js +10 -10
  44. package/dist/src/encoder/encoder.js +5 -5
  45. package/dist/src/genome/genome.d.ts +8 -0
  46. package/dist/src/genome/genome.d.ts.map +1 -1
  47. package/dist/src/genome/genome.js +16 -1
  48. package/dist/src/genomeSpy/inputBindingManager.js +1 -1
  49. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  50. package/dist/src/genomeSpy/interactionController.js +7 -1
  51. package/dist/src/genomeSpy.js +1 -1
  52. package/dist/src/gl/glslScaleGenerator.js +1 -1
  53. package/dist/src/marks/mark.d.ts.map +1 -1
  54. package/dist/src/marks/mark.js +22 -30
  55. package/dist/src/marks/point.d.ts.map +1 -1
  56. package/dist/src/marks/point.js +4 -6
  57. package/dist/src/paramRuntime/expressionCompiler.d.ts +7 -0
  58. package/dist/src/paramRuntime/expressionCompiler.d.ts.map +1 -0
  59. package/dist/src/paramRuntime/expressionCompiler.js +10 -0
  60. package/dist/src/paramRuntime/expressionRef.d.ts +20 -0
  61. package/dist/src/paramRuntime/expressionRef.d.ts.map +1 -0
  62. package/dist/src/paramRuntime/expressionRef.js +95 -0
  63. package/dist/src/paramRuntime/expressionRef.test.d.ts +2 -0
  64. package/dist/src/paramRuntime/expressionRef.test.d.ts.map +1 -0
  65. package/dist/src/paramRuntime/graphRuntime.d.ts +176 -0
  66. package/dist/src/paramRuntime/graphRuntime.d.ts.map +1 -0
  67. package/dist/src/paramRuntime/graphRuntime.js +628 -0
  68. package/dist/src/paramRuntime/graphRuntime.test.d.ts +2 -0
  69. package/dist/src/paramRuntime/graphRuntime.test.d.ts.map +1 -0
  70. package/dist/src/paramRuntime/index.d.ts +9 -0
  71. package/dist/src/paramRuntime/index.d.ts.map +1 -0
  72. package/dist/src/paramRuntime/index.js +8 -0
  73. package/dist/src/paramRuntime/lifecycleRegistry.d.ts +27 -0
  74. package/dist/src/paramRuntime/lifecycleRegistry.d.ts.map +1 -0
  75. package/dist/src/paramRuntime/lifecycleRegistry.js +54 -0
  76. package/dist/src/paramRuntime/paramRuntime.d.ts +165 -0
  77. package/dist/src/paramRuntime/paramRuntime.d.ts.map +1 -0
  78. package/dist/src/paramRuntime/paramRuntime.js +222 -0
  79. package/dist/src/paramRuntime/paramRuntime.test.d.ts +2 -0
  80. package/dist/src/paramRuntime/paramRuntime.test.d.ts.map +1 -0
  81. package/dist/src/paramRuntime/paramStore.d.ts +68 -0
  82. package/dist/src/paramRuntime/paramStore.d.ts.map +1 -0
  83. package/dist/src/paramRuntime/paramStore.js +148 -0
  84. package/dist/src/paramRuntime/paramStore.test.d.ts +2 -0
  85. package/dist/src/paramRuntime/paramStore.test.d.ts.map +1 -0
  86. package/dist/src/paramRuntime/paramUtils.d.ts +86 -0
  87. package/dist/src/paramRuntime/paramUtils.d.ts.map +1 -0
  88. package/dist/src/paramRuntime/paramUtils.js +272 -0
  89. package/dist/src/paramRuntime/selectionStore.d.ts +6 -0
  90. package/dist/src/paramRuntime/selectionStore.d.ts.map +1 -0
  91. package/dist/src/paramRuntime/selectionStore.js +13 -0
  92. package/dist/src/paramRuntime/types.d.ts +16 -0
  93. package/dist/src/paramRuntime/types.d.ts.map +1 -0
  94. package/dist/src/paramRuntime/types.js +25 -0
  95. package/dist/src/paramRuntime/viewParamRuntime.d.ts +164 -0
  96. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -0
  97. package/dist/src/paramRuntime/viewParamRuntime.js +443 -0
  98. package/dist/src/scales/scaleInstanceManager.d.ts +6 -3
  99. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  100. package/dist/src/scales/scaleInstanceManager.js +17 -11
  101. package/dist/src/scales/scaleResolution.d.ts +1 -0
  102. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  103. package/dist/src/scales/scaleResolution.js +7 -1
  104. package/dist/src/selection/selection.js +1 -1
  105. package/dist/src/spec/coreSchemaRoot.d.ts +53 -0
  106. package/dist/src/spec/root.d.ts +1 -1
  107. package/dist/src/spec/view.d.ts +114 -33
  108. package/dist/src/tooltip/dataTooltipHandler.d.ts +1 -1
  109. package/dist/src/tooltip/dataTooltipHandler.js +23 -32
  110. package/dist/src/tooltip/dataTooltipHandler.test.d.ts +2 -0
  111. package/dist/src/tooltip/dataTooltipHandler.test.d.ts.map +1 -0
  112. package/dist/src/tooltip/flattenDatumRows.d.ts +13 -0
  113. package/dist/src/tooltip/flattenDatumRows.d.ts.map +1 -0
  114. package/dist/src/tooltip/flattenDatumRows.js +47 -0
  115. package/dist/src/tooltip/flattenDatumRows.test.d.ts +2 -0
  116. package/dist/src/tooltip/flattenDatumRows.test.d.ts.map +1 -0
  117. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +1 -1
  118. package/dist/src/tooltip/refseqGeneTooltipHandler.js +7 -1
  119. package/dist/src/tooltip/tooltipContext.d.ts +13 -0
  120. package/dist/src/tooltip/tooltipContext.d.ts.map +1 -0
  121. package/dist/src/tooltip/tooltipContext.js +543 -0
  122. package/dist/src/tooltip/tooltipContext.test.d.ts +2 -0
  123. package/dist/src/tooltip/tooltipContext.test.d.ts.map +1 -0
  124. package/dist/src/tooltip/tooltipHandler.d.ts +40 -1
  125. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  126. package/dist/src/tooltip/tooltipHandler.ts +62 -1
  127. package/dist/src/types/encoder.d.ts +1 -1
  128. package/dist/src/utils/inputBinding.d.ts +10 -2
  129. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  130. package/dist/src/utils/inputBinding.js +12 -3
  131. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  132. package/dist/src/view/flowBuilder.js +12 -3
  133. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  134. package/dist/src/view/gridView/gridChild.js +8 -3
  135. package/dist/src/view/gridView/selectionRect.d.ts +6 -10
  136. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  137. package/dist/src/view/gridView/selectionRect.js +3 -20
  138. package/dist/src/view/layerView.d.ts.map +1 -1
  139. package/dist/src/view/layerView.js +4 -2
  140. package/dist/src/view/multiscale.d.ts +35 -0
  141. package/dist/src/view/multiscale.d.ts.map +1 -0
  142. package/dist/src/view/multiscale.js +233 -0
  143. package/dist/src/view/multiscale.test.d.ts +2 -0
  144. package/dist/src/view/multiscale.test.d.ts.map +1 -0
  145. package/dist/src/view/unitView.d.ts.map +1 -1
  146. package/dist/src/view/unitView.js +10 -4
  147. package/dist/src/view/view.d.ts +5 -4
  148. package/dist/src/view/view.d.ts.map +1 -1
  149. package/dist/src/view/view.js +223 -28
  150. package/dist/src/view/viewFactory.d.ts +0 -12
  151. package/dist/src/view/viewFactory.d.ts.map +1 -1
  152. package/dist/src/view/viewFactory.js +35 -24
  153. package/dist/src/view/viewParamRuntime.test.d.ts +2 -0
  154. package/dist/src/view/viewParamRuntime.test.d.ts.map +1 -0
  155. package/dist/src/view/viewSelectors.d.ts.map +1 -1
  156. package/dist/src/view/viewSelectors.js +8 -5
  157. package/package.json +3 -3
  158. package/dist/src/spec/sampleView.d.ts +0 -197
  159. package/dist/src/view/paramMediator.d.ts +0 -168
  160. package/dist/src/view/paramMediator.d.ts.map +0 -1
  161. package/dist/src/view/paramMediator.js +0 -545
  162. package/dist/src/view/paramMediator.test.d.ts +0 -2
  163. package/dist/src/view/paramMediator.test.d.ts.map +0 -1
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Tracks owner-bound cleanup callbacks for runtime resources.
3
+ *
4
+ * Why this exists:
5
+ * reactive graph nodes and expression subscriptions can outlive their creating
6
+ * call site unless they are disposed explicitly. The lifecycle registry gives
7
+ * `ParamRuntime`/`GraphRuntime` a single owner-based teardown mechanism so
8
+ * disposing a scope/view reliably detaches listeners and releases resources.
9
+ */
10
+ export default class LifecycleRegistry {
11
+ #nextOwnerId = 1;
12
+
13
+ /** @type {Map<string, Set<() => void>>} */
14
+ #ownerDisposers = new Map();
15
+
16
+ /**
17
+ * @param {"view" | "mark" | "transform" | "source" | "scope"} kind
18
+ * @param {string} key
19
+ */
20
+ createOwner(kind, key) {
21
+ const ownerId = kind + ":" + key + ":" + this.#nextOwnerId++;
22
+ this.#ownerDisposers.set(ownerId, new Set());
23
+ return ownerId;
24
+ }
25
+
26
+ /**
27
+ * @param {string} ownerId
28
+ * @param {() => void} disposer
29
+ */
30
+ addDisposer(ownerId, disposer) {
31
+ const disposers = this.#ownerDisposers.get(ownerId);
32
+ if (!disposers) {
33
+ throw new Error("Unknown owner: " + ownerId);
34
+ }
35
+
36
+ disposers.add(disposer);
37
+ }
38
+
39
+ /**
40
+ * @param {string} ownerId
41
+ */
42
+ disposeOwner(ownerId) {
43
+ const disposers = this.#ownerDisposers.get(ownerId);
44
+ if (!disposers) {
45
+ return;
46
+ }
47
+
48
+ for (const disposer of disposers) {
49
+ disposer();
50
+ }
51
+ disposers.clear();
52
+ this.#ownerDisposers.delete(ownerId);
53
+ }
54
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Core-facing parameter runtime facade.
3
+ *
4
+ * `ParamRuntime` composes three internal subsystems:
5
+ * 1. `ParamStore` for scoped name resolution (`scope` + `name` -> ref).
6
+ * 2. `GraphRuntime` for reactive propagation and batching.
7
+ * 3. `LifecycleRegistry` for owner-bound teardown.
8
+ *
9
+ * Most Core call sites should use this class (or `ViewParamRuntime`) instead
10
+ * of interacting with `GraphRuntime` directly.
11
+ *
12
+ * Scope semantics used by this runtime:
13
+ * 1. A scope is a runtime-only identity (`ScopeId`) with a parent pointer.
14
+ * 2. Parameters are registered into exactly one scope.
15
+ * 3. Name resolution is lexical/nearest-first: local scope, then parent chain.
16
+ * 4. Shadowing is allowed across scopes (same param name in parent/child).
17
+ * 5. Duplicate names are rejected within a single scope.
18
+ * 6. `disposeScope` clears local bindings and owner resources while preserving
19
+ * scope-chain structure for descendants that still resolve through parents.
20
+ *
21
+ * @typedef {string} ScopeId
22
+ */
23
+ export default class ParamRuntime {
24
+ /**
25
+ * Creates a new parameter scope.
26
+ *
27
+ * If `parentScope` is provided, name resolution in this scope falls back to
28
+ * the parent chain.
29
+ *
30
+ * @param {ScopeId} [parentScope]
31
+ * @returns {ScopeId}
32
+ */
33
+ createScope(parentScope?: ScopeId): ScopeId;
34
+ /**
35
+ * Disposes all runtime resources owned by the scope and clears the scope's
36
+ * local parameter bindings.
37
+ *
38
+ * Descendant scopes remain valid and continue resolving through their own
39
+ * parent chains.
40
+ *
41
+ * @param {ScopeId} scope
42
+ */
43
+ disposeScope(scope: ScopeId): void;
44
+ /**
45
+ * Registers a disposer that is bound to the scope lifecycle.
46
+ *
47
+ * The disposer is called when `disposeScope(scope)` is executed.
48
+ *
49
+ * @param {ScopeId} scope
50
+ * @param {() => void} disposer
51
+ */
52
+ addScopeDisposer(scope: ScopeId, disposer: () => void): void;
53
+ /**
54
+ * Registers a writable base parameter in `scope`.
55
+ *
56
+ * @template T
57
+ * @param {ScopeId} scope
58
+ * @param {string} name
59
+ * @param {T} initial
60
+ * @param {{ notify?: boolean }} [options]
61
+ * @returns {import("./types.js").WritableParamRef<T>}
62
+ */
63
+ registerBase<T>(scope: ScopeId, name: string, initial: T, options?: {
64
+ notify?: boolean;
65
+ }): import("./types.js").WritableParamRef<T>;
66
+ /**
67
+ * Registers a writable selection parameter in `scope`.
68
+ *
69
+ * Selection params are writable like base params but carry `kind:
70
+ * "selection"` for downstream handling.
71
+ *
72
+ * @template T
73
+ * @param {ScopeId} scope
74
+ * @param {string} name
75
+ * @param {T} initial
76
+ * @param {{ notify?: boolean }} [options]
77
+ * @returns {import("./types.js").WritableParamRef<T>}
78
+ */
79
+ registerSelection<T>(scope: ScopeId, name: string, initial: T, options?: {
80
+ notify?: boolean;
81
+ }): import("./types.js").WritableParamRef<T>;
82
+ /**
83
+ * Registers a derived read-only parameter in `scope`.
84
+ *
85
+ * The expression is bound to current scope resolution and re-evaluated by
86
+ * the graph runtime when dependencies change.
87
+ *
88
+ * @template T
89
+ * @param {ScopeId} scope
90
+ * @param {string} name
91
+ * @param {string} expr
92
+ * @returns {import("./types.js").ParamRef<T>}
93
+ */
94
+ registerDerived<T>(scope: ScopeId, name: string, expr: string): import("./types.js").ParamRef<T>;
95
+ /**
96
+ * Creates an expression function bound to scope-based parameter resolution.
97
+ *
98
+ * The returned expression supports subscriptions (`subscribe`)
99
+ * and can be used by callers that need expression-level reactivity without
100
+ * registering a named derived parameter.
101
+ *
102
+ * @param {ScopeId} scope
103
+ * @param {string} expr
104
+ * @returns {import("./types.js").ExprRefFunction}
105
+ */
106
+ createExpression(scope: ScopeId, expr: string): import("./types.js").ExprRefFunction;
107
+ /**
108
+ * Resolves a parameter by name from `scope`, searching parent scopes as needed.
109
+ * Returns the nearest matching binding, if any.
110
+ *
111
+ * @template T
112
+ * @param {ScopeId} scope
113
+ * @param {string} name
114
+ * @returns {import("./types.js").ParamRef<T> | undefined}
115
+ */
116
+ resolve<T>(scope: ScopeId, name: string): import("./types.js").ParamRef<T> | undefined;
117
+ /**
118
+ * Runs a transactional update against the underlying graph runtime.
119
+ *
120
+ * Multiple writes inside `fn` are batched and propagated after the
121
+ * outermost transaction exits.
122
+ *
123
+ * @template T
124
+ * @param {() => T} fn
125
+ * @returns {T}
126
+ */
127
+ runInTransaction<T>(fn: () => T): T;
128
+ /**
129
+ * Forces immediate synchronous propagation of currently queued graph work.
130
+ */
131
+ flushNow(): void;
132
+ /**
133
+ * Resolves when propagation/effects have settled in the graph runtime.
134
+ *
135
+ * @param {{ signal?: AbortSignal, timeoutMs?: number }} [options]
136
+ * @returns {Promise<void>}
137
+ */
138
+ whenPropagated(options?: {
139
+ signal?: AbortSignal;
140
+ timeoutMs?: number;
141
+ }): Promise<void>;
142
+ #private;
143
+ }
144
+ /**
145
+ * Core-facing parameter runtime facade.
146
+ *
147
+ * `ParamRuntime` composes three internal subsystems:
148
+ * 1. `ParamStore` for scoped name resolution (`scope` + `name` -> ref).
149
+ * 2. `GraphRuntime` for reactive propagation and batching.
150
+ * 3. `LifecycleRegistry` for owner-bound teardown.
151
+ *
152
+ * Most Core call sites should use this class (or `ViewParamRuntime`) instead
153
+ * of interacting with `GraphRuntime` directly.
154
+ *
155
+ * Scope semantics used by this runtime:
156
+ * 1. A scope is a runtime-only identity (`ScopeId`) with a parent pointer.
157
+ * 2. Parameters are registered into exactly one scope.
158
+ * 3. Name resolution is lexical/nearest-first: local scope, then parent chain.
159
+ * 4. Shadowing is allowed across scopes (same param name in parent/child).
160
+ * 5. Duplicate names are rejected within a single scope.
161
+ * 6. `disposeScope` clears local bindings and owner resources while preserving
162
+ * scope-chain structure for descendants that still resolve through parents.
163
+ */
164
+ export type ScopeId = string;
165
+ //# sourceMappingURL=paramRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramRuntime.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/paramRuntime.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IASI;;;;;;;;OAQG;IACH,0BAHW,OAAO,GACL,OAAO,CAYnB;IAED;;;;;;;;OAQG;IACH,oBAFW,OAAO,QAMjB;IAED;;;;;;;OAOG;IACH,wBAHW,OAAO,YACP,MAAM,IAAI,QAKpB;IAED;;;;;;;;;OASG;IACH,aAPa,CAAC,SACH,OAAO,QACP,MAAM,WACN,CAAC,YACD;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAClB,OAAO,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAYpD;IAED;;;;;;;;;;;;OAYG;IACH,kBAPa,CAAC,SACH,OAAO,QACP,MAAM,WACN,CAAC,YACD;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAClB,OAAO,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAYpD;IAED;;;;;;;;;;;OAWG;IACH,gBANa,CAAC,SACH,OAAO,QACP,MAAM,QACN,MAAM,GACJ,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAgB5C;IAED;;;;;;;;;;OAUG;IACH,wBAJW,OAAO,QACP,MAAM,GACJ,OAAO,YAAY,EAAE,eAAe,CAOhD;IAED;;;;;;;;OAQG;IACH,QALa,CAAC,SACH,OAAO,QACP,MAAM,GACJ,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAIxD;IAED;;;;;;;;;OASG;IACH,iBAJa,CAAC,MACH,MAAM,CAAC,GACL,CAAC,CAIb;IAED;;OAEG;IACH,iBAEC;IAED;;;;;OAKG;IACH,yBAHW;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAIzB;;CACJ;;;;;;;;;;;;;;;;;;;;;sBApMY,MAAM"}
@@ -0,0 +1,222 @@
1
+ import GraphRuntime from "./graphRuntime.js";
2
+ import LifecycleRegistry from "./lifecycleRegistry.js";
3
+ import ParamStore from "./paramStore.js";
4
+ import { bindExpression } from "./expressionRef.js";
5
+
6
+ /**
7
+ * Core-facing parameter runtime facade.
8
+ *
9
+ * `ParamRuntime` composes three internal subsystems:
10
+ * 1. `ParamStore` for scoped name resolution (`scope` + `name` -> ref).
11
+ * 2. `GraphRuntime` for reactive propagation and batching.
12
+ * 3. `LifecycleRegistry` for owner-bound teardown.
13
+ *
14
+ * Most Core call sites should use this class (or `ViewParamRuntime`) instead
15
+ * of interacting with `GraphRuntime` directly.
16
+ *
17
+ * Scope semantics used by this runtime:
18
+ * 1. A scope is a runtime-only identity (`ScopeId`) with a parent pointer.
19
+ * 2. Parameters are registered into exactly one scope.
20
+ * 3. Name resolution is lexical/nearest-first: local scope, then parent chain.
21
+ * 4. Shadowing is allowed across scopes (same param name in parent/child).
22
+ * 5. Duplicate names are rejected within a single scope.
23
+ * 6. `disposeScope` clears local bindings and owner resources while preserving
24
+ * scope-chain structure for descendants that still resolve through parents.
25
+ *
26
+ * @typedef {string} ScopeId
27
+ */
28
+ export default class ParamRuntime {
29
+ #lifecycleRegistry = new LifecycleRegistry();
30
+
31
+ #graphRuntime = new GraphRuntime({
32
+ lifecycleRegistry: this.#lifecycleRegistry,
33
+ });
34
+
35
+ #paramStore = new ParamStore();
36
+
37
+ /**
38
+ * Creates a new parameter scope.
39
+ *
40
+ * If `parentScope` is provided, name resolution in this scope falls back to
41
+ * the parent chain.
42
+ *
43
+ * @param {ScopeId} [parentScope]
44
+ * @returns {ScopeId}
45
+ */
46
+ createScope(parentScope) {
47
+ const ownerId = this.#lifecycleRegistry.createOwner(
48
+ "scope",
49
+ parentScope ?? "root"
50
+ );
51
+ if (parentScope) {
52
+ return this.#paramStore.createChildScope(ownerId, parentScope);
53
+ } else {
54
+ return this.#paramStore.createRootScope(ownerId);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Disposes all runtime resources owned by the scope and clears the scope's
60
+ * local parameter bindings.
61
+ *
62
+ * Descendant scopes remain valid and continue resolving through their own
63
+ * parent chains.
64
+ *
65
+ * @param {ScopeId} scope
66
+ */
67
+ disposeScope(scope) {
68
+ const ownerId = this.#paramStore.getOwnerId(scope);
69
+ this.#lifecycleRegistry.disposeOwner(ownerId);
70
+ this.#paramStore.clearScope(scope);
71
+ }
72
+
73
+ /**
74
+ * Registers a disposer that is bound to the scope lifecycle.
75
+ *
76
+ * The disposer is called when `disposeScope(scope)` is executed.
77
+ *
78
+ * @param {ScopeId} scope
79
+ * @param {() => void} disposer
80
+ */
81
+ addScopeDisposer(scope, disposer) {
82
+ const ownerId = this.#paramStore.getOwnerId(scope);
83
+ this.#lifecycleRegistry.addDisposer(ownerId, disposer);
84
+ }
85
+
86
+ /**
87
+ * Registers a writable base parameter in `scope`.
88
+ *
89
+ * @template T
90
+ * @param {ScopeId} scope
91
+ * @param {string} name
92
+ * @param {T} initial
93
+ * @param {{ notify?: boolean }} [options]
94
+ * @returns {import("./types.js").WritableParamRef<T>}
95
+ */
96
+ registerBase(scope, name, initial, options) {
97
+ const ownerId = this.#paramStore.getOwnerId(scope);
98
+ const ref = this.#graphRuntime.createWritable(
99
+ ownerId,
100
+ name,
101
+ "base",
102
+ initial,
103
+ options
104
+ );
105
+ return this.#paramStore.register(scope, name, ref);
106
+ }
107
+
108
+ /**
109
+ * Registers a writable selection parameter in `scope`.
110
+ *
111
+ * Selection params are writable like base params but carry `kind:
112
+ * "selection"` for downstream handling.
113
+ *
114
+ * @template T
115
+ * @param {ScopeId} scope
116
+ * @param {string} name
117
+ * @param {T} initial
118
+ * @param {{ notify?: boolean }} [options]
119
+ * @returns {import("./types.js").WritableParamRef<T>}
120
+ */
121
+ registerSelection(scope, name, initial, options) {
122
+ const ownerId = this.#paramStore.getOwnerId(scope);
123
+ const ref = this.#graphRuntime.createWritable(
124
+ ownerId,
125
+ name,
126
+ "selection",
127
+ initial,
128
+ options
129
+ );
130
+ return this.#paramStore.register(scope, name, ref);
131
+ }
132
+
133
+ /**
134
+ * Registers a derived read-only parameter in `scope`.
135
+ *
136
+ * The expression is bound to current scope resolution and re-evaluated by
137
+ * the graph runtime when dependencies change.
138
+ *
139
+ * @template T
140
+ * @param {ScopeId} scope
141
+ * @param {string} name
142
+ * @param {string} expr
143
+ * @returns {import("./types.js").ParamRef<T>}
144
+ */
145
+ registerDerived(scope, name, expr) {
146
+ const { expression, dependencies } = bindExpression(
147
+ expr,
148
+ (globalName) => this.resolve(scope, globalName)
149
+ );
150
+
151
+ const ownerId = this.#paramStore.getOwnerId(scope);
152
+ const ref = this.#graphRuntime.computed(
153
+ ownerId,
154
+ name,
155
+ dependencies,
156
+ () => expression(null)
157
+ );
158
+ return this.#paramStore.register(scope, name, ref);
159
+ }
160
+
161
+ /**
162
+ * Creates an expression function bound to scope-based parameter resolution.
163
+ *
164
+ * The returned expression supports subscriptions (`subscribe`)
165
+ * and can be used by callers that need expression-level reactivity without
166
+ * registering a named derived parameter.
167
+ *
168
+ * @param {ScopeId} scope
169
+ * @param {string} expr
170
+ * @returns {import("./types.js").ExprRefFunction}
171
+ */
172
+ createExpression(scope, expr) {
173
+ const { expression } = bindExpression(expr, (globalName) =>
174
+ this.resolve(scope, globalName)
175
+ );
176
+ return expression;
177
+ }
178
+
179
+ /**
180
+ * Resolves a parameter by name from `scope`, searching parent scopes as needed.
181
+ * Returns the nearest matching binding, if any.
182
+ *
183
+ * @template T
184
+ * @param {ScopeId} scope
185
+ * @param {string} name
186
+ * @returns {import("./types.js").ParamRef<T> | undefined}
187
+ */
188
+ resolve(scope, name) {
189
+ return this.#paramStore.resolve(scope, name);
190
+ }
191
+
192
+ /**
193
+ * Runs a transactional update against the underlying graph runtime.
194
+ *
195
+ * Multiple writes inside `fn` are batched and propagated after the
196
+ * outermost transaction exits.
197
+ *
198
+ * @template T
199
+ * @param {() => T} fn
200
+ * @returns {T}
201
+ */
202
+ runInTransaction(fn) {
203
+ return this.#graphRuntime.runInTransaction(fn);
204
+ }
205
+
206
+ /**
207
+ * Forces immediate synchronous propagation of currently queued graph work.
208
+ */
209
+ flushNow() {
210
+ this.#graphRuntime.flushNow();
211
+ }
212
+
213
+ /**
214
+ * Resolves when propagation/effects have settled in the graph runtime.
215
+ *
216
+ * @param {{ signal?: AbortSignal, timeoutMs?: number }} [options]
217
+ * @returns {Promise<void>}
218
+ */
219
+ whenPropagated(options) {
220
+ return this.#graphRuntime.whenPropagated(options);
221
+ }
222
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=paramRuntime.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramRuntime.test.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/paramRuntime.test.js"],"names":[],"mappings":""}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Runtime store for scoped parameter bindings.
3
+ *
4
+ * Responsibilities:
5
+ * 1. Maintain scope chain metadata (`scope -> parentScope`).
6
+ * 2. Store local bindings (`scope + name -> ParamRef`).
7
+ * 3. Resolve names using nearest-scope lookup through the parent chain.
8
+ *
9
+ * This class is intentionally storage-only: propagation/lifecycle is handled
10
+ * by higher-level runtime components.
11
+ */
12
+ export default class ParamStore {
13
+ /**
14
+ * Creates a root scope with no parent scope.
15
+ *
16
+ * @param {string} ownerId
17
+ * @returns {string}
18
+ */
19
+ createRootScope(ownerId: string): string;
20
+ /**
21
+ * Creates a child scope whose fallback resolution target is `parentScope`.
22
+ *
23
+ * @param {string} ownerId
24
+ * @param {string} parentScope
25
+ * @returns {string}
26
+ */
27
+ createChildScope(ownerId: string, parentScope: string): string;
28
+ /**
29
+ * Returns lifecycle owner id associated with a scope.
30
+ *
31
+ * @param {string} scopeId
32
+ * @returns {string}
33
+ */
34
+ getOwnerId(scopeId: string): string;
35
+ /**
36
+ * Clears all parameter bindings from a scope while keeping the scope chain
37
+ * metadata intact for descendants that may still resolve through it.
38
+ *
39
+ * @param {string} scopeId
40
+ */
41
+ clearScope(scopeId: string): void;
42
+ /**
43
+ * Registers a local parameter binding into `scopeId`.
44
+ *
45
+ * The same parameter name can exist in parent scopes (shadowing), but
46
+ * duplicate names are not allowed within one scope.
47
+ *
48
+ * @template T
49
+ * @template {import("./types.js").ParamRef<T>} R
50
+ * @param {string} scopeId
51
+ * @param {string} name
52
+ * @param {R} ref
53
+ * @returns {R}
54
+ */
55
+ register<T, R extends import("./types.js").ParamRef<T>>(scopeId: string, name: string, ref: R): R;
56
+ /**
57
+ * Resolves a parameter by name from `scopeId`, searching current scope
58
+ * first and then walking parent scopes until a match is found.
59
+ *
60
+ * @template T
61
+ * @param {string} scopeId
62
+ * @param {string} name
63
+ * @returns {import("./types.js").ParamRef<T> | undefined}
64
+ */
65
+ resolve<T>(scopeId: string, name: string): import("./types.js").ParamRef<T> | undefined;
66
+ #private;
67
+ }
68
+ //# sourceMappingURL=paramStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramStore.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/paramStore.js"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH;IAkBI;;;;;OAKG;IACH,yBAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;;OAMG;IACH,0BAJW,MAAM,eACN,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;OAKG;IACH,oBAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;OAKG;IACH,oBAFW,MAAM,QAShB;IAED;;;;;;;;;;;;OAYG;IACH,SAPa,CAAC,EACkC,CAAC,SAApC,OAAQ,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAE,WACpC,MAAM,QACN,MAAM,OACN,CAAC,GACC,CAAC,CAiBb;IAED;;;;;;;;OAQG;IACH,QALa,CAAC,WACH,MAAM,QACN,MAAM,GACJ,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAoBxD;;CACJ"}
@@ -0,0 +1,148 @@
1
+ import { validateParameterName } from "./paramUtils.js";
2
+
3
+ /**
4
+ * Runtime store for scoped parameter bindings.
5
+ *
6
+ * Responsibilities:
7
+ * 1. Maintain scope chain metadata (`scope -> parentScope`).
8
+ * 2. Store local bindings (`scope + name -> ParamRef`).
9
+ * 3. Resolve names using nearest-scope lookup through the parent chain.
10
+ *
11
+ * This class is intentionally storage-only: propagation/lifecycle is handled
12
+ * by higher-level runtime components.
13
+ */
14
+ export default class ParamStore {
15
+ #nextScopeId = 1;
16
+
17
+ /**
18
+ * @typedef {{
19
+ * parentScope?: string,
20
+ * params: Map<string, import("./types.js").ParamRef<any>>,
21
+ * ownerId: string
22
+ * }} ScopeRecord
23
+ */
24
+
25
+ /**
26
+ * Scope registry keyed by scope id.
27
+ *
28
+ * @type {Map<string, ScopeRecord>}
29
+ */
30
+ #scopes = new Map();
31
+
32
+ /**
33
+ * Creates a root scope with no parent scope.
34
+ *
35
+ * @param {string} ownerId
36
+ * @returns {string}
37
+ */
38
+ createRootScope(ownerId) {
39
+ const scopeId = "scope:" + this.#nextScopeId++;
40
+ this.#scopes.set(scopeId, { params: new Map(), ownerId });
41
+ return scopeId;
42
+ }
43
+
44
+ /**
45
+ * Creates a child scope whose fallback resolution target is `parentScope`.
46
+ *
47
+ * @param {string} ownerId
48
+ * @param {string} parentScope
49
+ * @returns {string}
50
+ */
51
+ createChildScope(ownerId, parentScope) {
52
+ if (!this.#scopes.has(parentScope)) {
53
+ throw new Error("Unknown parent scope: " + parentScope);
54
+ }
55
+
56
+ const scopeId = "scope:" + this.#nextScopeId++;
57
+ this.#scopes.set(scopeId, { parentScope, params: new Map(), ownerId });
58
+ return scopeId;
59
+ }
60
+
61
+ /**
62
+ * Returns lifecycle owner id associated with a scope.
63
+ *
64
+ * @param {string} scopeId
65
+ * @returns {string}
66
+ */
67
+ getOwnerId(scopeId) {
68
+ const scope = this.#scopes.get(scopeId);
69
+ if (!scope) {
70
+ throw new Error("Unknown scope: " + scopeId);
71
+ }
72
+ return scope.ownerId;
73
+ }
74
+
75
+ /**
76
+ * Clears all parameter bindings from a scope while keeping the scope chain
77
+ * metadata intact for descendants that may still resolve through it.
78
+ *
79
+ * @param {string} scopeId
80
+ */
81
+ clearScope(scopeId) {
82
+ const scope = this.#scopes.get(scopeId);
83
+ if (!scope) {
84
+ throw new Error("Unknown scope: " + scopeId);
85
+ }
86
+
87
+ scope.params.clear();
88
+ }
89
+
90
+ /**
91
+ * Registers a local parameter binding into `scopeId`.
92
+ *
93
+ * The same parameter name can exist in parent scopes (shadowing), but
94
+ * duplicate names are not allowed within one scope.
95
+ *
96
+ * @template T
97
+ * @template {import("./types.js").ParamRef<T>} R
98
+ * @param {string} scopeId
99
+ * @param {string} name
100
+ * @param {R} ref
101
+ * @returns {R}
102
+ */
103
+ register(scopeId, name, ref) {
104
+ validateParameterName(name);
105
+ const scope = this.#scopes.get(scopeId);
106
+ if (!scope) {
107
+ throw new Error("Unknown scope: " + scopeId);
108
+ }
109
+
110
+ if (scope.params.has(name)) {
111
+ throw new Error(
112
+ 'Parameter "' + name + '" already exists in scope ' + scopeId
113
+ );
114
+ }
115
+
116
+ scope.params.set(name, ref);
117
+ return ref;
118
+ }
119
+
120
+ /**
121
+ * Resolves a parameter by name from `scopeId`, searching current scope
122
+ * first and then walking parent scopes until a match is found.
123
+ *
124
+ * @template T
125
+ * @param {string} scopeId
126
+ * @param {string} name
127
+ * @returns {import("./types.js").ParamRef<T> | undefined}
128
+ */
129
+ resolve(scopeId, name) {
130
+ validateParameterName(name);
131
+
132
+ let currentScopeId = scopeId;
133
+ while (currentScopeId) {
134
+ const scope = this.#scopes.get(currentScopeId);
135
+ if (!scope) {
136
+ throw new Error("Unknown scope: " + currentScopeId);
137
+ }
138
+
139
+ const ref = scope.params.get(name);
140
+ if (ref) {
141
+ return /** @type {import("./types.js").ParamRef<T>} */ (ref);
142
+ }
143
+ currentScopeId = scope.parentScope;
144
+ }
145
+
146
+ return undefined;
147
+ }
148
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=paramStore.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramStore.test.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/paramStore.test.js"],"names":[],"mappings":""}