@invinite-org/chartlang-runtime 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +236 -0
- package/dist/barPoint.d.ts +20 -0
- package/dist/barPoint.d.ts.map +1 -0
- package/dist/barPoint.js +72 -0
- package/dist/barPoint.js.map +1 -0
- package/dist/bufferSnapshot.d.ts +102 -0
- package/dist/bufferSnapshot.d.ts.map +1 -0
- package/dist/bufferSnapshot.js +119 -0
- package/dist/bufferSnapshot.js.map +1 -0
- package/dist/createScriptRunner.d.ts +6 -3
- package/dist/createScriptRunner.d.ts.map +1 -1
- package/dist/createScriptRunner.js +29 -5
- package/dist/createScriptRunner.js.map +1 -1
- package/dist/dep/DepRunner.d.ts.map +1 -1
- package/dist/dep/DepRunner.js +1 -0
- package/dist/dep/DepRunner.js.map +1 -1
- package/dist/emit/draw/boxes/fillBetween.d.ts +45 -0
- package/dist/emit/draw/boxes/fillBetween.d.ts.map +1 -0
- package/dist/emit/draw/boxes/fillBetween.js +36 -0
- package/dist/emit/draw/boxes/fillBetween.js.map +1 -0
- package/dist/emit/draw/handle.d.ts +9 -0
- package/dist/emit/draw/handle.d.ts.map +1 -1
- package/dist/emit/draw/handle.js +65 -10
- package/dist/emit/draw/handle.js.map +1 -1
- package/dist/emit/draw/namespace.d.ts +4 -3
- package/dist/emit/draw/namespace.d.ts.map +1 -1
- package/dist/emit/draw/namespace.js +6 -3
- package/dist/emit/draw/namespace.js.map +1 -1
- package/dist/emit/plot.d.ts +7 -0
- package/dist/emit/plot.d.ts.map +1 -1
- package/dist/emit/plot.js +13 -0
- package/dist/emit/plot.js.map +1 -1
- package/dist/execution/dispose.d.ts.map +1 -1
- package/dist/execution/dispose.js +16 -0
- package/dist/execution/dispose.js.map +1 -1
- package/dist/execution/runComputeStep.d.ts.map +1 -1
- package/dist/execution/runComputeStep.js +10 -1
- package/dist/execution/runComputeStep.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/persistentStateStore.runtime.d.ts.map +1 -1
- package/dist/persistentStateStore.runtime.js +21 -7
- package/dist/persistentStateStore.runtime.js.map +1 -1
- package/dist/request/index.d.ts +2 -1
- package/dist/request/index.d.ts.map +1 -1
- package/dist/request/index.js +2 -1
- package/dist/request/index.js.map +1 -1
- package/dist/request/requestNamespace.d.ts.map +1 -1
- package/dist/request/requestNamespace.js +16 -3
- package/dist/request/requestNamespace.js.map +1 -1
- package/dist/request/security.d.ts +20 -1
- package/dist/request/security.d.ts.map +1 -1
- package/dist/request/security.js +62 -23
- package/dist/request/security.js.map +1 -1
- package/dist/request/securityExprRunner.d.ts +133 -0
- package/dist/request/securityExprRunner.d.ts.map +1 -0
- package/dist/request/securityExprRunner.js +235 -0
- package/dist/request/securityExprRunner.js.map +1 -0
- package/dist/request/streamBars.d.ts +14 -1
- package/dist/request/streamBars.d.ts.map +1 -1
- package/dist/request/streamBars.js +39 -1
- package/dist/request/streamBars.js.map +1 -1
- package/dist/runtimeContext.d.ts +48 -0
- package/dist/runtimeContext.d.ts.map +1 -1
- package/dist/runtimeContext.js.map +1 -1
- package/dist/seriesView.d.ts +42 -17
- package/dist/seriesView.d.ts.map +1 -1
- package/dist/seriesView.js +65 -42
- package/dist/seriesView.js.map +1 -1
- package/dist/state/index.d.ts +2 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +2 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/lifecycle.d.ts +40 -0
- package/dist/state/lifecycle.d.ts.map +1 -1
- package/dist/state/lifecycle.js +53 -0
- package/dist/state/lifecycle.js.map +1 -1
- package/dist/state/seriesPersistence.d.ts +48 -0
- package/dist/state/seriesPersistence.d.ts.map +1 -0
- package/dist/state/seriesPersistence.js +87 -0
- package/dist/state/seriesPersistence.js.map +1 -0
- package/dist/state/seriesSlot.d.ts +105 -0
- package/dist/state/seriesSlot.d.ts.map +1 -0
- package/dist/state/seriesSlot.js +123 -0
- package/dist/state/seriesSlot.js.map +1 -0
- package/dist/state/stateNamespace.d.ts.map +1 -1
- package/dist/state/stateNamespace.js +28 -0
- package/dist/state/stateNamespace.js.map +1 -1
- package/dist/streamState.d.ts +25 -19
- package/dist/streamState.d.ts.map +1 -1
- package/dist/streamState.js +40 -66
- package/dist/streamState.js.map +1 -1
- package/dist/ta/adx.d.ts +3 -2
- package/dist/ta/adx.d.ts.map +1 -1
- package/dist/ta/adx.js +3 -2
- package/dist/ta/adx.js.map +1 -1
- package/dist/ta/alma.d.ts +6 -4
- package/dist/ta/alma.d.ts.map +1 -1
- package/dist/ta/alma.js +19 -6
- package/dist/ta/alma.js.map +1 -1
- package/dist/ta/atr.d.ts +3 -2
- package/dist/ta/atr.d.ts.map +1 -1
- package/dist/ta/atr.js +3 -2
- package/dist/ta/atr.js.map +1 -1
- package/dist/ta/bb.d.ts +3 -2
- package/dist/ta/bb.d.ts.map +1 -1
- package/dist/ta/bb.js +3 -2
- package/dist/ta/bb.js.map +1 -1
- package/dist/ta/chaikinOsc.d.ts +3 -2
- package/dist/ta/chaikinOsc.d.ts.map +1 -1
- package/dist/ta/chaikinOsc.js +3 -2
- package/dist/ta/chaikinOsc.js.map +1 -1
- package/dist/ta/crossover.d.ts +3 -2
- package/dist/ta/crossover.d.ts.map +1 -1
- package/dist/ta/crossover.js +3 -2
- package/dist/ta/crossover.js.map +1 -1
- package/dist/ta/crossunder.d.ts +3 -2
- package/dist/ta/crossunder.d.ts.map +1 -1
- package/dist/ta/crossunder.js +3 -2
- package/dist/ta/crossunder.js.map +1 -1
- package/dist/ta/dmi.d.ts +4 -3
- package/dist/ta/dmi.d.ts.map +1 -1
- package/dist/ta/dmi.js +4 -3
- package/dist/ta/dmi.js.map +1 -1
- package/dist/ta/ema.d.ts +3 -2
- package/dist/ta/ema.d.ts.map +1 -1
- package/dist/ta/ema.js +3 -2
- package/dist/ta/ema.js.map +1 -1
- package/dist/ta/eom.d.ts +3 -1
- package/dist/ta/eom.d.ts.map +1 -1
- package/dist/ta/eom.js +3 -1
- package/dist/ta/eom.js.map +1 -1
- package/dist/ta/highestbars.d.ts +25 -0
- package/dist/ta/highestbars.d.ts.map +1 -0
- package/dist/ta/highestbars.js +106 -0
- package/dist/ta/highestbars.js.map +1 -0
- package/dist/ta/historicalVolatility.d.ts +3 -2
- package/dist/ta/historicalVolatility.d.ts.map +1 -1
- package/dist/ta/historicalVolatility.js +3 -2
- package/dist/ta/historicalVolatility.js.map +1 -1
- package/dist/ta/ichimoku.d.ts +3 -1
- package/dist/ta/ichimoku.d.ts.map +1 -1
- package/dist/ta/ichimoku.js +3 -1
- package/dist/ta/ichimoku.js.map +1 -1
- package/dist/ta/lowestbars.d.ts +25 -0
- package/dist/ta/lowestbars.d.ts.map +1 -0
- package/dist/ta/lowestbars.js +102 -0
- package/dist/ta/lowestbars.js.map +1 -0
- package/dist/ta/macd.d.ts +3 -2
- package/dist/ta/macd.d.ts.map +1 -1
- package/dist/ta/macd.js +3 -2
- package/dist/ta/macd.js.map +1 -1
- package/dist/ta/massIndex.d.ts +3 -2
- package/dist/ta/massIndex.d.ts.map +1 -1
- package/dist/ta/massIndex.js +3 -2
- package/dist/ta/massIndex.js.map +1 -1
- package/dist/ta/mfi.d.ts +3 -1
- package/dist/ta/mfi.d.ts.map +1 -1
- package/dist/ta/mfi.js +3 -1
- package/dist/ta/mfi.js.map +1 -1
- package/dist/ta/netVolume.d.ts +3 -1
- package/dist/ta/netVolume.d.ts.map +1 -1
- package/dist/ta/netVolume.js +3 -1
- package/dist/ta/netVolume.js.map +1 -1
- package/dist/ta/nvi.d.ts +3 -1
- package/dist/ta/nvi.d.ts.map +1 -1
- package/dist/ta/nvi.js +3 -1
- package/dist/ta/nvi.js.map +1 -1
- package/dist/ta/persistence.d.ts.map +1 -1
- package/dist/ta/persistence.js +1 -40
- package/dist/ta/persistence.js.map +1 -1
- package/dist/ta/ppo.d.ts +3 -2
- package/dist/ta/ppo.d.ts.map +1 -1
- package/dist/ta/ppo.js +3 -2
- package/dist/ta/ppo.js.map +1 -1
- package/dist/ta/pvi.d.ts +3 -1
- package/dist/ta/pvi.d.ts.map +1 -1
- package/dist/ta/pvi.js +3 -1
- package/dist/ta/pvi.js.map +1 -1
- package/dist/ta/pvo.d.ts +3 -1
- package/dist/ta/pvo.d.ts.map +1 -1
- package/dist/ta/pvo.js +3 -1
- package/dist/ta/pvo.js.map +1 -1
- package/dist/ta/pvt.d.ts +3 -1
- package/dist/ta/pvt.d.ts.map +1 -1
- package/dist/ta/pvt.js +3 -1
- package/dist/ta/pvt.js.map +1 -1
- package/dist/ta/registry.d.ts +7 -1
- package/dist/ta/registry.d.ts.map +1 -1
- package/dist/ta/registry.js +4 -0
- package/dist/ta/registry.js.map +1 -1
- package/dist/ta/rsi.d.ts +3 -2
- package/dist/ta/rsi.d.ts.map +1 -1
- package/dist/ta/rsi.js +3 -2
- package/dist/ta/rsi.js.map +1 -1
- package/dist/ta/rvi.d.ts +3 -2
- package/dist/ta/rvi.d.ts.map +1 -1
- package/dist/ta/rvi.js +3 -2
- package/dist/ta/rvi.js.map +1 -1
- package/dist/ta/sma.d.ts +6 -3
- package/dist/ta/sma.d.ts.map +1 -1
- package/dist/ta/sma.js +6 -3
- package/dist/ta/sma.js.map +1 -1
- package/dist/ta/stdev.d.ts +3 -2
- package/dist/ta/stdev.d.ts.map +1 -1
- package/dist/ta/stdev.js +3 -2
- package/dist/ta/stdev.js.map +1 -1
- package/dist/ta/trendStrengthIndex.d.ts +3 -2
- package/dist/ta/trendStrengthIndex.d.ts.map +1 -1
- package/dist/ta/trendStrengthIndex.js +3 -2
- package/dist/ta/trendStrengthIndex.js.map +1 -1
- package/dist/ta/trix.d.ts +4 -3
- package/dist/ta/trix.d.ts.map +1 -1
- package/dist/ta/trix.js +4 -3
- package/dist/ta/trix.js.map +1 -1
- package/dist/ta/vortex.d.ts +3 -2
- package/dist/ta/vortex.d.ts.map +1 -1
- package/dist/ta/vortex.js +3 -2
- package/dist/ta/vortex.js.map +1 -1
- package/package.json +3 -3
- package/dist/ta/lib/applyOffset.d.ts +0 -19
- package/dist/ta/lib/applyOffset.d.ts.map +0 -1
- package/dist/ta/lib/applyOffset.js +0 -38
- package/dist/ta/lib/applyOffset.js.map +0 -1
package/dist/seriesView.d.ts
CHANGED
|
@@ -10,6 +10,14 @@ import type { RingBufferLike } from "./ringBuffer.js";
|
|
|
10
10
|
* Property reads dispatch as follows:
|
|
11
11
|
* - `series.current` → `buf.at(0)`
|
|
12
12
|
* - `series.length` → `buf.length`
|
|
13
|
+
* - `series.valueOf` / `series[Symbol.toPrimitive]` → a function returning
|
|
14
|
+
* `buf.at(0)`, so a numeric series coerces to its **current** value in any
|
|
15
|
+
* value context (`series * 2`, `series > x`, `` `${series}` ``,
|
|
16
|
+
* `Math.max(series, …)`). This is what lets `bar.close` be used both as a
|
|
17
|
+
* scalar and indexed as a series. Coercion is harmless for non-numeric
|
|
18
|
+
* buffers — nothing coerces those. Note `Number.isFinite(series)` is still
|
|
19
|
+
* `false` (it does not coerce) and `series === 42` is `false` (object vs
|
|
20
|
+
* number); use `series.current` / `+series` there.
|
|
13
21
|
* - `series[n]` (string coerces to a non-negative integer) → `buf.at(n)`
|
|
14
22
|
* - any other key → `undefined`
|
|
15
23
|
*
|
|
@@ -30,30 +38,47 @@ import type { RingBufferLike } from "./ringBuffer.js";
|
|
|
30
38
|
*/
|
|
31
39
|
export declare function makeSeriesView<T>(buf: RingBufferLike<T>): Series<T>;
|
|
32
40
|
/**
|
|
33
|
-
* Offset-
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* `
|
|
37
|
-
* `
|
|
38
|
-
* `
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* `RingBuffer`).
|
|
41
|
+
* Offset-tagging variant of {@link makeSeriesView}. It returns the
|
|
42
|
+
* **unshifted** view (delegating to {@link makeSeriesView}) and, for a
|
|
43
|
+
* non-zero `offset`, records `view → offset` in a module-level
|
|
44
|
+
* `WeakMap` side-table read by `plot()` via {@link seriesOffsetOf}. The
|
|
45
|
+
* offset is **presentation-only** — `view.current` is `buf.at(0)`, not a
|
|
46
|
+
* value `offset` bars ago — so both shift directions are expressible and
|
|
47
|
+
* alerts / `state.*` see the unshifted value. `offset === 0` records
|
|
48
|
+
* nothing (byte-identical to a plain {@link makeSeriesView}).
|
|
42
49
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
50
|
+
* Callers cache the returned view per `(slot, offset)` pair so the
|
|
51
|
+
* view's identity — and therefore its recorded offset — stays stable
|
|
52
|
+
* across bars.
|
|
46
53
|
*
|
|
47
54
|
* @since 0.2
|
|
55
|
+
* @stable
|
|
48
56
|
* @example
|
|
49
|
-
* // import { Float64RingBuffer, makeShiftedSeriesView }
|
|
57
|
+
* // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }
|
|
50
58
|
* // from "@invinite-org/chartlang-runtime";
|
|
51
59
|
* // const buf = new Float64RingBuffer(8);
|
|
52
60
|
* // buf.append(10); buf.append(20); buf.append(30);
|
|
53
|
-
* // const view = makeShiftedSeriesView<number>(buf,
|
|
54
|
-
* // view.current;
|
|
55
|
-
* // view
|
|
56
|
-
* // view[1]; // 10
|
|
61
|
+
* // const view = makeShiftedSeriesView<number>(buf, 5);
|
|
62
|
+
* // view.current; // 30 (unshifted — the offset does NOT lag the read)
|
|
63
|
+
* // seriesOffsetOf(view); // 5 (presentation x-shift carried to the emission)
|
|
57
64
|
*/
|
|
58
65
|
export declare function makeShiftedSeriesView<T>(buf: RingBufferLike<T>, offset: number): Series<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Read the presentation x-shift recorded for `series` by
|
|
68
|
+
* {@link makeShiftedSeriesView}, or `0` when the series is untagged (a
|
|
69
|
+
* plain {@link makeSeriesView} view, an `offset === 0` view, or any
|
|
70
|
+
* non-runtime Series). `plot()` calls this to populate
|
|
71
|
+
* `PlotEmission.xShift`; a `0` result omits the field so a no-offset
|
|
72
|
+
* plot stays byte-identical to today.
|
|
73
|
+
*
|
|
74
|
+
* @since 0.2
|
|
75
|
+
* @stable
|
|
76
|
+
* @example
|
|
77
|
+
* // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }
|
|
78
|
+
* // from "@invinite-org/chartlang-runtime";
|
|
79
|
+
* // const buf = new Float64RingBuffer(8);
|
|
80
|
+
* // const shifted = makeShiftedSeriesView<number>(buf, -3);
|
|
81
|
+
* // seriesOffsetOf(shifted); // -3
|
|
82
|
+
*/
|
|
83
|
+
export declare function seriesOffsetOf(series: Series<unknown>): number;
|
|
59
84
|
//# sourceMappingURL=seriesView.d.ts.map
|
package/dist/seriesView.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seriesView.d.ts","sourceRoot":"","sources":["../src/seriesView.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD
|
|
1
|
+
{"version":3,"file":"seriesView.d.ts","sourceRoot":"","sources":["../src/seriesView.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAuBnE;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAI1F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAE9D"}
|
package/dist/seriesView.js
CHANGED
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* Property reads dispatch as follows:
|
|
11
11
|
* - `series.current` → `buf.at(0)`
|
|
12
12
|
* - `series.length` → `buf.length`
|
|
13
|
+
* - `series.valueOf` / `series[Symbol.toPrimitive]` → a function returning
|
|
14
|
+
* `buf.at(0)`, so a numeric series coerces to its **current** value in any
|
|
15
|
+
* value context (`series * 2`, `series > x`, `` `${series}` ``,
|
|
16
|
+
* `Math.max(series, …)`). This is what lets `bar.close` be used both as a
|
|
17
|
+
* scalar and indexed as a series. Coercion is harmless for non-numeric
|
|
18
|
+
* buffers — nothing coerces those. Note `Number.isFinite(series)` is still
|
|
19
|
+
* `false` (it does not coerce) and `series === 42` is `false` (object vs
|
|
20
|
+
* number); use `series.current` / `+series` there.
|
|
13
21
|
* - `series[n]` (string coerces to a non-negative integer) → `buf.at(n)`
|
|
14
22
|
* - any other key → `undefined`
|
|
15
23
|
*
|
|
@@ -35,6 +43,10 @@ export function makeSeriesView(buf) {
|
|
|
35
43
|
return buf.at(0);
|
|
36
44
|
if (prop === "length")
|
|
37
45
|
return buf.length;
|
|
46
|
+
if (prop === "valueOf")
|
|
47
|
+
return () => buf.at(0);
|
|
48
|
+
if (prop === Symbol.toPrimitive)
|
|
49
|
+
return () => buf.at(0);
|
|
38
50
|
if (typeof prop === "string") {
|
|
39
51
|
const n = Number(prop);
|
|
40
52
|
if (Number.isInteger(n) && n >= 0)
|
|
@@ -45,6 +57,8 @@ export function makeSeriesView(buf) {
|
|
|
45
57
|
has(_target, prop) {
|
|
46
58
|
if (prop === "current" || prop === "length")
|
|
47
59
|
return true;
|
|
60
|
+
if (prop === "valueOf" || prop === Symbol.toPrimitive)
|
|
61
|
+
return true;
|
|
48
62
|
if (typeof prop === "string") {
|
|
49
63
|
const n = Number(prop);
|
|
50
64
|
return Number.isInteger(n) && n >= 0;
|
|
@@ -54,56 +68,65 @@ export function makeSeriesView(buf) {
|
|
|
54
68
|
});
|
|
55
69
|
}
|
|
56
70
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* `
|
|
62
|
-
* `
|
|
63
|
-
* `
|
|
64
|
-
*
|
|
65
|
-
|
|
71
|
+
* Module-level side-table recording the **presentation x-shift** declared
|
|
72
|
+
* for an offset-tagged Series view. `offset` is no longer a value-read
|
|
73
|
+
* transform (Option A, bidirectional-plot-offset): the series value is
|
|
74
|
+
* always the unshifted `buf.at(0)`; the recorded offset rides the plot
|
|
75
|
+
* emission as `PlotEmission.xShift` so the adapter renders the series
|
|
76
|
+
* shifted (`+n` right / future, `−n` left / past) without changing the
|
|
77
|
+
* numbers alerts and `state.*` see. Keyed weakly on the view object so a
|
|
78
|
+
* dropped slot's tag is collected with it.
|
|
79
|
+
*/
|
|
80
|
+
const seriesOffsets = new WeakMap();
|
|
81
|
+
/**
|
|
82
|
+
* Offset-tagging variant of {@link makeSeriesView}. It returns the
|
|
83
|
+
* **unshifted** view (delegating to {@link makeSeriesView}) and, for a
|
|
84
|
+
* non-zero `offset`, records `view → offset` in a module-level
|
|
85
|
+
* `WeakMap` side-table read by `plot()` via {@link seriesOffsetOf}. The
|
|
86
|
+
* offset is **presentation-only** — `view.current` is `buf.at(0)`, not a
|
|
87
|
+
* value `offset` bars ago — so both shift directions are expressible and
|
|
88
|
+
* alerts / `state.*` see the unshifted value. `offset === 0` records
|
|
89
|
+
* nothing (byte-identical to a plain {@link makeSeriesView}).
|
|
66
90
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
91
|
+
* Callers cache the returned view per `(slot, offset)` pair so the
|
|
92
|
+
* view's identity — and therefore its recorded offset — stays stable
|
|
93
|
+
* across bars.
|
|
70
94
|
*
|
|
71
95
|
* @since 0.2
|
|
96
|
+
* @stable
|
|
72
97
|
* @example
|
|
73
|
-
* // import { Float64RingBuffer, makeShiftedSeriesView }
|
|
98
|
+
* // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }
|
|
74
99
|
* // from "@invinite-org/chartlang-runtime";
|
|
75
100
|
* // const buf = new Float64RingBuffer(8);
|
|
76
101
|
* // buf.append(10); buf.append(20); buf.append(30);
|
|
77
|
-
* // const view = makeShiftedSeriesView<number>(buf,
|
|
78
|
-
* // view.current;
|
|
79
|
-
* // view
|
|
80
|
-
* // view[1]; // 10
|
|
102
|
+
* // const view = makeShiftedSeriesView<number>(buf, 5);
|
|
103
|
+
* // view.current; // 30 (unshifted — the offset does NOT lag the read)
|
|
104
|
+
* // seriesOffsetOf(view); // 5 (presentation x-shift carried to the emission)
|
|
81
105
|
*/
|
|
82
106
|
export function makeShiftedSeriesView(buf, offset) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
});
|
|
107
|
+
const view = makeSeriesView(buf);
|
|
108
|
+
if (offset !== 0)
|
|
109
|
+
seriesOffsets.set(view, offset);
|
|
110
|
+
return view;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Read the presentation x-shift recorded for `series` by
|
|
114
|
+
* {@link makeShiftedSeriesView}, or `0` when the series is untagged (a
|
|
115
|
+
* plain {@link makeSeriesView} view, an `offset === 0` view, or any
|
|
116
|
+
* non-runtime Series). `plot()` calls this to populate
|
|
117
|
+
* `PlotEmission.xShift`; a `0` result omits the field so a no-offset
|
|
118
|
+
* plot stays byte-identical to today.
|
|
119
|
+
*
|
|
120
|
+
* @since 0.2
|
|
121
|
+
* @stable
|
|
122
|
+
* @example
|
|
123
|
+
* // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }
|
|
124
|
+
* // from "@invinite-org/chartlang-runtime";
|
|
125
|
+
* // const buf = new Float64RingBuffer(8);
|
|
126
|
+
* // const shifted = makeShiftedSeriesView<number>(buf, -3);
|
|
127
|
+
* // seriesOffsetOf(shifted); // -3
|
|
128
|
+
*/
|
|
129
|
+
export function seriesOffsetOf(series) {
|
|
130
|
+
return seriesOffsets.get(series) ?? 0;
|
|
108
131
|
}
|
|
109
132
|
//# sourceMappingURL=seriesView.js.map
|
package/dist/seriesView.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seriesView.js","sourceRoot":"","sources":["../src/seriesView.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAM/D
|
|
1
|
+
{"version":3,"file":"seriesView.js","sourceRoot":"","sources":["../src/seriesView.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAM/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,cAAc,CAAI,GAAsB;IACpD,OAAO,IAAI,KAAK,CAAC,EAAe,EAAE;QAC9B,GAAG,CAAC,OAAO,EAAE,IAAI;YACb,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,GAAG,CAAC,MAAM,CAAC;YACzC,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,IAAI,KAAK,MAAM,CAAC,WAAW;gBAAE,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvB,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,GAAG,CAAC,OAAO,EAAE,IAAI;YACb,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC;YACnE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvB,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;KACJ,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,aAAa,GAAG,IAAI,OAAO,EAA2B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,qBAAqB,CAAI,GAAsB,EAAE,MAAc;IAC3E,MAAM,IAAI,GAAG,cAAc,CAAI,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,CAAC;QAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAAC,MAAuB;IAClD,OAAO,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { Series } from \"@invinite-org/chartlang-core\";\n\nimport type { RingBufferLike } from \"./ringBuffer.js\";\n\n/**\n * Wrap a `RingBufferLike<T>` in the user-facing `Series<T>` Proxy shape\n *. The Proxy is created **once per backing buffer**\n * at stream/slot construction time and re-used across every bar — its\n * identity is stable so script authors can keep `const ema = ta.ema(...)`\n * at the top of `compute` and reference `ema` the same way every bar.\n *\n * Property reads dispatch as follows:\n * - `series.current` → `buf.at(0)`\n * - `series.length` → `buf.length`\n * - `series.valueOf` / `series[Symbol.toPrimitive]` → a function returning\n * `buf.at(0)`, so a numeric series coerces to its **current** value in any\n * value context (`series * 2`, `series > x`, `` `${series}` ``,\n * `Math.max(series, …)`). This is what lets `bar.close` be used both as a\n * scalar and indexed as a series. Coercion is harmless for non-numeric\n * buffers — nothing coerces those. Note `Number.isFinite(series)` is still\n * `false` (it does not coerce) and `series === 42` is `false` (object vs\n * number); use `series.current` / `+series` there.\n * - `series[n]` (string coerces to a non-negative integer) → `buf.at(n)`\n * - any other key → `undefined`\n *\n * For numeric buffers (`Float64RingBuffer`) out-of-range reads return\n * `NaN`; for object buffers they return `undefined`. The Proxy passes\n * the underlying sentinel through verbatim.\n *\n * @since 0.1\n * @example\n * // import { Float64RingBuffer, makeSeriesView }\n * // from \"@invinite-org/chartlang-runtime\";\n * // const buf = new Float64RingBuffer(8);\n * // const view = makeSeriesView<number>(buf);\n * // buf.append(42);\n * // view.current; // 42\n * // view[0]; // 42\n * // view.length; // 1\n */\nexport function makeSeriesView<T>(buf: RingBufferLike<T>): Series<T> {\n return new Proxy({} as Series<T>, {\n get(_target, prop) {\n if (prop === \"current\") return buf.at(0);\n if (prop === \"length\") return buf.length;\n if (prop === \"valueOf\") return () => buf.at(0);\n if (prop === Symbol.toPrimitive) return () => buf.at(0);\n if (typeof prop === \"string\") {\n const n = Number(prop);\n if (Number.isInteger(n) && n >= 0) return buf.at(n);\n }\n return undefined;\n },\n has(_target, prop) {\n if (prop === \"current\" || prop === \"length\") return true;\n if (prop === \"valueOf\" || prop === Symbol.toPrimitive) return true;\n if (typeof prop === \"string\") {\n const n = Number(prop);\n return Number.isInteger(n) && n >= 0;\n }\n return false;\n },\n });\n}\n\n/**\n * Module-level side-table recording the **presentation x-shift** declared\n * for an offset-tagged Series view. `offset` is no longer a value-read\n * transform (Option A, bidirectional-plot-offset): the series value is\n * always the unshifted `buf.at(0)`; the recorded offset rides the plot\n * emission as `PlotEmission.xShift` so the adapter renders the series\n * shifted (`+n` right / future, `−n` left / past) without changing the\n * numbers alerts and `state.*` see. Keyed weakly on the view object so a\n * dropped slot's tag is collected with it.\n */\nconst seriesOffsets = new WeakMap<Series<unknown>, number>();\n\n/**\n * Offset-tagging variant of {@link makeSeriesView}. It returns the\n * **unshifted** view (delegating to {@link makeSeriesView}) and, for a\n * non-zero `offset`, records `view → offset` in a module-level\n * `WeakMap` side-table read by `plot()` via {@link seriesOffsetOf}. The\n * offset is **presentation-only** — `view.current` is `buf.at(0)`, not a\n * value `offset` bars ago — so both shift directions are expressible and\n * alerts / `state.*` see the unshifted value. `offset === 0` records\n * nothing (byte-identical to a plain {@link makeSeriesView}).\n *\n * Callers cache the returned view per `(slot, offset)` pair so the\n * view's identity — and therefore its recorded offset — stays stable\n * across bars.\n *\n * @since 0.2\n * @stable\n * @example\n * // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }\n * // from \"@invinite-org/chartlang-runtime\";\n * // const buf = new Float64RingBuffer(8);\n * // buf.append(10); buf.append(20); buf.append(30);\n * // const view = makeShiftedSeriesView<number>(buf, 5);\n * // view.current; // 30 (unshifted — the offset does NOT lag the read)\n * // seriesOffsetOf(view); // 5 (presentation x-shift carried to the emission)\n */\nexport function makeShiftedSeriesView<T>(buf: RingBufferLike<T>, offset: number): Series<T> {\n const view = makeSeriesView<T>(buf);\n if (offset !== 0) seriesOffsets.set(view, offset);\n return view;\n}\n\n/**\n * Read the presentation x-shift recorded for `series` by\n * {@link makeShiftedSeriesView}, or `0` when the series is untagged (a\n * plain {@link makeSeriesView} view, an `offset === 0` view, or any\n * non-runtime Series). `plot()` calls this to populate\n * `PlotEmission.xShift`; a `0` result omits the field so a no-offset\n * plot stays byte-identical to today.\n *\n * @since 0.2\n * @stable\n * @example\n * // import { Float64RingBuffer, makeShiftedSeriesView, seriesOffsetOf }\n * // from \"@invinite-org/chartlang-runtime\";\n * // const buf = new Float64RingBuffer(8);\n * // const shifted = makeShiftedSeriesView<number>(buf, -3);\n * // seriesOffsetOf(shifted); // -3\n */\nexport function seriesOffsetOf(series: Series<unknown>): number {\n return seriesOffsets.get(series) ?? 0;\n}\n"]}
|
package/dist/state/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { commitStateSlots, flushStateSlots, restoreStateSlots, resetTentativeStateSlots, serialiseStateSlots, } from "./lifecycle.js";
|
|
1
|
+
export { advanceSeriesSlots, commitSeriesSlots, commitStateSlots, flushStateSlots, resetSeriesHeads, restoreStateSlots, resetTentativeStateSlots, serialiseStateSlots, } from "./lifecycle.js";
|
|
2
2
|
export type { StateSlotSnapshot } from "./lifecycle.js";
|
|
3
|
+
export { isSeriesSlotSnapshotKey, restoreSeriesSlots, serialiseSeriesSlots, } from "./seriesPersistence.js";
|
|
3
4
|
export { buildStateNamespace } from "./stateNamespace.js";
|
|
4
5
|
export type { StateSlotSerialisers } from "./stateSlot.js";
|
|
5
6
|
export { asMutableSlot, StateSlot } from "./stateSlot.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACH,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/state/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
2
|
// See the LICENSE file in the repo root for full license text.
|
|
3
|
-
export { commitStateSlots, flushStateSlots, restoreStateSlots, resetTentativeStateSlots, serialiseStateSlots, } from "./lifecycle.js";
|
|
3
|
+
export { advanceSeriesSlots, commitSeriesSlots, commitStateSlots, flushStateSlots, resetSeriesHeads, restoreStateSlots, resetTentativeStateSlots, serialiseStateSlots, } from "./lifecycle.js";
|
|
4
|
+
export { isSeriesSlotSnapshotKey, restoreSeriesSlots, serialiseSeriesSlots, } from "./seriesPersistence.js";
|
|
4
5
|
export { buildStateNamespace } from "./stateNamespace.js";
|
|
5
6
|
export { asMutableSlot, StateSlot } from "./stateSlot.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/state/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport {\n commitStateSlots,\n flushStateSlots,\n restoreStateSlots,\n resetTentativeStateSlots,\n serialiseStateSlots,\n} from \"./lifecycle.js\";\nexport type { StateSlotSnapshot } from \"./lifecycle.js\";\nexport { buildStateNamespace } from \"./stateNamespace.js\";\nexport type { StateSlotSerialisers } from \"./stateSlot.js\";\nexport { asMutableSlot, StateSlot } from \"./stateSlot.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EACH,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport {\n advanceSeriesSlots,\n commitSeriesSlots,\n commitStateSlots,\n flushStateSlots,\n resetSeriesHeads,\n restoreStateSlots,\n resetTentativeStateSlots,\n serialiseStateSlots,\n} from \"./lifecycle.js\";\nexport type { StateSlotSnapshot } from \"./lifecycle.js\";\nexport {\n isSeriesSlotSnapshotKey,\n restoreSeriesSlots,\n serialiseSeriesSlots,\n} from \"./seriesPersistence.js\";\nexport { buildStateNamespace } from \"./stateNamespace.js\";\nexport type { StateSlotSerialisers } from \"./stateSlot.js\";\nexport { asMutableSlot, StateSlot } from \"./stateSlot.js\";\n"]}
|
|
@@ -72,4 +72,44 @@ export declare function serialiseStateSlots(ctx: RuntimeContext): Readonly<Recor
|
|
|
72
72
|
* void restored;
|
|
73
73
|
*/
|
|
74
74
|
export declare function restoreStateSlots(ctx: RuntimeContext, slots: Readonly<Record<string, unknown>>): void;
|
|
75
|
+
/**
|
|
76
|
+
* Advance every `state.series` ring once for a new close bar — append a
|
|
77
|
+
* fresh `NaN` head so the prior committed head slides to index 1. Runs
|
|
78
|
+
* BEFORE compute on close, so a slot first allocated mid-compute (already
|
|
79
|
+
* holding its seeded head) is not present here and is not double-advanced.
|
|
80
|
+
*
|
|
81
|
+
* @since 0.9
|
|
82
|
+
* @stable
|
|
83
|
+
* @example
|
|
84
|
+
* // advanceSeriesSlots(ctx);
|
|
85
|
+
* const advanced = true;
|
|
86
|
+
* void advanced;
|
|
87
|
+
*/
|
|
88
|
+
export declare function advanceSeriesSlots(ctx: RuntimeContext): void;
|
|
89
|
+
/**
|
|
90
|
+
* Commit every `state.series` live head as its bar-close value after
|
|
91
|
+
* close compute, so the next advance retains it and a tick can reset to
|
|
92
|
+
* it.
|
|
93
|
+
*
|
|
94
|
+
* @since 0.9
|
|
95
|
+
* @stable
|
|
96
|
+
* @example
|
|
97
|
+
* // commitSeriesSlots(ctx);
|
|
98
|
+
* const committed = true;
|
|
99
|
+
* void committed;
|
|
100
|
+
*/
|
|
101
|
+
export declare function commitSeriesSlots(ctx: RuntimeContext): void;
|
|
102
|
+
/**
|
|
103
|
+
* Reset every `state.series` live head to its last committed value before
|
|
104
|
+
* tick compute, so a re-write refines from the committed baseline and a
|
|
105
|
+
* tick without a write reads the committed head. Does NOT advance length.
|
|
106
|
+
*
|
|
107
|
+
* @since 0.9
|
|
108
|
+
* @stable
|
|
109
|
+
* @example
|
|
110
|
+
* // resetSeriesHeads(ctx);
|
|
111
|
+
* const reset = true;
|
|
112
|
+
* void reset;
|
|
113
|
+
*/
|
|
114
|
+
export declare function resetSeriesHeads(ctx: RuntimeContext): void;
|
|
75
115
|
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/state/lifecycle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/state/lifecycle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IAC/B,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;CACzB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAIlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAI1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAOzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAS1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACzC,IAAI,CAKN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAI5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAI3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAI1D"}
|
package/dist/state/lifecycle.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
2
|
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
import { advanceSeriesSlot, commitSeriesSlot, resetSeriesSlotHead } from "./seriesSlot.js";
|
|
3
4
|
/**
|
|
4
5
|
* Reset all non-`state.tick.*` tentative values before tick compute.
|
|
5
6
|
*
|
|
@@ -84,4 +85,56 @@ export function restoreStateSlots(ctx, slots) {
|
|
|
84
85
|
ctx.stateStore.set(key, value);
|
|
85
86
|
}
|
|
86
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Advance every `state.series` ring once for a new close bar — append a
|
|
90
|
+
* fresh `NaN` head so the prior committed head slides to index 1. Runs
|
|
91
|
+
* BEFORE compute on close, so a slot first allocated mid-compute (already
|
|
92
|
+
* holding its seeded head) is not present here and is not double-advanced.
|
|
93
|
+
*
|
|
94
|
+
* @since 0.9
|
|
95
|
+
* @stable
|
|
96
|
+
* @example
|
|
97
|
+
* // advanceSeriesSlots(ctx);
|
|
98
|
+
* const advanced = true;
|
|
99
|
+
* void advanced;
|
|
100
|
+
*/
|
|
101
|
+
export function advanceSeriesSlots(ctx) {
|
|
102
|
+
for (const slot of ctx.seriesSlots.values()) {
|
|
103
|
+
advanceSeriesSlot(slot);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Commit every `state.series` live head as its bar-close value after
|
|
108
|
+
* close compute, so the next advance retains it and a tick can reset to
|
|
109
|
+
* it.
|
|
110
|
+
*
|
|
111
|
+
* @since 0.9
|
|
112
|
+
* @stable
|
|
113
|
+
* @example
|
|
114
|
+
* // commitSeriesSlots(ctx);
|
|
115
|
+
* const committed = true;
|
|
116
|
+
* void committed;
|
|
117
|
+
*/
|
|
118
|
+
export function commitSeriesSlots(ctx) {
|
|
119
|
+
for (const slot of ctx.seriesSlots.values()) {
|
|
120
|
+
commitSeriesSlot(slot);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Reset every `state.series` live head to its last committed value before
|
|
125
|
+
* tick compute, so a re-write refines from the committed baseline and a
|
|
126
|
+
* tick without a write reads the committed head. Does NOT advance length.
|
|
127
|
+
*
|
|
128
|
+
* @since 0.9
|
|
129
|
+
* @stable
|
|
130
|
+
* @example
|
|
131
|
+
* // resetSeriesHeads(ctx);
|
|
132
|
+
* const reset = true;
|
|
133
|
+
* void reset;
|
|
134
|
+
*/
|
|
135
|
+
export function resetSeriesHeads(ctx) {
|
|
136
|
+
for (const slot of ctx.seriesSlots.values()) {
|
|
137
|
+
resetSeriesSlotHead(slot);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
87
140
|
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/state/lifecycle.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/state/lifecycle.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAG/D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAqB3F;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAmB;IACxD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,SAAS,EAAE,CAAC;IACrB,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAmB;IAChD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;IACtB,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,GAAmB;IAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,GAAG,CAAC,UAAU,CAAC,GAAG,CAA6B,GAAG,EAAE;YAChD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC5B,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAmB;IACnD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,GAAG,CAAC,GAAG,CAAC,GAAG;YACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;YACzC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;SAC5C,CAAC;IACN,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC7B,GAAmB,EACnB,KAAwC;IAExC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IAClD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACjD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAmB;IAChD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;AACL,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport { advanceSeriesSlot, commitSeriesSlot, resetSeriesSlotHead } from \"./seriesSlot.js\";\n\n/**\n * Persisted representation for a runtime state slot. Keys use\n * `${slotId}:state`, matching the compiler-injected slot id plus the\n * state namespace suffix.\n *\n * @since 0.4\n * @stable\n * @example\n * const snapshot: StateSlotSnapshot<number> = {\n * committed: 1,\n * tentative: 2,\n * };\n * void snapshot;\n */\nexport type StateSlotSnapshot<T> = {\n readonly committed: T;\n readonly tentative: T;\n};\n\n/**\n * Reset all non-`state.tick.*` tentative values before tick compute.\n *\n * @since 0.4\n * @stable\n * @example\n * // resetTentativeStateSlots(ctx);\n * const called = true;\n * void called;\n */\nexport function resetTentativeStateSlots(ctx: RuntimeContext): void {\n for (const slot of ctx.stateSlots.values()) {\n slot.onBarTick();\n }\n}\n\n/**\n * Commit all non-`state.tick.*` tentative values after close compute.\n *\n * @since 0.4\n * @stable\n * @example\n * // commitStateSlots(ctx);\n * const called = true;\n * void called;\n */\nexport function commitStateSlots(ctx: RuntimeContext): void {\n for (const slot of ctx.stateSlots.values()) {\n slot.onBarClose();\n }\n}\n\n/**\n * Flush runtime state slots into the backing {@link StateStore}.\n *\n * @since 0.4\n * @stable\n * @example\n * // flushStateSlots(ctx);\n * const called = true;\n * void called;\n */\nexport function flushStateSlots(ctx: RuntimeContext): void {\n for (const [key, slot] of ctx.stateSlots.entries()) {\n ctx.stateStore.set<StateSlotSnapshot<unknown>>(key, {\n committed: slot.committed,\n tentative: slot.tentative,\n });\n }\n}\n\n/**\n * Serialise runtime state slots into a snapshot payload.\n *\n * @since 0.5\n * @stable\n * @example\n * // const slots = serialiseStateSlots(ctx);\n * const slots = {};\n * void slots;\n */\nexport function serialiseStateSlots(ctx: RuntimeContext): Readonly<Record<string, unknown>> {\n const out: Record<string, unknown> = {};\n for (const [key, slot] of ctx.stateSlots.entries()) {\n out[key] = {\n committed: slot.serialise(slot.committed),\n tentative: slot.serialise(slot.tentative),\n };\n }\n return Object.freeze(out);\n}\n\n/**\n * Seed restored state-slot payloads into the backing slot store.\n *\n * @since 0.5\n * @stable\n * @example\n * // restoreStateSlots(ctx, snapshot.slots);\n * const restored = true;\n * void restored;\n */\nexport function restoreStateSlots(\n ctx: RuntimeContext,\n slots: Readonly<Record<string, unknown>>,\n): void {\n ctx.stateSlots.clear();\n for (const [key, value] of Object.entries(slots)) {\n ctx.stateStore.set(key, value);\n }\n}\n\n/**\n * Advance every `state.series` ring once for a new close bar — append a\n * fresh `NaN` head so the prior committed head slides to index 1. Runs\n * BEFORE compute on close, so a slot first allocated mid-compute (already\n * holding its seeded head) is not present here and is not double-advanced.\n *\n * @since 0.9\n * @stable\n * @example\n * // advanceSeriesSlots(ctx);\n * const advanced = true;\n * void advanced;\n */\nexport function advanceSeriesSlots(ctx: RuntimeContext): void {\n for (const slot of ctx.seriesSlots.values()) {\n advanceSeriesSlot(slot);\n }\n}\n\n/**\n * Commit every `state.series` live head as its bar-close value after\n * close compute, so the next advance retains it and a tick can reset to\n * it.\n *\n * @since 0.9\n * @stable\n * @example\n * // commitSeriesSlots(ctx);\n * const committed = true;\n * void committed;\n */\nexport function commitSeriesSlots(ctx: RuntimeContext): void {\n for (const slot of ctx.seriesSlots.values()) {\n commitSeriesSlot(slot);\n }\n}\n\n/**\n * Reset every `state.series` live head to its last committed value before\n * tick compute, so a re-write refines from the committed baseline and a\n * tick without a write reads the committed head. Does NOT advance length.\n *\n * @since 0.9\n * @stable\n * @example\n * // resetSeriesHeads(ctx);\n * const reset = true;\n * void reset;\n */\nexport function resetSeriesHeads(ctx: RuntimeContext): void {\n for (const slot of ctx.seriesSlots.values()) {\n resetSeriesSlotHead(slot);\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { JsonValue } from "@invinite-org/chartlang-core";
|
|
2
|
+
import type { RuntimeContext } from "../runtimeContext.js";
|
|
3
|
+
/**
|
|
4
|
+
* Return whether a snapshot slot key belongs to the `state.series`
|
|
5
|
+
* namespace (a `${slotIdPrefix}${slotId}:series` key). Lets the restore
|
|
6
|
+
* router separate series slots from scalar `state.*` (`:state`) and `ta.*`
|
|
7
|
+
* (`ta:`) slots, all of which share one `slots` record.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.9
|
|
10
|
+
* @internal
|
|
11
|
+
* @stable
|
|
12
|
+
* @example
|
|
13
|
+
* isSeriesSlotSnapshotKey("x.chart.ts:1:1:series"); // true
|
|
14
|
+
*/
|
|
15
|
+
export declare function isSeriesSlotSnapshotKey(key: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Serialise the runner's `state.series` slots into JSON-clean snapshot
|
|
18
|
+
* entries keyed by the same `${prefix}${slotId}:series` key the slot store
|
|
19
|
+
* uses. `committedHead` is nulled when `NaN` (the validator rejects `NaN`);
|
|
20
|
+
* the buffer rides {@link Float64RingBuffer.serialiseSnapshotBuffer}.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.9
|
|
23
|
+
* @internal
|
|
24
|
+
* @stable
|
|
25
|
+
* @example
|
|
26
|
+
* // const entries = serialiseSeriesSlots(ctx);
|
|
27
|
+
* const entries = {};
|
|
28
|
+
* void entries;
|
|
29
|
+
*/
|
|
30
|
+
export declare function serialiseSeriesSlots(ctx: RuntimeContext): Readonly<Record<string, JsonValue>>;
|
|
31
|
+
/**
|
|
32
|
+
* Restore `state.series` slots from namespaced snapshot entries into
|
|
33
|
+
* `ctx.seriesSlots`, rebuilding each ring via
|
|
34
|
+
* {@link Float64RingBuffer.restoreFromSnapshotBuffer} sized to the runner's
|
|
35
|
+
* current `capacity`. Non-series keys are ignored; malformed series
|
|
36
|
+
* snapshots are skipped. The view identity is recreated on restore
|
|
37
|
+
* (acceptable — same as `ta.*`).
|
|
38
|
+
*
|
|
39
|
+
* @since 0.9
|
|
40
|
+
* @internal
|
|
41
|
+
* @stable
|
|
42
|
+
* @example
|
|
43
|
+
* // restoreSeriesSlots(ctx, snapshot.slots, capacity);
|
|
44
|
+
* const restored = true;
|
|
45
|
+
* void restored;
|
|
46
|
+
*/
|
|
47
|
+
export declare function restoreSeriesSlots(ctx: RuntimeContext, slots: Readonly<Record<string, unknown>>, capacity: number): void;
|
|
48
|
+
//# sourceMappingURL=seriesPersistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seriesPersistence.d.ts","sourceRoot":"","sources":["../../src/state/seriesPersistence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAU9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAU7F;AAaD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,QAAQ,EAAE,MAAM,GACjB,IAAI,CASN"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
|
+
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
import { finiteOrNull, isBufferSnapshot, isRecord, restoreBuffer, restoreNumber, serialiseBuffer, } from "../bufferSnapshot.js";
|
|
4
|
+
import { restoreSeriesSlot } from "./seriesSlot.js";
|
|
5
|
+
const SERIES_SLOT_SUFFIX = ":series";
|
|
6
|
+
/**
|
|
7
|
+
* Return whether a snapshot slot key belongs to the `state.series`
|
|
8
|
+
* namespace (a `${slotIdPrefix}${slotId}:series` key). Lets the restore
|
|
9
|
+
* router separate series slots from scalar `state.*` (`:state`) and `ta.*`
|
|
10
|
+
* (`ta:`) slots, all of which share one `slots` record.
|
|
11
|
+
*
|
|
12
|
+
* @since 0.9
|
|
13
|
+
* @internal
|
|
14
|
+
* @stable
|
|
15
|
+
* @example
|
|
16
|
+
* isSeriesSlotSnapshotKey("x.chart.ts:1:1:series"); // true
|
|
17
|
+
*/
|
|
18
|
+
export function isSeriesSlotSnapshotKey(key) {
|
|
19
|
+
return key.endsWith(SERIES_SLOT_SUFFIX);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Serialise the runner's `state.series` slots into JSON-clean snapshot
|
|
23
|
+
* entries keyed by the same `${prefix}${slotId}:series` key the slot store
|
|
24
|
+
* uses. `committedHead` is nulled when `NaN` (the validator rejects `NaN`);
|
|
25
|
+
* the buffer rides {@link Float64RingBuffer.serialiseSnapshotBuffer}.
|
|
26
|
+
*
|
|
27
|
+
* @since 0.9
|
|
28
|
+
* @internal
|
|
29
|
+
* @stable
|
|
30
|
+
* @example
|
|
31
|
+
* // const entries = serialiseSeriesSlots(ctx);
|
|
32
|
+
* const entries = {};
|
|
33
|
+
* void entries;
|
|
34
|
+
*/
|
|
35
|
+
export function serialiseSeriesSlots(ctx) {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const [key, slot] of ctx.seriesSlots.entries()) {
|
|
38
|
+
out[key] = {
|
|
39
|
+
kind: "state.series",
|
|
40
|
+
buffer: serialiseBuffer(slot.buffer),
|
|
41
|
+
committedHead: finiteOrNull(slot.committedHead),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return Object.freeze(out);
|
|
45
|
+
}
|
|
46
|
+
function restoreSeriesSlotSnapshot(snapshot, capacity) {
|
|
47
|
+
if (!isRecord(snapshot) || snapshot.kind !== "state.series")
|
|
48
|
+
return null;
|
|
49
|
+
const bufferSnapshot = snapshot.buffer;
|
|
50
|
+
if (!isBufferSnapshot(bufferSnapshot))
|
|
51
|
+
return null;
|
|
52
|
+
const committedHead = restoreNumber(snapshot.committedHead);
|
|
53
|
+
if (committedHead === null)
|
|
54
|
+
return null;
|
|
55
|
+
const buffer = restoreBuffer(bufferSnapshot, capacity);
|
|
56
|
+
if (buffer === null)
|
|
57
|
+
return null;
|
|
58
|
+
return restoreSeriesSlot(buffer, committedHead);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Restore `state.series` slots from namespaced snapshot entries into
|
|
62
|
+
* `ctx.seriesSlots`, rebuilding each ring via
|
|
63
|
+
* {@link Float64RingBuffer.restoreFromSnapshotBuffer} sized to the runner's
|
|
64
|
+
* current `capacity`. Non-series keys are ignored; malformed series
|
|
65
|
+
* snapshots are skipped. The view identity is recreated on restore
|
|
66
|
+
* (acceptable — same as `ta.*`).
|
|
67
|
+
*
|
|
68
|
+
* @since 0.9
|
|
69
|
+
* @internal
|
|
70
|
+
* @stable
|
|
71
|
+
* @example
|
|
72
|
+
* // restoreSeriesSlots(ctx, snapshot.slots, capacity);
|
|
73
|
+
* const restored = true;
|
|
74
|
+
* void restored;
|
|
75
|
+
*/
|
|
76
|
+
export function restoreSeriesSlots(ctx, slots, capacity) {
|
|
77
|
+
ctx.seriesSlots.clear();
|
|
78
|
+
for (const [key, value] of Object.entries(slots)) {
|
|
79
|
+
if (!isSeriesSlotSnapshotKey(key))
|
|
80
|
+
continue;
|
|
81
|
+
const slot = restoreSeriesSlotSnapshot(value, capacity);
|
|
82
|
+
if (slot !== null) {
|
|
83
|
+
ctx.seriesSlots.set(key, slot);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=seriesPersistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seriesPersistence.js","sourceRoot":"","sources":["../../src/state/seriesPersistence.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAI/D,OAAO,EACH,YAAY,EACZ,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAmB,MAAM,iBAAiB,CAAC;AAErE,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IAC/C,OAAO,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAmB;IACpD,MAAM,GAAG,GAA8B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,GAAG;YACP,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;YACpC,aAAa,EAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC;SAClD,CAAC;IACN,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,yBAAyB,CAAC,QAAiB,EAAE,QAAgB;IAClE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO,IAAI,CAAC;IACzE,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;IACvC,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC5D,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,MAAM,GAAG,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,kBAAkB,CAC9B,GAAmB,EACnB,KAAwC,EACxC,QAAgB;IAEhB,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,IAAI,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACxD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAChB,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;IACL,CAAC;AACL,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { JsonValue } from \"@invinite-org/chartlang-core\";\n\nimport {\n finiteOrNull,\n isBufferSnapshot,\n isRecord,\n restoreBuffer,\n restoreNumber,\n serialiseBuffer,\n} from \"../bufferSnapshot.js\";\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport { restoreSeriesSlot, type SeriesSlot } from \"./seriesSlot.js\";\n\nconst SERIES_SLOT_SUFFIX = \":series\";\n\n/**\n * Return whether a snapshot slot key belongs to the `state.series`\n * namespace (a `${slotIdPrefix}${slotId}:series` key). Lets the restore\n * router separate series slots from scalar `state.*` (`:state`) and `ta.*`\n * (`ta:`) slots, all of which share one `slots` record.\n *\n * @since 0.9\n * @internal\n * @stable\n * @example\n * isSeriesSlotSnapshotKey(\"x.chart.ts:1:1:series\"); // true\n */\nexport function isSeriesSlotSnapshotKey(key: string): boolean {\n return key.endsWith(SERIES_SLOT_SUFFIX);\n}\n\n/**\n * Serialise the runner's `state.series` slots into JSON-clean snapshot\n * entries keyed by the same `${prefix}${slotId}:series` key the slot store\n * uses. `committedHead` is nulled when `NaN` (the validator rejects `NaN`);\n * the buffer rides {@link Float64RingBuffer.serialiseSnapshotBuffer}.\n *\n * @since 0.9\n * @internal\n * @stable\n * @example\n * // const entries = serialiseSeriesSlots(ctx);\n * const entries = {};\n * void entries;\n */\nexport function serialiseSeriesSlots(ctx: RuntimeContext): Readonly<Record<string, JsonValue>> {\n const out: Record<string, JsonValue> = {};\n for (const [key, slot] of ctx.seriesSlots.entries()) {\n out[key] = {\n kind: \"state.series\",\n buffer: serialiseBuffer(slot.buffer),\n committedHead: finiteOrNull(slot.committedHead),\n };\n }\n return Object.freeze(out);\n}\n\nfunction restoreSeriesSlotSnapshot(snapshot: unknown, capacity: number): SeriesSlot | null {\n if (!isRecord(snapshot) || snapshot.kind !== \"state.series\") return null;\n const bufferSnapshot = snapshot.buffer;\n if (!isBufferSnapshot(bufferSnapshot)) return null;\n const committedHead = restoreNumber(snapshot.committedHead);\n if (committedHead === null) return null;\n const buffer = restoreBuffer(bufferSnapshot, capacity);\n if (buffer === null) return null;\n return restoreSeriesSlot(buffer, committedHead);\n}\n\n/**\n * Restore `state.series` slots from namespaced snapshot entries into\n * `ctx.seriesSlots`, rebuilding each ring via\n * {@link Float64RingBuffer.restoreFromSnapshotBuffer} sized to the runner's\n * current `capacity`. Non-series keys are ignored; malformed series\n * snapshots are skipped. The view identity is recreated on restore\n * (acceptable — same as `ta.*`).\n *\n * @since 0.9\n * @internal\n * @stable\n * @example\n * // restoreSeriesSlots(ctx, snapshot.slots, capacity);\n * const restored = true;\n * void restored;\n */\nexport function restoreSeriesSlots(\n ctx: RuntimeContext,\n slots: Readonly<Record<string, unknown>>,\n capacity: number,\n): void {\n ctx.seriesSlots.clear();\n for (const [key, value] of Object.entries(slots)) {\n if (!isSeriesSlotSnapshotKey(key)) continue;\n const slot = restoreSeriesSlotSnapshot(value, capacity);\n if (slot !== null) {\n ctx.seriesSlots.set(key, slot);\n }\n }\n}\n"]}
|