sia-reactor 0.0.25 → 0.0.26
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 +21 -14
- package/dist/{TimeTravelOverlay-Bz2v9hov.d.cts → TimeTravelOverlay-_6k5wu1I.d.cts} +2 -2
- package/dist/{TimeTravelOverlay-CvTDJWpP.d.ts → TimeTravelOverlay-fun5VLIo.d.ts} +2 -2
- package/dist/adapters/react.d.cts +3 -3
- package/dist/adapters/react.d.ts +3 -3
- package/dist/adapters/vanilla.d.cts +4 -4
- package/dist/adapters/vanilla.d.ts +4 -4
- package/dist/{index-CB-IiZIB.d.cts → index-2jKy98op.d.cts} +9 -1
- package/dist/{index-CB-IiZIB.d.ts → index-2jKy98op.d.ts} +9 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/modules.cjs +31 -18
- package/dist/modules.d.cts +14 -10
- package/dist/modules.d.ts +14 -10
- package/dist/modules.js +31 -18
- package/dist/super.d.ts +26 -9
- package/dist/super.global.js +31 -18
- package/dist/{timeTravel-CEc3grUE.d.cts → timeTravel-CsbQ8qhP.d.ts} +8 -4
- package/dist/{timeTravel-D7NiYqdD.d.ts → timeTravel-DzgX8BKQ.d.cts} +8 -4
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://www.npmjs.com/package/sia-reactor)
|
|
7
7
|
[](https://bundlephobia.com/package/sia-reactor)
|
|
8
|
+
[](https://github.com/Tobi007-del/sia-reactor)
|
|
8
9
|
|
|
9
|
-
[Live Demo & Benchmarks](https://tobi007-del.github.io/
|
|
10
|
+
[Live Demo & Benchmarks](https://tobi007-del.github.io/sia-reactor/src/index.html) | [Report Bug](https://github.com/Tobi007-del/sia-reactor/issues)
|
|
10
11
|
|
|
11
12
|
[Chronicles](https://github.com/Tobi007-del/tmg-media-player/blob/main/CHRONICLES.md) | [Interaction Folklore](https://github.com/Tobi007-del/tmg-media-player/blob/main/FOLKLORE.md)
|
|
12
13
|
|
|
@@ -195,7 +196,7 @@ const data = reactive({
|
|
|
195
196
|
|
|
196
197
|
### React Hooks & Effects
|
|
197
198
|
|
|
198
|
-
The engine provides native React bindings utilizing `useSyncExternalStore` and an internal `Autotracker` for concurrent-safe, surgically precise component re-renders. All hooks natively accept a `Reactor` instance, a `reactive()` proxy, or a plain object (which will be auto-wrapped on the fly). Just import, your editor will reveal more details.
|
|
199
|
+
The engine provides native React bindings utilizing `useSyncExternalStore` and an internal `Autotracker` for concurrent-safe, surgically precise component re-renders. All hooks natively accept a `Reactor` instance, a `reactive()` proxy, or a plain object (which will be auto-wrapped on the fly). Just import, your editor will reveal more details all round.
|
|
199
200
|
|
|
200
201
|
```javascript
|
|
201
202
|
import { reactive } from "sia-reactor";
|
|
@@ -230,7 +231,7 @@ const stopTracking = effect(() => console.log("User name changed to:", state.use
|
|
|
230
231
|
|
|
231
232
|
### Modules: The Extension Port
|
|
232
233
|
|
|
233
|
-
The `Reactor` is designed to be a lightweight core. Extended capabilities are attached via Modules.
|
|
234
|
+
The `Reactor` is designed to be a lightweight core. Extended capabilities are attached via Modules. Use `.attach(target: Reactor | Reactive<T>, id)` to chain reactors then `.setup(target, id)` which the `Reactor.use()` also calls to init, the `id` param will be direct keys on the final object, pass dotted paths to manipulate the shape.
|
|
234
235
|
|
|
235
236
|
#### The Persistence Module
|
|
236
237
|
Automatically syncs your State to LocalStorage, SessionStorage, Memory or IndexedDB. Always use this module first to avoid re-initialization issues.
|
|
@@ -240,14 +241,20 @@ import { reactive, Reactor, getReactor } from "sia-reactor";
|
|
|
240
241
|
import { PersistModule, LocalStorageAdapter, IndexedDBAdapter, SessionStorageAdapter, CookieAdapter, MemoryAdapter } from "sia-reactor/modules";
|
|
241
242
|
|
|
242
243
|
const state = reactive({ theme: "dark", settings: { volume: 50, brightness: 30 } });
|
|
243
|
-
const persist = new PersistModule({
|
|
244
|
-
key: "
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
const persist = new PersistModule({
|
|
245
|
+
key: "APP_GLOBAL_STATE",
|
|
246
|
+
whitelist: ["theme", "settings.brightness"], // all paths if omitted, use object if multiple reactors
|
|
247
|
+
blacklist: ["settings.debug"], // optional excluded paths
|
|
248
|
+
throttle: 2500, // ms between saves
|
|
249
|
+
fanout: true, // async hydration use leaf writes to sync initialized listeners.
|
|
248
250
|
adapter: new IndexedDBAdapter({ dbName: "Session", version: 1, onversionchange: () => location.reload(), useSnapshot: true }) // or `LocalStorageAdapter` (instance or signature)
|
|
249
|
-
};
|
|
250
|
-
state.use(persist
|
|
251
|
+
}, getReactor(state)); // `Reactor` in second arg for path inference
|
|
252
|
+
state.use(persist); // calls `.setup()`, use after all attachments, `id` is the second param too.
|
|
253
|
+
|
|
254
|
+
// Seperate attach sample if multiple reactors desired
|
|
255
|
+
persist.attach(uiState, "ui").setup(appState, "app"); // or paths: "app.ui"
|
|
256
|
+
persist.config.whitelist = { ui: ["settings.theme"], app: ["settings.volume"] }; // Multi-reactor filtering by id key. If you didn't pass ids, use implicit index keys: { "0": [...], "1": [...] }
|
|
257
|
+
|
|
251
258
|
```
|
|
252
259
|
|
|
253
260
|
#### The Time Travel Module
|
|
@@ -258,7 +265,7 @@ import { TimeTravelModule } from "sia-reactor/modules";
|
|
|
258
265
|
import { effect, TimeTravelOverlay } from "sia-reactor/adapters/vanilla";
|
|
259
266
|
import "sia-reactor/css/time-travel-overlay.css";
|
|
260
267
|
|
|
261
|
-
const time = new TimeTravelModule({ maxHistory: 300, loop: false, rate: 150 });
|
|
268
|
+
const time = new TimeTravelModule({ maxHistory: 300, loop: false, rate: 150, whitelist: ["state.playing", "state.currentTime"] });
|
|
262
269
|
state.use(time);
|
|
263
270
|
|
|
264
271
|
// If persist uses an async adapter (e.g. IndexedDB), wait till after hydration:
|
|
@@ -531,7 +538,7 @@ S.I.A. Reactor synthesizes core concepts from the heavyweights of web and media
|
|
|
531
538
|
|
|
532
539
|
No fancy screenshots here. True engineers look at performance metrics.
|
|
533
540
|
|
|
534
|
-
To see the Reactor handle deep DAG mutations, DOM-style event routing, and microtask batching in real-time, visit the **[Live Demo](https://tobi007-del.github.io/
|
|
541
|
+
To see the Reactor handle deep DAG mutations, DOM-style event routing, and microtask batching in real-time, visit the **[Live Demo](https://tobi007-del.github.io/sia-reactor/src/index.html)**, open your DevTools console, and run the built-in Grand Master Stress Suite directly on your own CPU.
|
|
535
542
|
|
|
536
543
|
*NOTE: The reactor is progressively enhanced so it's performance depends on how you use it and the options you toggle, it's base form is incredibly light.*
|
|
537
544
|
|
|
@@ -540,7 +547,7 @@ To see the Reactor handle deep DAG mutations, DOM-style event routing, and micro
|
|
|
540
547
|
## Author
|
|
541
548
|
|
|
542
549
|
- Architect & Developer - [Oketade Oluwatobiloba (Tobi007-del)](https://github.com/Tobi007-del)
|
|
543
|
-
- Project - [t007-tools](https://github.com/Tobi007-del/
|
|
550
|
+
- Project - [t007-tools](https://github.com/Tobi007-del/sia-reactor)
|
|
544
551
|
|
|
545
552
|
## Acknowledgments
|
|
546
553
|
|
|
@@ -550,6 +557,6 @@ Designed to bring absolute architectural dominance and rendering efficiency to c
|
|
|
550
557
|
|
|
551
558
|
If you find this project useful, please consider giving it a star! ⭐
|
|
552
559
|
|
|
553
|
-
[](https://github.com/Tobi007-del/sia-reactor)
|
|
554
561
|
|
|
555
562
|
**[⬆ Back to Top](#sia-reactor)**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as Reactive } from './index-
|
|
2
|
-
import { m as TimeTravelModule } from './timeTravel-
|
|
1
|
+
import { d as Reactive } from './index-2jKy98op.cjs';
|
|
2
|
+
import { m as TimeTravelModule } from './timeTravel-DzgX8BKQ.cjs';
|
|
3
3
|
|
|
4
4
|
/** Reactive options for the TimeTravel overlay instance. */
|
|
5
5
|
interface TimeTravelOverlayConfig {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as Reactive } from './index-
|
|
2
|
-
import { m as TimeTravelModule } from './timeTravel-
|
|
1
|
+
import { d as Reactive } from './index-2jKy98op.js';
|
|
2
|
+
import { m as TimeTravelModule } from './timeTravel-CsbQ8qhP.js';
|
|
3
3
|
|
|
4
4
|
/** Reactive options for the TimeTravel overlay instance. */
|
|
5
5
|
interface TimeTravelOverlayConfig {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions, R as Reactor, d as Reactive, v as ReactorBuild, D as DeepReadonly, W as WildPaths, e as PathValue } from '../index-
|
|
1
|
+
import { E as EffectOptions, R as Reactor, d as Reactive, v as ReactorBuild, D as DeepReadonly, W as WildPaths, e as PathValue } from '../index-2jKy98op.cjs';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
|
-
import { m as TimeTravelModule } from '../timeTravel-
|
|
4
|
-
import { a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-
|
|
3
|
+
import { m as TimeTravelModule } from '../timeTravel-DzgX8BKQ.cjs';
|
|
4
|
+
import { a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-_6k5wu1I.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Subscribes a component to desired Reactor state and returns it.
|
package/dist/adapters/react.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions, R as Reactor, d as Reactive, v as ReactorBuild, D as DeepReadonly, W as WildPaths, e as PathValue } from '../index-
|
|
1
|
+
import { E as EffectOptions, R as Reactor, d as Reactive, v as ReactorBuild, D as DeepReadonly, W as WildPaths, e as PathValue } from '../index-2jKy98op.js';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
|
-
import { m as TimeTravelModule } from '../timeTravel-
|
|
4
|
-
import { a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-
|
|
3
|
+
import { m as TimeTravelModule } from '../timeTravel-CsbQ8qhP.js';
|
|
4
|
+
import { a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-fun5VLIo.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Subscribes a component to desired Reactor state and returns it.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions } from '../index-
|
|
2
|
-
export { A as Autotracker, w as withTracker } from '../index-
|
|
3
|
-
export { T as TimeTravelOverlay, a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-
|
|
4
|
-
import '../timeTravel-
|
|
1
|
+
import { E as EffectOptions } from '../index-2jKy98op.cjs';
|
|
2
|
+
export { A as Autotracker, w as withTracker } from '../index-2jKy98op.cjs';
|
|
3
|
+
export { T as TimeTravelOverlay, a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-_6k5wu1I.cjs';
|
|
4
|
+
import '../timeTravel-DzgX8BKQ.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Runs a reactive side effect in vanilla JavaScript.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions } from '../index-
|
|
2
|
-
export { A as Autotracker, w as withTracker } from '../index-
|
|
3
|
-
export { T as TimeTravelOverlay, a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-
|
|
4
|
-
import '../timeTravel-
|
|
1
|
+
import { E as EffectOptions } from '../index-2jKy98op.js';
|
|
2
|
+
export { A as Autotracker, w as withTracker } from '../index-2jKy98op.js';
|
|
3
|
+
export { T as TimeTravelOverlay, a as TimeTravelOverlayConfig } from '../TimeTravelOverlay-fun5VLIo.js';
|
|
4
|
+
import '../timeTravel-CsbQ8qhP.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Runs a reactive side effect in vanilla JavaScript.
|
|
@@ -816,6 +816,7 @@ declare function deepClone<T>(obj: T, config?: {
|
|
|
816
816
|
declare function nuke(target: any): void;
|
|
817
817
|
|
|
818
818
|
type ReactorModuleId = string | number;
|
|
819
|
+
type ModulePaths<P extends string = string> = P[] | Partial<Record<string, P[]>>;
|
|
819
820
|
interface ReactorModuleConstructor<P extends BaseReactorModule = BaseReactorModule, T extends object = any> {
|
|
820
821
|
new (rtr: Reactor<T>, config: any): P;
|
|
821
822
|
moduleName: string;
|
|
@@ -873,6 +874,13 @@ declare abstract class BaseReactorModule<T extends object = any, Config = any, S
|
|
|
873
874
|
* window.addEventListener("resize", this.guard(() => this.syncLayout(true)), { signal: this.signal });
|
|
874
875
|
*/
|
|
875
876
|
guard: <Fn extends Function>(fn: Fn) => Fn;
|
|
877
|
+
/**
|
|
878
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
879
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
880
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
881
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
882
|
+
*/
|
|
883
|
+
protected getPaths<P extends string = string>(paths?: ModulePaths<P>, target?: Reactor<any> | ReactorModuleId): P[];
|
|
876
884
|
}
|
|
877
885
|
|
|
878
886
|
/**
|
|
@@ -1195,4 +1203,4 @@ declare const NIL: any;
|
|
|
1195
1203
|
/** Shared no-operation function. */
|
|
1196
1204
|
declare const NOOP: () => void;
|
|
1197
1205
|
|
|
1198
|
-
export { type
|
|
1206
|
+
export { type ListenerRecord as $, Autotracker as A, BaseReactorModule as B, CTX as C, type DeepReadonly as D, type EffectOptions as E, type FanoutTuple as F, type DeepMerge as G, type DeepPartial as H, type Inert as I, type DeepRequired as J, type Deleter as K, type DeleterRecord as L, type ModulePaths as M, type DepthConfig as N, type DirectPayload as O, type Paths as P, EVT_OPTS as Q, Reactor as R, type Getter as S, type GetterRecord as T, INDIFFABLE as U, INERTIA as V, type WildPaths as W, type Intent as X, type Listener as Y, type ListenerOptions as Z, type ListenerOptionsTuple as _, type ReactorModuleId as a, type Live as a0, type MaxDepth as a1, NIL as a2, NOOP as a3, type NextDepth as a4, type NoTraverse as a5, type PathBranch as a6, type PathBranchValue as a7, type PathDepth as a8, type PathKey as a9, type Watcher as aA, type WatcherRecord as aB, getRaw as aC, getSnapshotVersion as aD, getVersion as aE, inert as aF, intent as aG, isInert as aH, isIntent as aI, isVolatile as aJ, live as aK, methods as aL, reactive as aM, stable as aN, state as aO, volatile as aP, type PathLeaf as aa, type Payload as ab, type PrevDepth as ac, type Primitive as ad, RAW as ae, REJECTABLE as af, RTR_BATCH as ag, RTR_LOG as ah, type ReactivePreferences as ai, ReactorEvent as aj, SSVERSION as ak, type Setter as al, type SetterRecord as am, type Stable as an, type State as ao, type StrictPathKey as ap, type SubtractDepth as aq, type SyncOptions as ar, type SyncOptionsTuple as as, TERMINATOR as at, type Target as au, type Unflatten as av, type UnionToIntersection as aw, type UpdatePayload as ax, VERSION as ay, type Volatile as az, type REvent as b, type ReactorModuleConstructor as c, type Reactive as d, type PathValue as e, arrRegex as f, canHandle as g, deepClone as h, deleteAny as i, fanout as j, fanoutOptsArr as k, getAny as l, getTrailRecords as m, inAny as n, isObj as o, isPOJO as p, mergeObjs as q, nuke as r, parseAnyObj as s, parseEvtOpts as t, setAny as u, type ReactorBuild as v, withTracker as w, type AddDepth as x, type ChildPaths as y, type DeepKeys as z };
|
|
@@ -816,6 +816,7 @@ declare function deepClone<T>(obj: T, config?: {
|
|
|
816
816
|
declare function nuke(target: any): void;
|
|
817
817
|
|
|
818
818
|
type ReactorModuleId = string | number;
|
|
819
|
+
type ModulePaths<P extends string = string> = P[] | Partial<Record<string, P[]>>;
|
|
819
820
|
interface ReactorModuleConstructor<P extends BaseReactorModule = BaseReactorModule, T extends object = any> {
|
|
820
821
|
new (rtr: Reactor<T>, config: any): P;
|
|
821
822
|
moduleName: string;
|
|
@@ -873,6 +874,13 @@ declare abstract class BaseReactorModule<T extends object = any, Config = any, S
|
|
|
873
874
|
* window.addEventListener("resize", this.guard(() => this.syncLayout(true)), { signal: this.signal });
|
|
874
875
|
*/
|
|
875
876
|
guard: <Fn extends Function>(fn: Fn) => Fn;
|
|
877
|
+
/**
|
|
878
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
879
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
880
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
881
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
882
|
+
*/
|
|
883
|
+
protected getPaths<P extends string = string>(paths?: ModulePaths<P>, target?: Reactor<any> | ReactorModuleId): P[];
|
|
876
884
|
}
|
|
877
885
|
|
|
878
886
|
/**
|
|
@@ -1195,4 +1203,4 @@ declare const NIL: any;
|
|
|
1195
1203
|
/** Shared no-operation function. */
|
|
1196
1204
|
declare const NOOP: () => void;
|
|
1197
1205
|
|
|
1198
|
-
export { type
|
|
1206
|
+
export { type ListenerRecord as $, Autotracker as A, BaseReactorModule as B, CTX as C, type DeepReadonly as D, type EffectOptions as E, type FanoutTuple as F, type DeepMerge as G, type DeepPartial as H, type Inert as I, type DeepRequired as J, type Deleter as K, type DeleterRecord as L, type ModulePaths as M, type DepthConfig as N, type DirectPayload as O, type Paths as P, EVT_OPTS as Q, Reactor as R, type Getter as S, type GetterRecord as T, INDIFFABLE as U, INERTIA as V, type WildPaths as W, type Intent as X, type Listener as Y, type ListenerOptions as Z, type ListenerOptionsTuple as _, type ReactorModuleId as a, type Live as a0, type MaxDepth as a1, NIL as a2, NOOP as a3, type NextDepth as a4, type NoTraverse as a5, type PathBranch as a6, type PathBranchValue as a7, type PathDepth as a8, type PathKey as a9, type Watcher as aA, type WatcherRecord as aB, getRaw as aC, getSnapshotVersion as aD, getVersion as aE, inert as aF, intent as aG, isInert as aH, isIntent as aI, isVolatile as aJ, live as aK, methods as aL, reactive as aM, stable as aN, state as aO, volatile as aP, type PathLeaf as aa, type Payload as ab, type PrevDepth as ac, type Primitive as ad, RAW as ae, REJECTABLE as af, RTR_BATCH as ag, RTR_LOG as ah, type ReactivePreferences as ai, ReactorEvent as aj, SSVERSION as ak, type Setter as al, type SetterRecord as am, type Stable as an, type State as ao, type StrictPathKey as ap, type SubtractDepth as aq, type SyncOptions as ar, type SyncOptionsTuple as as, TERMINATOR as at, type Target as au, type Unflatten as av, type UnionToIntersection as aw, type UpdatePayload as ax, VERSION as ay, type Volatile as az, type REvent as b, type ReactorModuleConstructor as c, type Reactive as d, type PathValue as e, arrRegex as f, canHandle as g, deepClone as h, deleteAny as i, fanout as j, fanoutOptsArr as k, getAny as l, getTrailRecords as m, inAny as n, isObj as o, isPOJO as p, mergeObjs as q, nuke as r, parseAnyObj as s, parseEvtOpts as t, setAny as u, type ReactorBuild as v, withTracker as w, type AddDepth as x, type ChildPaths as y, type DeepKeys as z };
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { x as AddDepth, C as CTX, y as ChildPaths, z as DeepKeys, G as DeepMerge, H as DeepPartial, D as DeepReadonly, J as DeepRequired, K as Deleter, L as DeleterRecord,
|
|
1
|
+
export { x as AddDepth, C as CTX, y as ChildPaths, z as DeepKeys, G as DeepMerge, H as DeepPartial, D as DeepReadonly, J as DeepRequired, K as Deleter, L as DeleterRecord, N as DepthConfig, O as DirectPayload, Q as EVT_OPTS, E as EffectOptions, S as Getter, T as GetterRecord, U as INDIFFABLE, V as INERTIA, I as Inert, X as Intent, Y as Listener, Z as ListenerOptions, _ as ListenerOptionsTuple, $ as ListenerRecord, a0 as Live, a1 as MaxDepth, a2 as NIL, a3 as NOOP, a4 as NextDepth, a5 as NoTraverse, a6 as PathBranch, a7 as PathBranchValue, a8 as PathDepth, a9 as PathKey, aa as PathLeaf, e as PathValue, P as Paths, ab as Payload, ac as PrevDepth, ad as Primitive, ae as RAW, af as REJECTABLE, b as REvent, ag as RTR_BATCH, ah as RTR_LOG, d as Reactive, ai as ReactivePreferences, R as Reactor, v as ReactorBuild, aj as ReactorEvent, ak as SSVERSION, al as Setter, am as SetterRecord, an as Stable, ao as State, ap as StrictPathKey, aq as SubtractDepth, ar as SyncOptions, as as SyncOptionsTuple, at as TERMINATOR, au as Target, av as Unflatten, aw as UnionToIntersection, ax as UpdatePayload, ay as VERSION, az as Volatile, aA as Watcher, aB as WatcherRecord, W as WildPaths, aC as getRaw, aD as getSnapshotVersion, aE as getVersion, aF as inert, aG as intent, aH as isInert, aI as isIntent, aJ as isVolatile, aK as live, aL as methods, aM as reactive, aN as stable, aO as state, aP as volatile } from './index-2jKy98op.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { x as AddDepth, C as CTX, y as ChildPaths, z as DeepKeys, G as DeepMerge, H as DeepPartial, D as DeepReadonly, J as DeepRequired, K as Deleter, L as DeleterRecord,
|
|
1
|
+
export { x as AddDepth, C as CTX, y as ChildPaths, z as DeepKeys, G as DeepMerge, H as DeepPartial, D as DeepReadonly, J as DeepRequired, K as Deleter, L as DeleterRecord, N as DepthConfig, O as DirectPayload, Q as EVT_OPTS, E as EffectOptions, S as Getter, T as GetterRecord, U as INDIFFABLE, V as INERTIA, I as Inert, X as Intent, Y as Listener, Z as ListenerOptions, _ as ListenerOptionsTuple, $ as ListenerRecord, a0 as Live, a1 as MaxDepth, a2 as NIL, a3 as NOOP, a4 as NextDepth, a5 as NoTraverse, a6 as PathBranch, a7 as PathBranchValue, a8 as PathDepth, a9 as PathKey, aa as PathLeaf, e as PathValue, P as Paths, ab as Payload, ac as PrevDepth, ad as Primitive, ae as RAW, af as REJECTABLE, b as REvent, ag as RTR_BATCH, ah as RTR_LOG, d as Reactive, ai as ReactivePreferences, R as Reactor, v as ReactorBuild, aj as ReactorEvent, ak as SSVERSION, al as Setter, am as SetterRecord, an as Stable, ao as State, ap as StrictPathKey, aq as SubtractDepth, ar as SyncOptions, as as SyncOptionsTuple, at as TERMINATOR, au as Target, av as Unflatten, aw as UnionToIntersection, ax as UpdatePayload, ay as VERSION, az as Volatile, aA as Watcher, aB as WatcherRecord, W as WildPaths, aC as getRaw, aD as getSnapshotVersion, aE as getVersion, aF as inert, aG as intent, aH as isInert, aI as isIntent, aJ as isVolatile, aK as live, aL as methods, aM as reactive, aN as stable, aO as state, aP as volatile } from './index-2jKy98op.js';
|
package/dist/modules.cjs
CHANGED
|
@@ -1021,6 +1021,16 @@ var BaseReactorModule = class {
|
|
|
1021
1021
|
return guardMethod(fn, (e) => this.rtrs.values().next().value?.log(`[Reactor "${this.name}" Module] Error: ${e}`));
|
|
1022
1022
|
};
|
|
1023
1023
|
// `()=>{}`: needs to be bounded even before initialization
|
|
1024
|
+
/**
|
|
1025
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
1026
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
1027
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
1028
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
1029
|
+
*/
|
|
1030
|
+
getPaths(paths, target) {
|
|
1031
|
+
const rid = "object" === typeof target ? this.rids.get(target) : target;
|
|
1032
|
+
return (paths && (Array.isArray(paths) ? paths : paths[String(rid)])) ?? wpArr;
|
|
1033
|
+
}
|
|
1024
1034
|
};
|
|
1025
1035
|
|
|
1026
1036
|
// src/ts/utils/store.ts
|
|
@@ -1367,7 +1377,7 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
1367
1377
|
get payload() {
|
|
1368
1378
|
let res = this.rtrs.size > 1 ? {} : void 0;
|
|
1369
1379
|
for (const [rid, rtr] of this.rtrs) {
|
|
1370
|
-
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core,
|
|
1380
|
+
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core, paths = this.getPaths(this.config.whitelist, rid), val = this.config.whitelist ? paths.reduce((acc, p) => (setAny(acc, p, getAny(snap, p)), acc), {}) : snap;
|
|
1371
1381
|
this.rtrs.size > 1 ? setAny(res, rid, val) : res = val;
|
|
1372
1382
|
}
|
|
1373
1383
|
return res;
|
|
@@ -1380,10 +1390,10 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
1380
1390
|
"undefined" !== typeof document && document.addEventListener("visibilitychange", () => document.visibilityState === "hidden" && this.onDestroy(), { signal: this.signal });
|
|
1381
1391
|
this.config.on("adapter", this.handleAdapter, { signal: this.signal, immediate: true });
|
|
1382
1392
|
this.config.on("disabled", this.handleDisabled, { signal: this.signal, immediate: true });
|
|
1383
|
-
this.config.on("
|
|
1393
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
1384
1394
|
}
|
|
1385
|
-
onAttach(rtr) {
|
|
1386
|
-
for (const p of this.config.
|
|
1395
|
+
onAttach(rtr, rid) {
|
|
1396
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) !this.config.disabled ? rtr.on(p, this.save, { signal: this.signal, immediate: true }) : rtr.off(p, this.save);
|
|
1387
1397
|
}
|
|
1388
1398
|
async handleAdapter({ value = LocalStorageAdapter }) {
|
|
1389
1399
|
const seq = ++this.hydrateSeq;
|
|
@@ -1397,27 +1407,29 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
1397
1407
|
saved = !isAsync ? saved : await saved;
|
|
1398
1408
|
if (seq !== this.hydrateSeq || !saved) return;
|
|
1399
1409
|
for (const [rid, rtr] of this.rtrs) {
|
|
1410
|
+
const paths = this.getPaths(this.config.whitelist, rid);
|
|
1400
1411
|
const entry = this.rtrs.size > 1 ? getAny(saved, rid) : saved;
|
|
1401
1412
|
if (!entry) continue;
|
|
1402
1413
|
const set = (p, news, olds) => (depth ? fanout : setAny)(rtr.core, p, merge ? mergeObjs(news, olds) : olds, depth ? { depth, crossRealms: rtr.config.crossRealms } : void 0);
|
|
1403
|
-
for (const p of this.config.paths
|
|
1414
|
+
for (const p of this.config.whitelist ? paths : wpArr) set(p, getAny(rtr.core, p), getAny(entry, p));
|
|
1404
1415
|
}
|
|
1405
|
-
for (const rtr of this.rtrs
|
|
1416
|
+
for (const [rid, rtr] of this.rtrs) rtr.tick(depth ? "*" : this.config.whitelist ? this.getPaths(this.config.whitelist, rid) : "*");
|
|
1406
1417
|
} finally {
|
|
1407
1418
|
if (seq === this.hydrateSeq) this.state.hydrated = true;
|
|
1408
1419
|
}
|
|
1409
1420
|
}
|
|
1410
1421
|
handleDisabled({ value }) {
|
|
1411
|
-
for (const rtr of this.rtrs
|
|
1422
|
+
for (const [rid, rtr] of this.rtrs) this.onAttach(rtr, rid);
|
|
1412
1423
|
value && this.adapter?.remove(this.config.key);
|
|
1413
1424
|
}
|
|
1414
|
-
|
|
1415
|
-
for (const rtr of this.rtrs
|
|
1416
|
-
for (const p of prevs) rtr.off(p, this.
|
|
1417
|
-
for (const p of paths) rtr.off(p, this.
|
|
1425
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
1426
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
1427
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.save);
|
|
1428
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.save), !this.config.disabled && rtr.on(p, this.save, { signal: this.signal, immediate: true });
|
|
1418
1429
|
}
|
|
1419
1430
|
}
|
|
1420
|
-
|
|
1431
|
+
save(e) {
|
|
1432
|
+
if (this.config.blacklist && this.getPaths(this.config.blacklist, e.reactor).includes(e.path)) return;
|
|
1421
1433
|
if (!this.state.hydrated) return e.stopImmediatePropagation();
|
|
1422
1434
|
if (!this.saveTimeoutId) this.saveTimeoutId = setTimeout2(() => (this.adapter.set(this.config.key, this.payload), this.saveTimeoutId = 0), this.config.throttle, this.signal);
|
|
1423
1435
|
}
|
|
@@ -1453,22 +1465,23 @@ var TimeTravelModule = class extends BaseReactorModule {
|
|
|
1453
1465
|
wire() {
|
|
1454
1466
|
this.lastTimestamp = performance.now();
|
|
1455
1467
|
this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
|
|
1456
|
-
this.config.on("
|
|
1468
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
1457
1469
|
!this.state.paused && this.play();
|
|
1458
1470
|
}
|
|
1459
1471
|
onAttach(rtr, rid) {
|
|
1460
1472
|
rtr.config.referenceTracking = rtr.config.smartCloning = rtr.config.eventTimeStamps = true;
|
|
1461
1473
|
if (!this.state.history.length || !this.state.initialState[rid]) this.state.initialState[rid] = rtr.snapshot();
|
|
1462
|
-
for (const p of this.config.
|
|
1474
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) rtr.on(p, this.record, { signal: this.signal });
|
|
1463
1475
|
}
|
|
1464
|
-
|
|
1465
|
-
for (const rtr of this.rtrs
|
|
1466
|
-
for (const p of prevs) rtr.off(p, this.record);
|
|
1467
|
-
for (const p of paths) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
1476
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
1477
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
1478
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.record);
|
|
1479
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
1468
1480
|
}
|
|
1469
1481
|
}
|
|
1470
1482
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
1471
1483
|
record(e, rid = this.rids.get(e.reactor)) {
|
|
1484
|
+
if (this.getPaths(this.config.blacklist, rid).includes(e.path)) return;
|
|
1472
1485
|
if (!this.state.paused) return;
|
|
1473
1486
|
if (this.state.currentFrame < this.state.history.length) fanout(this.state, "history", this.state.history.slice(0, this.state.currentFrame), { atomic: true });
|
|
1474
1487
|
if (this.state.history.length >= this.config.maxHistoryLength) fanout(this.state, "history", this.state.history.slice(1), { atomic: true });
|
package/dist/modules.d.cts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { P as Paths, I as Inert, F as FanoutTuple, B as BaseReactorModule, R as Reactor, a as REvent } from './index-
|
|
2
|
-
export {
|
|
3
|
-
import { S as StorageAdapter, A as AsyncStorageAdapter, a as StorageAdapterConstructor, b as AsyncStorageAdapterConstructor } from './timeTravel-
|
|
4
|
-
export { B as BaseStorageAdapter, C as COOKIE_ADAPTER_BUILD, c as CookieAdapter, d as CookieAdapterConfig, e as CookieOptions, H as HistoryEntry, I as INDEXED_DB_ADAPTER_BUILD, f as IndexedDBAdapter, g as IndexedDBAdapterConfig, J as JSONReplacer, h as JSONReviver, L as LocalStorageAdapter, M as MemoryAdapter, i as MemoryAdapterConfig, j as SessionStorageAdapter, k as StorageAdapterConfig, T as TIME_TRAVEL_MODULE_BUILD, l as TimeTravelConfig, m as TimeTravelModule, n as TimeTravelState } from './timeTravel-
|
|
1
|
+
import { P as Paths, M as ModulePaths, I as Inert, F as FanoutTuple, B as BaseReactorModule, R as Reactor, a as ReactorModuleId, b as REvent } from './index-2jKy98op.cjs';
|
|
2
|
+
export { c as ReactorModuleConstructor } from './index-2jKy98op.cjs';
|
|
3
|
+
import { S as StorageAdapter, A as AsyncStorageAdapter, a as StorageAdapterConstructor, b as AsyncStorageAdapterConstructor } from './timeTravel-DzgX8BKQ.cjs';
|
|
4
|
+
export { B as BaseStorageAdapter, C as COOKIE_ADAPTER_BUILD, c as CookieAdapter, d as CookieAdapterConfig, e as CookieOptions, H as HistoryEntry, I as INDEXED_DB_ADAPTER_BUILD, f as IndexedDBAdapter, g as IndexedDBAdapterConfig, J as JSONReplacer, h as JSONReviver, L as LocalStorageAdapter, M as MemoryAdapter, i as MemoryAdapterConfig, j as SessionStorageAdapter, k as StorageAdapterConfig, T as TIME_TRAVEL_MODULE_BUILD, l as TimeTravelConfig, m as TimeTravelModule, n as TimeTravelState } from './timeTravel-DzgX8BKQ.cjs';
|
|
5
5
|
|
|
6
6
|
interface PersistConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
7
7
|
/** Whether the persistence is disabled and cleared */
|
|
8
8
|
disabled: boolean;
|
|
9
9
|
/** The key under which to store the persisted data */
|
|
10
10
|
key: string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
12
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
13
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
14
|
+
whitelist: ModulePaths<P>;
|
|
15
|
+
/** Exclude filter for save-trigger paths. Checked only during save events. */
|
|
16
|
+
blacklist?: ModulePaths<P>;
|
|
13
17
|
/** Storage adapter class or instance to use, can satisfy `instanceof` or just definition, cast to `any` if the latter */
|
|
14
18
|
adapter: Inert<StorageAdapter> | Inert<AsyncStorageAdapter> | Inert<StorageAdapterConstructor> | Inert<AsyncStorageAdapterConstructor>;
|
|
15
19
|
/** Throttle time for saving changes */
|
|
@@ -38,15 +42,15 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
38
42
|
get payload(): Record<string, any> | undefined;
|
|
39
43
|
constructor(config?: Partial<PersistConfig<T, P>>, rtr?: Reactor<T>);
|
|
40
44
|
wire(): void;
|
|
41
|
-
protected onAttach(rtr: Reactor<any
|
|
45
|
+
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
42
46
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
43
47
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
44
|
-
protected
|
|
45
|
-
protected
|
|
48
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<PersistConfig<T, P>, "whitelist">): void;
|
|
49
|
+
protected save(e: REvent<any, P>): void;
|
|
46
50
|
/** Clears persisted payload for this module instance and drops any pending save. */
|
|
47
51
|
clear(): void;
|
|
48
52
|
protected onDestroy(): void;
|
|
49
53
|
}
|
|
50
54
|
declare const PERSIST_MODULE_BUILD: Partial<PersistConfig<any>>;
|
|
51
55
|
|
|
52
|
-
export { AsyncStorageAdapter, AsyncStorageAdapterConstructor, BaseReactorModule, PERSIST_MODULE_BUILD, type PersistConfig, PersistModule, StorageAdapter, StorageAdapterConstructor };
|
|
56
|
+
export { AsyncStorageAdapter, AsyncStorageAdapterConstructor, BaseReactorModule, ModulePaths, PERSIST_MODULE_BUILD, type PersistConfig, PersistModule, ReactorModuleId, StorageAdapter, StorageAdapterConstructor };
|
package/dist/modules.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { P as Paths, I as Inert, F as FanoutTuple, B as BaseReactorModule, R as Reactor, a as REvent } from './index-
|
|
2
|
-
export {
|
|
3
|
-
import { S as StorageAdapter, A as AsyncStorageAdapter, a as StorageAdapterConstructor, b as AsyncStorageAdapterConstructor } from './timeTravel-
|
|
4
|
-
export { B as BaseStorageAdapter, C as COOKIE_ADAPTER_BUILD, c as CookieAdapter, d as CookieAdapterConfig, e as CookieOptions, H as HistoryEntry, I as INDEXED_DB_ADAPTER_BUILD, f as IndexedDBAdapter, g as IndexedDBAdapterConfig, J as JSONReplacer, h as JSONReviver, L as LocalStorageAdapter, M as MemoryAdapter, i as MemoryAdapterConfig, j as SessionStorageAdapter, k as StorageAdapterConfig, T as TIME_TRAVEL_MODULE_BUILD, l as TimeTravelConfig, m as TimeTravelModule, n as TimeTravelState } from './timeTravel-
|
|
1
|
+
import { P as Paths, M as ModulePaths, I as Inert, F as FanoutTuple, B as BaseReactorModule, R as Reactor, a as ReactorModuleId, b as REvent } from './index-2jKy98op.js';
|
|
2
|
+
export { c as ReactorModuleConstructor } from './index-2jKy98op.js';
|
|
3
|
+
import { S as StorageAdapter, A as AsyncStorageAdapter, a as StorageAdapterConstructor, b as AsyncStorageAdapterConstructor } from './timeTravel-CsbQ8qhP.js';
|
|
4
|
+
export { B as BaseStorageAdapter, C as COOKIE_ADAPTER_BUILD, c as CookieAdapter, d as CookieAdapterConfig, e as CookieOptions, H as HistoryEntry, I as INDEXED_DB_ADAPTER_BUILD, f as IndexedDBAdapter, g as IndexedDBAdapterConfig, J as JSONReplacer, h as JSONReviver, L as LocalStorageAdapter, M as MemoryAdapter, i as MemoryAdapterConfig, j as SessionStorageAdapter, k as StorageAdapterConfig, T as TIME_TRAVEL_MODULE_BUILD, l as TimeTravelConfig, m as TimeTravelModule, n as TimeTravelState } from './timeTravel-CsbQ8qhP.js';
|
|
5
5
|
|
|
6
6
|
interface PersistConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
7
7
|
/** Whether the persistence is disabled and cleared */
|
|
8
8
|
disabled: boolean;
|
|
9
9
|
/** The key under which to store the persisted data */
|
|
10
10
|
key: string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
12
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
13
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
14
|
+
whitelist: ModulePaths<P>;
|
|
15
|
+
/** Exclude filter for save-trigger paths. Checked only during save events. */
|
|
16
|
+
blacklist?: ModulePaths<P>;
|
|
13
17
|
/** Storage adapter class or instance to use, can satisfy `instanceof` or just definition, cast to `any` if the latter */
|
|
14
18
|
adapter: Inert<StorageAdapter> | Inert<AsyncStorageAdapter> | Inert<StorageAdapterConstructor> | Inert<AsyncStorageAdapterConstructor>;
|
|
15
19
|
/** Throttle time for saving changes */
|
|
@@ -38,15 +42,15 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
38
42
|
get payload(): Record<string, any> | undefined;
|
|
39
43
|
constructor(config?: Partial<PersistConfig<T, P>>, rtr?: Reactor<T>);
|
|
40
44
|
wire(): void;
|
|
41
|
-
protected onAttach(rtr: Reactor<any
|
|
45
|
+
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
42
46
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
43
47
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
44
|
-
protected
|
|
45
|
-
protected
|
|
48
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<PersistConfig<T, P>, "whitelist">): void;
|
|
49
|
+
protected save(e: REvent<any, P>): void;
|
|
46
50
|
/** Clears persisted payload for this module instance and drops any pending save. */
|
|
47
51
|
clear(): void;
|
|
48
52
|
protected onDestroy(): void;
|
|
49
53
|
}
|
|
50
54
|
declare const PERSIST_MODULE_BUILD: Partial<PersistConfig<any>>;
|
|
51
55
|
|
|
52
|
-
export { AsyncStorageAdapter, AsyncStorageAdapterConstructor, BaseReactorModule, PERSIST_MODULE_BUILD, type PersistConfig, PersistModule, StorageAdapter, StorageAdapterConstructor };
|
|
56
|
+
export { AsyncStorageAdapter, AsyncStorageAdapterConstructor, BaseReactorModule, ModulePaths, PERSIST_MODULE_BUILD, type PersistConfig, PersistModule, ReactorModuleId, StorageAdapter, StorageAdapterConstructor };
|
package/dist/modules.js
CHANGED
|
@@ -88,6 +88,16 @@ var BaseReactorModule = class {
|
|
|
88
88
|
return guardMethod(fn, (e) => this.rtrs.values().next().value?.log(`[Reactor "${this.name}" Module] Error: ${e}`));
|
|
89
89
|
};
|
|
90
90
|
// `()=>{}`: needs to be bounded even before initialization
|
|
91
|
+
/**
|
|
92
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
93
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
94
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
95
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
96
|
+
*/
|
|
97
|
+
getPaths(paths, target) {
|
|
98
|
+
const rid = "object" === typeof target ? this.rids.get(target) : target;
|
|
99
|
+
return (paths && (Array.isArray(paths) ? paths : paths[String(rid)])) ?? wpArr;
|
|
100
|
+
}
|
|
91
101
|
};
|
|
92
102
|
|
|
93
103
|
// src/ts/utils/store.ts
|
|
@@ -424,7 +434,7 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
424
434
|
get payload() {
|
|
425
435
|
let res = this.rtrs.size > 1 ? {} : void 0;
|
|
426
436
|
for (const [rid, rtr] of this.rtrs) {
|
|
427
|
-
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core,
|
|
437
|
+
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core, paths = this.getPaths(this.config.whitelist, rid), val = this.config.whitelist ? paths.reduce((acc, p) => (setAny(acc, p, getAny(snap, p)), acc), {}) : snap;
|
|
428
438
|
this.rtrs.size > 1 ? setAny(res, rid, val) : res = val;
|
|
429
439
|
}
|
|
430
440
|
return res;
|
|
@@ -437,10 +447,10 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
437
447
|
"undefined" !== typeof document && document.addEventListener("visibilitychange", () => document.visibilityState === "hidden" && this.onDestroy(), { signal: this.signal });
|
|
438
448
|
this.config.on("adapter", this.handleAdapter, { signal: this.signal, immediate: true });
|
|
439
449
|
this.config.on("disabled", this.handleDisabled, { signal: this.signal, immediate: true });
|
|
440
|
-
this.config.on("
|
|
450
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
441
451
|
}
|
|
442
|
-
onAttach(rtr) {
|
|
443
|
-
for (const p of this.config.
|
|
452
|
+
onAttach(rtr, rid) {
|
|
453
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) !this.config.disabled ? rtr.on(p, this.save, { signal: this.signal, immediate: true }) : rtr.off(p, this.save);
|
|
444
454
|
}
|
|
445
455
|
async handleAdapter({ value = LocalStorageAdapter }) {
|
|
446
456
|
const seq = ++this.hydrateSeq;
|
|
@@ -454,27 +464,29 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
454
464
|
saved = !isAsync ? saved : await saved;
|
|
455
465
|
if (seq !== this.hydrateSeq || !saved) return;
|
|
456
466
|
for (const [rid, rtr] of this.rtrs) {
|
|
467
|
+
const paths = this.getPaths(this.config.whitelist, rid);
|
|
457
468
|
const entry = this.rtrs.size > 1 ? getAny(saved, rid) : saved;
|
|
458
469
|
if (!entry) continue;
|
|
459
470
|
const set = (p, news, olds) => (depth ? fanout : setAny)(rtr.core, p, merge ? mergeObjs(news, olds) : olds, depth ? { depth, crossRealms: rtr.config.crossRealms } : void 0);
|
|
460
|
-
for (const p of this.config.paths
|
|
471
|
+
for (const p of this.config.whitelist ? paths : wpArr) set(p, getAny(rtr.core, p), getAny(entry, p));
|
|
461
472
|
}
|
|
462
|
-
for (const rtr of this.rtrs
|
|
473
|
+
for (const [rid, rtr] of this.rtrs) rtr.tick(depth ? "*" : this.config.whitelist ? this.getPaths(this.config.whitelist, rid) : "*");
|
|
463
474
|
} finally {
|
|
464
475
|
if (seq === this.hydrateSeq) this.state.hydrated = true;
|
|
465
476
|
}
|
|
466
477
|
}
|
|
467
478
|
handleDisabled({ value }) {
|
|
468
|
-
for (const rtr of this.rtrs
|
|
479
|
+
for (const [rid, rtr] of this.rtrs) this.onAttach(rtr, rid);
|
|
469
480
|
value && this.adapter?.remove(this.config.key);
|
|
470
481
|
}
|
|
471
|
-
|
|
472
|
-
for (const rtr of this.rtrs
|
|
473
|
-
for (const p of prevs) rtr.off(p, this.
|
|
474
|
-
for (const p of paths) rtr.off(p, this.
|
|
482
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
483
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
484
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.save);
|
|
485
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.save), !this.config.disabled && rtr.on(p, this.save, { signal: this.signal, immediate: true });
|
|
475
486
|
}
|
|
476
487
|
}
|
|
477
|
-
|
|
488
|
+
save(e) {
|
|
489
|
+
if (this.config.blacklist && this.getPaths(this.config.blacklist, e.reactor).includes(e.path)) return;
|
|
478
490
|
if (!this.state.hydrated) return e.stopImmediatePropagation();
|
|
479
491
|
if (!this.saveTimeoutId) this.saveTimeoutId = setTimeout(() => (this.adapter.set(this.config.key, this.payload), this.saveTimeoutId = 0), this.config.throttle, this.signal);
|
|
480
492
|
}
|
|
@@ -505,22 +517,23 @@ var TimeTravelModule = class extends BaseReactorModule {
|
|
|
505
517
|
wire() {
|
|
506
518
|
this.lastTimestamp = performance.now();
|
|
507
519
|
this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
|
|
508
|
-
this.config.on("
|
|
520
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
509
521
|
!this.state.paused && this.play();
|
|
510
522
|
}
|
|
511
523
|
onAttach(rtr, rid) {
|
|
512
524
|
rtr.config.referenceTracking = rtr.config.smartCloning = rtr.config.eventTimeStamps = true;
|
|
513
525
|
if (!this.state.history.length || !this.state.initialState[rid]) this.state.initialState[rid] = rtr.snapshot();
|
|
514
|
-
for (const p of this.config.
|
|
526
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) rtr.on(p, this.record, { signal: this.signal });
|
|
515
527
|
}
|
|
516
|
-
|
|
517
|
-
for (const rtr of this.rtrs
|
|
518
|
-
for (const p of prevs) rtr.off(p, this.record);
|
|
519
|
-
for (const p of paths) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
528
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
529
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
530
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.record);
|
|
531
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
520
532
|
}
|
|
521
533
|
}
|
|
522
534
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
523
535
|
record(e, rid = this.rids.get(e.reactor)) {
|
|
536
|
+
if (this.getPaths(this.config.blacklist, rid).includes(e.path)) return;
|
|
524
537
|
if (!this.state.paused) return;
|
|
525
538
|
if (this.state.currentFrame < this.state.history.length) fanout(this.state, "history", this.state.history.slice(0, this.state.currentFrame), { atomic: true });
|
|
526
539
|
if (this.state.history.length >= this.config.maxHistoryLength) fanout(this.state, "history", this.state.history.slice(1), { atomic: true });
|
package/dist/super.d.ts
CHANGED
|
@@ -816,6 +816,7 @@ declare function deepClone<T>(obj: T, config?: {
|
|
|
816
816
|
declare function nuke(target: any): void;
|
|
817
817
|
|
|
818
818
|
type ReactorModuleId = string | number;
|
|
819
|
+
type ModulePaths<P extends string = string> = P[] | Partial<Record<string, P[]>>;
|
|
819
820
|
interface ReactorModuleConstructor<P extends BaseReactorModule = BaseReactorModule, T extends object = any> {
|
|
820
821
|
new (rtr: Reactor<T>, config: any): P;
|
|
821
822
|
moduleName: string;
|
|
@@ -873,6 +874,13 @@ declare abstract class BaseReactorModule<T extends object = any, Config = any, S
|
|
|
873
874
|
* window.addEventListener("resize", this.guard(() => this.syncLayout(true)), { signal: this.signal });
|
|
874
875
|
*/
|
|
875
876
|
guard: <Fn extends Function>(fn: Fn) => Fn;
|
|
877
|
+
/**
|
|
878
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
879
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
880
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
881
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
882
|
+
*/
|
|
883
|
+
protected getPaths<P extends string = string>(paths?: ModulePaths<P>, target?: Reactor<any> | ReactorModuleId): P[];
|
|
876
884
|
}
|
|
877
885
|
|
|
878
886
|
/**
|
|
@@ -1686,8 +1694,12 @@ interface PersistConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
|
1686
1694
|
disabled: boolean;
|
|
1687
1695
|
/** The key under which to store the persisted data */
|
|
1688
1696
|
key: string;
|
|
1689
|
-
/**
|
|
1690
|
-
|
|
1697
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
1698
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
1699
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
1700
|
+
whitelist: ModulePaths<P>;
|
|
1701
|
+
/** Exclude filter for save-trigger paths. Checked only during save events. */
|
|
1702
|
+
blacklist?: ModulePaths<P>;
|
|
1691
1703
|
/** Storage adapter class or instance to use, can satisfy `instanceof` or just definition, cast to `any` if the latter */
|
|
1692
1704
|
adapter: Inert<StorageAdapter> | Inert<AsyncStorageAdapter> | Inert<StorageAdapterConstructor> | Inert<AsyncStorageAdapterConstructor>;
|
|
1693
1705
|
/** Throttle time for saving changes */
|
|
@@ -1716,11 +1728,11 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
1716
1728
|
get payload(): Record<string, any> | undefined;
|
|
1717
1729
|
constructor(config?: Partial<PersistConfig<T, P>>, rtr?: Reactor<T>);
|
|
1718
1730
|
wire(): void;
|
|
1719
|
-
protected onAttach(rtr: Reactor<any
|
|
1731
|
+
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
1720
1732
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
1721
1733
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
1722
|
-
protected
|
|
1723
|
-
protected
|
|
1734
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<PersistConfig<T, P>, "whitelist">): void;
|
|
1735
|
+
protected save(e: REvent<any, P>): void;
|
|
1724
1736
|
/** Clears persisted payload for this module instance and drops any pending save. */
|
|
1725
1737
|
clear(): void;
|
|
1726
1738
|
protected onDestroy(): void;
|
|
@@ -1747,8 +1759,12 @@ interface HistoryEntry<T extends object = any, P extends Paths<T> = Paths<T>> {
|
|
|
1747
1759
|
rid: ReactorModuleId;
|
|
1748
1760
|
}
|
|
1749
1761
|
interface TimeTravelConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
1750
|
-
/**
|
|
1751
|
-
|
|
1762
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
1763
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
1764
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
1765
|
+
whitelist: ModulePaths<P>;
|
|
1766
|
+
/** Exclude filter for recorded paths. Checked only during record events. */
|
|
1767
|
+
blacklist?: ModulePaths<P>;
|
|
1752
1768
|
/** Maximum number of history entries to keep (Memory Cap), you lose replaying Sessions or the Genesis */
|
|
1753
1769
|
maxHistoryLength: number;
|
|
1754
1770
|
/** Max delay between events during playback (ms) */
|
|
@@ -1779,7 +1795,7 @@ declare class TimeTravelModule<T extends object = any, P extends Paths<T> = Path
|
|
|
1779
1795
|
constructor(config?: Partial<TimeTravelConfig<T, P>>, rtr?: Reactor<T>);
|
|
1780
1796
|
wire(): void;
|
|
1781
1797
|
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
1782
|
-
protected
|
|
1798
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<TimeTravelConfig<T, P>, "whitelist">): void;
|
|
1783
1799
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
1784
1800
|
protected record(e: REvent<any, P>, rid?: ReactorModuleId): void;
|
|
1785
1801
|
/** Clears timeline history and resets playhead/genesis to the current reactor state. */
|
|
@@ -1831,6 +1847,7 @@ declare const modules_LocalStorageAdapter: typeof LocalStorageAdapter;
|
|
|
1831
1847
|
type modules_MemoryAdapter = MemoryAdapter;
|
|
1832
1848
|
declare const modules_MemoryAdapter: typeof MemoryAdapter;
|
|
1833
1849
|
type modules_MemoryAdapterConfig = MemoryAdapterConfig;
|
|
1850
|
+
type modules_ModulePaths<P extends string = string> = ModulePaths<P>;
|
|
1834
1851
|
declare const modules_PERSIST_MODULE_BUILD: typeof PERSIST_MODULE_BUILD;
|
|
1835
1852
|
type modules_PersistConfig<T extends object, P extends Paths<T> = Paths<T>> = PersistConfig<T, P>;
|
|
1836
1853
|
type modules_PersistModule<T extends object = any, P extends Paths<T> = Paths<T>> = PersistModule<T, P>;
|
|
@@ -1849,7 +1866,7 @@ type modules_TimeTravelModule<T extends object = any, P extends Paths<T> = Paths
|
|
|
1849
1866
|
declare const modules_TimeTravelModule: typeof TimeTravelModule;
|
|
1850
1867
|
type modules_TimeTravelState<T extends object, P extends Paths<T> = Paths<T>> = TimeTravelState<T, P>;
|
|
1851
1868
|
declare namespace modules {
|
|
1852
|
-
export { modules_AsyncStorageAdapter as AsyncStorageAdapter, type modules_AsyncStorageAdapterConstructor as AsyncStorageAdapterConstructor, modules_BaseReactorModule as BaseReactorModule, modules_BaseStorageAdapter as BaseStorageAdapter, modules_COOKIE_ADAPTER_BUILD as COOKIE_ADAPTER_BUILD, modules_CookieAdapter as CookieAdapter, type modules_CookieAdapterConfig as CookieAdapterConfig, type modules_CookieOptions as CookieOptions, type modules_HistoryEntry as HistoryEntry, modules_INDEXED_DB_ADAPTER_BUILD as INDEXED_DB_ADAPTER_BUILD, modules_IndexedDBAdapter as IndexedDBAdapter, type modules_IndexedDBAdapterConfig as IndexedDBAdapterConfig, type modules_JSONReplacer as JSONReplacer, type modules_JSONReviver as JSONReviver, modules_LocalStorageAdapter as LocalStorageAdapter, modules_MemoryAdapter as MemoryAdapter, type modules_MemoryAdapterConfig as MemoryAdapterConfig, modules_PERSIST_MODULE_BUILD as PERSIST_MODULE_BUILD, type modules_PersistConfig as PersistConfig, modules_PersistModule as PersistModule, type modules_ReactorModuleConstructor as ReactorModuleConstructor, type modules_ReactorModuleId as ReactorModuleId, modules_SessionStorageAdapter as SessionStorageAdapter, modules_StorageAdapter as StorageAdapter, type modules_StorageAdapterConfig as StorageAdapterConfig, type modules_StorageAdapterConstructor as StorageAdapterConstructor, modules_TIME_TRAVEL_MODULE_BUILD as TIME_TRAVEL_MODULE_BUILD, type modules_TimeTravelConfig as TimeTravelConfig, modules_TimeTravelModule as TimeTravelModule, type modules_TimeTravelState as TimeTravelState };
|
|
1869
|
+
export { modules_AsyncStorageAdapter as AsyncStorageAdapter, type modules_AsyncStorageAdapterConstructor as AsyncStorageAdapterConstructor, modules_BaseReactorModule as BaseReactorModule, modules_BaseStorageAdapter as BaseStorageAdapter, modules_COOKIE_ADAPTER_BUILD as COOKIE_ADAPTER_BUILD, modules_CookieAdapter as CookieAdapter, type modules_CookieAdapterConfig as CookieAdapterConfig, type modules_CookieOptions as CookieOptions, type modules_HistoryEntry as HistoryEntry, modules_INDEXED_DB_ADAPTER_BUILD as INDEXED_DB_ADAPTER_BUILD, modules_IndexedDBAdapter as IndexedDBAdapter, type modules_IndexedDBAdapterConfig as IndexedDBAdapterConfig, type modules_JSONReplacer as JSONReplacer, type modules_JSONReviver as JSONReviver, modules_LocalStorageAdapter as LocalStorageAdapter, modules_MemoryAdapter as MemoryAdapter, type modules_MemoryAdapterConfig as MemoryAdapterConfig, type modules_ModulePaths as ModulePaths, modules_PERSIST_MODULE_BUILD as PERSIST_MODULE_BUILD, type modules_PersistConfig as PersistConfig, modules_PersistModule as PersistModule, type modules_ReactorModuleConstructor as ReactorModuleConstructor, type modules_ReactorModuleId as ReactorModuleId, modules_SessionStorageAdapter as SessionStorageAdapter, modules_StorageAdapter as StorageAdapter, type modules_StorageAdapterConfig as StorageAdapterConfig, type modules_StorageAdapterConstructor as StorageAdapterConstructor, modules_TIME_TRAVEL_MODULE_BUILD as TIME_TRAVEL_MODULE_BUILD, type modules_TimeTravelConfig as TimeTravelConfig, modules_TimeTravelModule as TimeTravelModule, type modules_TimeTravelState as TimeTravelState };
|
|
1853
1870
|
}
|
|
1854
1871
|
|
|
1855
1872
|
/**
|
package/dist/super.global.js
CHANGED
|
@@ -1256,6 +1256,16 @@ var sia = (() => {
|
|
|
1256
1256
|
return guardMethod(fn, (e) => this.rtrs.values().next().value?.log(`[Reactor "${this.name}" Module] Error: ${e}`));
|
|
1257
1257
|
};
|
|
1258
1258
|
// `()=>{}`: needs to be bounded even before initialization
|
|
1259
|
+
/**
|
|
1260
|
+
* Path resolution utility for modules, provides automatic reactor id resolution for multi-reactor setups.
|
|
1261
|
+
* @param paths Paths to filter by, supports same formats as `ModulePaths`, will be resolved with the module's reactor id if applicable.
|
|
1262
|
+
* @param target Reactor or reactor id to resolve paths for when using per-reactor path lists`.
|
|
1263
|
+
* @returns Resolved paths array, defaults to `["*"]` if no paths are found using search criteria.
|
|
1264
|
+
*/
|
|
1265
|
+
getPaths(paths, target) {
|
|
1266
|
+
const rid = "object" === typeof target ? this.rids.get(target) : target;
|
|
1267
|
+
return (paths && (Array.isArray(paths) ? paths : paths[String(rid)])) ?? wpArr;
|
|
1268
|
+
}
|
|
1259
1269
|
};
|
|
1260
1270
|
|
|
1261
1271
|
// src/ts/utils/store.ts
|
|
@@ -1592,7 +1602,7 @@ var sia = (() => {
|
|
|
1592
1602
|
get payload() {
|
|
1593
1603
|
let res = this.rtrs.size > 1 ? {} : void 0;
|
|
1594
1604
|
for (const [rid, rtr] of this.rtrs) {
|
|
1595
|
-
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core,
|
|
1605
|
+
const snap = this.config.useSnapshot ? (this.config.useSnapshot === true && (rtr.config.referenceTracking = rtr.config.smartCloning = true), rtr.snapshot()) : rtr.core, paths = this.getPaths(this.config.whitelist, rid), val = this.config.whitelist ? paths.reduce((acc, p) => (setAny(acc, p, getAny(snap, p)), acc), {}) : snap;
|
|
1596
1606
|
this.rtrs.size > 1 ? setAny(res, rid, val) : res = val;
|
|
1597
1607
|
}
|
|
1598
1608
|
return res;
|
|
@@ -1605,10 +1615,10 @@ var sia = (() => {
|
|
|
1605
1615
|
"undefined" !== typeof document && document.addEventListener("visibilitychange", () => document.visibilityState === "hidden" && this.onDestroy(), { signal: this.signal });
|
|
1606
1616
|
this.config.on("adapter", this.handleAdapter, { signal: this.signal, immediate: true });
|
|
1607
1617
|
this.config.on("disabled", this.handleDisabled, { signal: this.signal, immediate: true });
|
|
1608
|
-
this.config.on("
|
|
1618
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
1609
1619
|
}
|
|
1610
|
-
onAttach(rtr) {
|
|
1611
|
-
for (const p of this.config.
|
|
1620
|
+
onAttach(rtr, rid) {
|
|
1621
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) !this.config.disabled ? rtr.on(p, this.save, { signal: this.signal, immediate: true }) : rtr.off(p, this.save);
|
|
1612
1622
|
}
|
|
1613
1623
|
async handleAdapter({ value = LocalStorageAdapter }) {
|
|
1614
1624
|
const seq = ++this.hydrateSeq;
|
|
@@ -1622,27 +1632,29 @@ var sia = (() => {
|
|
|
1622
1632
|
saved = !isAsync ? saved : await saved;
|
|
1623
1633
|
if (seq !== this.hydrateSeq || !saved) return;
|
|
1624
1634
|
for (const [rid, rtr] of this.rtrs) {
|
|
1635
|
+
const paths = this.getPaths(this.config.whitelist, rid);
|
|
1625
1636
|
const entry = this.rtrs.size > 1 ? getAny(saved, rid) : saved;
|
|
1626
1637
|
if (!entry) continue;
|
|
1627
1638
|
const set = (p, news, olds) => (depth ? fanout : setAny)(rtr.core, p, merge ? mergeObjs(news, olds) : olds, depth ? { depth, crossRealms: rtr.config.crossRealms } : void 0);
|
|
1628
|
-
for (const p of this.config.paths
|
|
1639
|
+
for (const p of this.config.whitelist ? paths : wpArr) set(p, getAny(rtr.core, p), getAny(entry, p));
|
|
1629
1640
|
}
|
|
1630
|
-
for (const rtr of this.rtrs
|
|
1641
|
+
for (const [rid, rtr] of this.rtrs) rtr.tick(depth ? "*" : this.config.whitelist ? this.getPaths(this.config.whitelist, rid) : "*");
|
|
1631
1642
|
} finally {
|
|
1632
1643
|
if (seq === this.hydrateSeq) this.state.hydrated = true;
|
|
1633
1644
|
}
|
|
1634
1645
|
}
|
|
1635
1646
|
handleDisabled({ value }) {
|
|
1636
|
-
for (const rtr of this.rtrs
|
|
1647
|
+
for (const [rid, rtr] of this.rtrs) this.onAttach(rtr, rid);
|
|
1637
1648
|
value && this.adapter?.remove(this.config.key);
|
|
1638
1649
|
}
|
|
1639
|
-
|
|
1640
|
-
for (const rtr of this.rtrs
|
|
1641
|
-
for (const p of prevs) rtr.off(p, this.
|
|
1642
|
-
for (const p of paths) rtr.off(p, this.
|
|
1650
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
1651
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
1652
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.save);
|
|
1653
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.save), !this.config.disabled && rtr.on(p, this.save, { signal: this.signal, immediate: true });
|
|
1643
1654
|
}
|
|
1644
1655
|
}
|
|
1645
|
-
|
|
1656
|
+
save(e) {
|
|
1657
|
+
if (this.config.blacklist && this.getPaths(this.config.blacklist, e.reactor).includes(e.path)) return;
|
|
1646
1658
|
if (!this.state.hydrated) return e.stopImmediatePropagation();
|
|
1647
1659
|
if (!this.saveTimeoutId) this.saveTimeoutId = setTimeout2(() => (this.adapter.set(this.config.key, this.payload), this.saveTimeoutId = 0), this.config.throttle, this.signal);
|
|
1648
1660
|
}
|
|
@@ -1673,22 +1685,23 @@ var sia = (() => {
|
|
|
1673
1685
|
wire() {
|
|
1674
1686
|
this.lastTimestamp = performance.now();
|
|
1675
1687
|
this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
|
|
1676
|
-
this.config.on("
|
|
1688
|
+
this.config.on("whitelist", this.handleWhitelist, { signal: this.signal, immediate: true });
|
|
1677
1689
|
!this.state.paused && this.play();
|
|
1678
1690
|
}
|
|
1679
1691
|
onAttach(rtr, rid) {
|
|
1680
1692
|
rtr.config.referenceTracking = rtr.config.smartCloning = rtr.config.eventTimeStamps = true;
|
|
1681
1693
|
if (!this.state.history.length || !this.state.initialState[rid]) this.state.initialState[rid] = rtr.snapshot();
|
|
1682
|
-
for (const p of this.config.
|
|
1694
|
+
for (const p of this.getPaths(this.config.whitelist, rid)) rtr.on(p, this.record, { signal: this.signal });
|
|
1683
1695
|
}
|
|
1684
|
-
|
|
1685
|
-
for (const rtr of this.rtrs
|
|
1686
|
-
for (const p of prevs) rtr.off(p, this.record);
|
|
1687
|
-
for (const p of paths) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
1696
|
+
handleWhitelist({ value: paths, oldValue: prevs }) {
|
|
1697
|
+
for (const [rid, rtr] of this.rtrs) {
|
|
1698
|
+
for (const p of this.getPaths(prevs, rid)) rtr.off(p, this.record);
|
|
1699
|
+
for (const p of this.getPaths(paths, rid)) rtr.off(p, this.record), rtr.on(p, this.record, { signal: this.signal });
|
|
1688
1700
|
}
|
|
1689
1701
|
}
|
|
1690
1702
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
1691
1703
|
record(e, rid = this.rids.get(e.reactor)) {
|
|
1704
|
+
if (this.getPaths(this.config.blacklist, rid).includes(e.path)) return;
|
|
1692
1705
|
if (!this.state.paused) return;
|
|
1693
1706
|
if (this.state.currentFrame < this.state.history.length) fanout(this.state, "history", this.state.history.slice(0, this.state.currentFrame), { atomic: true });
|
|
1694
1707
|
if (this.state.history.length >= this.config.maxHistoryLength) fanout(this.state, "history", this.state.history.slice(1), { atomic: true });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Paths, e as PathValue,
|
|
1
|
+
import { P as Paths, e as PathValue, b as REvent, a as ReactorModuleId, M as ModulePaths, B as BaseReactorModule, R as Reactor } from './index-2jKy98op.js';
|
|
2
2
|
|
|
3
3
|
type JSONReplacer = ((this: any, key: string, value: any) => any) | (number | string)[] | null;
|
|
4
4
|
type JSONReviver = ((this: any, key: string, value: any) => any) | undefined;
|
|
@@ -289,8 +289,12 @@ interface HistoryEntry<T extends object = any, P extends Paths<T> = Paths<T>> {
|
|
|
289
289
|
rid: ReactorModuleId;
|
|
290
290
|
}
|
|
291
291
|
interface TimeTravelConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
292
|
-
/**
|
|
293
|
-
|
|
292
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
293
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
294
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
295
|
+
whitelist: ModulePaths<P>;
|
|
296
|
+
/** Exclude filter for recorded paths. Checked only during record events. */
|
|
297
|
+
blacklist?: ModulePaths<P>;
|
|
294
298
|
/** Maximum number of history entries to keep (Memory Cap), you lose replaying Sessions or the Genesis */
|
|
295
299
|
maxHistoryLength: number;
|
|
296
300
|
/** Max delay between events during playback (ms) */
|
|
@@ -321,7 +325,7 @@ declare class TimeTravelModule<T extends object = any, P extends Paths<T> = Path
|
|
|
321
325
|
constructor(config?: Partial<TimeTravelConfig<T, P>>, rtr?: Reactor<T>);
|
|
322
326
|
wire(): void;
|
|
323
327
|
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
324
|
-
protected
|
|
328
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<TimeTravelConfig<T, P>, "whitelist">): void;
|
|
325
329
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
326
330
|
protected record(e: REvent<any, P>, rid?: ReactorModuleId): void;
|
|
327
331
|
/** Clears timeline history and resets playhead/genesis to the current reactor state. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Paths, e as PathValue,
|
|
1
|
+
import { P as Paths, e as PathValue, b as REvent, a as ReactorModuleId, M as ModulePaths, B as BaseReactorModule, R as Reactor } from './index-2jKy98op.cjs';
|
|
2
2
|
|
|
3
3
|
type JSONReplacer = ((this: any, key: string, value: any) => any) | (number | string)[] | null;
|
|
4
4
|
type JSONReviver = ((this: any, key: string, value: any) => any) | undefined;
|
|
@@ -289,8 +289,12 @@ interface HistoryEntry<T extends object = any, P extends Paths<T> = Paths<T>> {
|
|
|
289
289
|
rid: ReactorModuleId;
|
|
290
290
|
}
|
|
291
291
|
interface TimeTravelConfig<T extends object, P extends Paths<T> = Paths<T>> {
|
|
292
|
-
/**
|
|
293
|
-
|
|
292
|
+
/** Whitelist paths only, no need for "*"; instead don't pass anything.
|
|
293
|
+
* - `P[]`: one shared path list for all attached reactors.
|
|
294
|
+
* - `Record<string, P[]>`: per-reactor path lists keyed by module reactor id. If you don't pass ids in `.attach()`, use implicit index keys (`"0"`, `"1"`, ...). */
|
|
295
|
+
whitelist: ModulePaths<P>;
|
|
296
|
+
/** Exclude filter for recorded paths. Checked only during record events. */
|
|
297
|
+
blacklist?: ModulePaths<P>;
|
|
294
298
|
/** Maximum number of history entries to keep (Memory Cap), you lose replaying Sessions or the Genesis */
|
|
295
299
|
maxHistoryLength: number;
|
|
296
300
|
/** Max delay between events during playback (ms) */
|
|
@@ -321,7 +325,7 @@ declare class TimeTravelModule<T extends object = any, P extends Paths<T> = Path
|
|
|
321
325
|
constructor(config?: Partial<TimeTravelConfig<T, P>>, rtr?: Reactor<T>);
|
|
322
326
|
wire(): void;
|
|
323
327
|
protected onAttach(rtr: Reactor<any>, rid: ReactorModuleId): void;
|
|
324
|
-
protected
|
|
328
|
+
protected handleWhitelist({ value: paths, oldValue: prevs }: REvent<TimeTravelConfig<T, P>, "whitelist">): void;
|
|
325
329
|
/** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
|
|
326
330
|
protected record(e: REvent<any, P>, rid?: ReactorModuleId): void;
|
|
327
331
|
/** Clears timeline history and resets playhead/genesis to the current reactor state. */
|
package/dist/utils.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FanoutTuple, f as arrRegex, g as canHandle, h as deepClone, i as deleteAny, j as fanout, k as fanoutOptsArr, l as getAny, m as getTrailRecords, n as inAny, o as isObj, p as isPOJO, q as mergeObjs, r as nuke, s as parseAnyObj, t as parseEvtOpts, u as setAny } from './index-
|
|
1
|
+
export { F as FanoutTuple, f as arrRegex, g as canHandle, h as deepClone, i as deleteAny, j as fanout, k as fanoutOptsArr, l as getAny, m as getTrailRecords, n as inAny, o as isObj, p as isPOJO, q as mergeObjs, r as nuke, s as parseAnyObj, t as parseEvtOpts, u as setAny } from './index-2jKy98op.cjs';
|
|
2
2
|
|
|
3
3
|
declare function clamp(min: number | undefined, val: number, max?: number): number;
|
|
4
4
|
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FanoutTuple, f as arrRegex, g as canHandle, h as deepClone, i as deleteAny, j as fanout, k as fanoutOptsArr, l as getAny, m as getTrailRecords, n as inAny, o as isObj, p as isPOJO, q as mergeObjs, r as nuke, s as parseAnyObj, t as parseEvtOpts, u as setAny } from './index-
|
|
1
|
+
export { F as FanoutTuple, f as arrRegex, g as canHandle, h as deepClone, i as deleteAny, j as fanout, k as fanoutOptsArr, l as getAny, m as getTrailRecords, n as inAny, o as isObj, p as isPOJO, q as mergeObjs, r as nuke, s as parseAnyObj, t as parseEvtOpts, u as setAny } from './index-2jKy98op.js';
|
|
2
2
|
|
|
3
3
|
declare function clamp(min: number | undefined, val: number, max?: number): number;
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sia-reactor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "The Programmable Data DOM. A high-performance State Intent Architecture (S.I.A.) Engine with zero-allocation loops, event propagation, and structural sharing.",
|
|
5
5
|
"author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/Tobi007-del/
|
|
10
|
-
"directory": "packages/sia-reactor"
|
|
9
|
+
"url": "git+https://github.com/Tobi007-del/sia-reactor.git"
|
|
11
10
|
},
|
|
12
|
-
"homepage": "https://github.com/Tobi007-del/
|
|
11
|
+
"homepage": "https://github.com/Tobi007-del/sia-reactor#readme",
|
|
13
12
|
"bugs": {
|
|
14
13
|
"url": "https://github.com/Tobi007-del/sia-reactor/issues"
|
|
15
14
|
},
|
|
@@ -58,12 +57,14 @@
|
|
|
58
57
|
},
|
|
59
58
|
"scripts": {
|
|
60
59
|
"build": "tsup --config tsup.config.ts",
|
|
61
|
-
"prepublishOnly": "shx cp ../../LICENSE .",
|
|
62
60
|
"test": "vitest --reporter=verbose",
|
|
63
|
-
"test:run": "vitest run",
|
|
61
|
+
"test:run": "vitest run --reporter=verbose",
|
|
64
62
|
"demo": "vite --config demo/vite.config.ts",
|
|
65
63
|
"demo:build": "vite build --config demo/vite.config.ts",
|
|
66
|
-
"demo:preview": "vite preview --config demo/vite.config.ts"
|
|
64
|
+
"demo:preview": "vite preview --config demo/vite.config.ts",
|
|
65
|
+
"change": "changeset",
|
|
66
|
+
"bump": "changeset version",
|
|
67
|
+
"release": "changeset publish"
|
|
67
68
|
},
|
|
68
69
|
"files": [
|
|
69
70
|
"dist"
|
|
@@ -89,6 +90,8 @@
|
|
|
89
90
|
"zero-dependency"
|
|
90
91
|
],
|
|
91
92
|
"devDependencies": {
|
|
93
|
+
"@changesets/cli": "^2.30.0",
|
|
94
|
+
"@types/node": "^25.2.2",
|
|
92
95
|
"@types/react-dom": "^18.0.0",
|
|
93
96
|
"@vitejs/plugin-react": "^5.0.4",
|
|
94
97
|
"@types/react": "^18.0.0",
|