sia-reactor 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +102 -58
  2. package/dist/TimeTravelOverlay-CJv-S_Km.d.cts +41 -0
  3. package/dist/TimeTravelOverlay-DxqJL0Zk.d.ts +41 -0
  4. package/dist/adapters/react.cjs +308 -92
  5. package/dist/adapters/react.d.cts +68 -10
  6. package/dist/adapters/react.d.ts +68 -10
  7. package/dist/adapters/react.js +80 -29
  8. package/dist/adapters/vanilla.cjs +957 -10
  9. package/dist/adapters/vanilla.d.cts +4 -2
  10. package/dist/adapters/vanilla.d.ts +4 -2
  11. package/dist/adapters/vanilla.js +8 -12
  12. package/dist/{chunk-Q2AKMIHN.js → chunk-2WBPGSRL.js} +106 -48
  13. package/dist/chunk-5A44QFT6.js +93 -0
  14. package/dist/{chunk-4MJUBEI7.js → chunk-DP74DVRT.js} +4 -2
  15. package/dist/{chunk-UQIMMJTY.js → chunk-P37ADJMM.js} +3 -3
  16. package/dist/chunk-TFLYCXK4.js +251 -0
  17. package/dist/{index-C2hyIh0K.d.cts → index-Oie9hhE8.d.cts} +14 -10
  18. package/dist/{index-C2hyIh0K.d.ts → index-Oie9hhE8.d.ts} +14 -10
  19. package/dist/index.cjs +45 -52
  20. package/dist/index.d.cts +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +4 -6
  23. package/dist/plugins.cjs +72 -73
  24. package/dist/plugins.d.cts +4 -75
  25. package/dist/plugins.d.ts +4 -75
  26. package/dist/plugins.js +27 -22
  27. package/dist/styles/time-travel-overlay.css +189 -0
  28. package/dist/super.d.ts +79 -26
  29. package/dist/super.global.js +200 -105
  30. package/dist/timeTravel-B1vedDQc.d.ts +76 -0
  31. package/dist/timeTravel-WpgWmKu-.d.cts +76 -0
  32. package/dist/utils.cjs +34 -7
  33. package/dist/utils.d.cts +9 -2
  34. package/dist/utils.d.ts +9 -2
  35. package/dist/utils.js +17 -65
  36. package/package.json +3 -2
  37. package/dist/chunk-FGUCKMLH.js +0 -154
  38. package/dist/chunk-KIQP7G7W.js +0 -80
package/dist/plugins.cjs CHANGED
@@ -17,7 +17,7 @@ var __copyProps = (to, from, except, desc) => {
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
- // src/plugins.ts
20
+ // src/ts/plugins.ts
21
21
  var plugins_exports = {};
22
22
  __export(plugins_exports, {
23
23
  BaseReactorPlugin: () => BaseReactorPlugin,
@@ -34,8 +34,10 @@ __export(plugins_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(plugins_exports);
36
36
 
37
- // src/core/consts.ts
37
+ // src/ts/core/consts.ts
38
38
  var CTX = {
39
+ /** Flag indicating whether the application is running in development mode. */
40
+ isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
39
41
  /** active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
40
42
  autotracker: null
41
43
  };
@@ -54,7 +56,7 @@ var NIL = Object.freeze({});
54
56
  var NOOP = () => {
55
57
  };
56
58
 
57
- // src/utils/obj.ts
59
+ // src/ts/utils/obj.ts
58
60
  var arrRx = /^([^\[\]]+)\[(\d+)\]$/;
59
61
  function isObj(obj, arraycheck = true) {
60
62
  return "object" === typeof obj && obj !== null && (arraycheck ? !Array.isArray(obj) : true);
@@ -181,7 +183,7 @@ function nuke(target) {
181
183
  }
182
184
  }
183
185
 
184
- // src/core/event.ts
186
+ // src/ts/core/event.ts
185
187
  var ReactorEvent = class _ReactorEvent {
186
188
  /** No active propagation phase. */
187
189
  static NONE = 0;
@@ -304,7 +306,7 @@ var ReactorEvent = class _ReactorEvent {
304
306
  }
305
307
  };
306
308
 
307
- // src/core/reactor.ts
309
+ // src/ts/core/reactor.ts
308
310
  var Reactor = class {
309
311
  log = NOOP;
310
312
  core;
@@ -332,27 +334,27 @@ var Reactor = class {
332
334
  listeners;
333
335
  /**
334
336
  * Creates a new Reactor instance.
335
- * @param object Initial state object.
337
+ * @param target Initial state target.
336
338
  * @param build Reactor bootstrap/build configuration.
337
339
  * @example
338
340
  * const rtr = new Reactor({ count: 0 });
339
341
  */
340
- constructor(object = {}, build) {
342
+ constructor(target = {}, build) {
341
343
  this[INERTIA] = true;
342
344
  this.config = { crossRealms: false, smartCloning: false, eventBubbling: true, lineageTracing: false, preserveContext: false, equalityFunction: Object.is, batchingFunction: RTR_BATCH, ...build };
343
- this.core = this.proxied(object);
345
+ this.core = this.proxied(target);
344
346
  if (build) this.canLog = !!build.debug;
345
347
  }
346
- proxied(obj, rejectable = false, indiffable = false, parent, key, path) {
347
- if (!obj || "object" !== typeof obj) return obj;
348
- obj = obj[RAW] || obj;
349
- if (this.config.referenceTracking && parent && key && !this.link(obj, parent, key, false)) return obj;
350
- const cached = this.proxyCache.get(obj);
348
+ proxied(target, rejectable = false, indiffable = false, parent, key, path) {
349
+ if (!target || "object" !== typeof target) return target;
350
+ target = target[RAW] || target;
351
+ if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
352
+ const cached = this.proxyCache.get(target);
351
353
  if (cached) return cached;
352
- if (obj[INERTIA] || !canHandle(obj, this.config, false)) return obj;
353
- rejectable ||= obj[REJECTABLE];
354
- indiffable ||= obj[INDIFFABLE];
355
- const proxy = new Proxy(obj, {
354
+ if (target[INERTIA] || !canHandle(target, this.config, false)) return target;
355
+ rejectable ||= target[REJECTABLE];
356
+ indiffable ||= target[INDIFFABLE];
357
+ const proxy = new Proxy(target, {
356
358
  // Robust Proxy handler
357
359
  get: (object, key2, receiver) => {
358
360
  if (key2 === RAW) return this.log(`\u{1F440} [Reactor \`get\` Trap] Peeked at ${object}`), object;
@@ -365,10 +367,10 @@ var Reactor = class {
365
367
  for (let i = 0, len = this.config.lineageTracing ? paths.length : 1; i < len; i++) {
366
368
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.getters.get(currPath);
367
369
  if (!cords && !wildcords) continue;
368
- const target = { path: currPath, value, key: keyStr, keyExisted: true, object: receiver }, payload = { type: "get", target, currentTarget: target, root: this.core, rejectable };
370
+ const target2 = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target: target2, currentTarget: target2, root: this.core, rejectable };
369
371
  if (cords) value = this.mediate(currPath, payload, "get", cords);
370
372
  if (!wildcords) continue;
371
- target.value = value;
373
+ target2.value = value;
372
374
  value = this.mediate("*", payload, "get", wildcords);
373
375
  }
374
376
  }
@@ -376,7 +378,7 @@ var Reactor = class {
376
378
  },
377
379
  set: (object, key2, value, receiver) => {
378
380
  let unchanged, safeValue, safeOldValue, terminated = false;
379
- const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), keyExisted = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
381
+ const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), hadKey = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
380
382
  this.log(`\u270F\uFE0F [Reactor \`set\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
381
383
  if (this.config.referenceTracking || !indiffable) {
382
384
  safeOldValue = oldValue?.[RAW] || oldValue;
@@ -390,13 +392,13 @@ var Reactor = class {
390
392
  for (let i = 0; i < loopLen; i++) {
391
393
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.setters.get(currPath);
392
394
  if (!cords && !wildcords) continue;
393
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable };
395
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable };
394
396
  if (cords) {
395
397
  const result2 = this.mediate(currPath, payload, "set", cords);
396
398
  if (!(terminated ||= payload.terminated)) value = result2;
397
399
  }
398
400
  if (!wildcords) continue;
399
- target.value = value;
401
+ target2.value = value;
400
402
  const result = this.mediate("*", payload, "set", wildcords);
401
403
  if (!(terminated ||= payload.terminated)) value = result;
402
404
  }
@@ -407,14 +409,14 @@ var Reactor = class {
407
409
  if (this.config.referenceTracking && !unchanged) this.config.smartCloning && this.stamp(object), this.unlink(safeOldValue, object, keyStr), this.link(safeValue, object, keyStr);
408
410
  if (this.watchers || this.listeners)
409
411
  for (let i = 0; i < loopLen; i++) {
410
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
411
- this.notify(currPath, { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable });
412
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
413
+ this.notify(currPath, { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable });
412
414
  }
413
415
  return true;
414
416
  },
415
417
  deleteProperty: (object, key2) => {
416
418
  let value, receiver = this.proxyCache.get(object), terminated = false;
417
- const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), keyExisted = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
419
+ const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), hadKey = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
418
420
  this.log(`\u{1F5D1}\uFE0F [Reactor \`deleteProperty\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
419
421
  if (this.config.deleteProperty) terminated = (value = this.config.deleteProperty(object, key2, oldValue, receiver, paths)) === TERMINATOR;
420
422
  if (this.deleters) {
@@ -422,7 +424,7 @@ var Reactor = class {
422
424
  for (let i = 0; i < loopLen; i++) {
423
425
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.deleters.get(currPath);
424
426
  if (!cords && !wildcords) continue;
425
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "delete", target, currentTarget: target, root: this.core, rejectable };
427
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable };
426
428
  if (cords) {
427
429
  const result2 = this.mediate(currPath, payload, "delete", cords);
428
430
  if (!(terminated ||= payload.terminated)) value = result2;
@@ -438,8 +440,8 @@ var Reactor = class {
438
440
  if (this.config.referenceTracking) this.config.smartCloning && this.stamp(object), this.unlink(oldValue?.[RAW] || oldValue, object, keyStr);
439
441
  if (this.watchers || this.listeners)
440
442
  for (let i = 0; i < loopLen; i++) {
441
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
442
- this.notify(currPath, { type: "delete", target, currentTarget: target, root: this.core, rejectable });
443
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
444
+ this.notify(currPath, { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable });
443
445
  }
444
446
  return true;
445
447
  },
@@ -465,7 +467,7 @@ var Reactor = class {
465
467
  return ownKeys;
466
468
  }
467
469
  });
468
- return this.proxyCache.set(obj, proxy), proxy;
470
+ return this.proxyCache.set(target, proxy), proxy;
469
471
  }
470
472
  trace(target, path, paths = [], seen = /* @__PURE__ */ new WeakSet()) {
471
473
  if (Object.is(target, this.core[RAW] || this.core)) return paths.push(path), paths;
@@ -557,7 +559,7 @@ var Reactor = class {
557
559
  fire([path, object, value], e, isCapture, cords = this.listeners.get(path)) {
558
560
  if (!cords) return;
559
561
  e.type = path !== e.target.path ? "update" : e.staticType;
560
- e.currentTarget = { path, value, oldValue: e.type !== "update" ? e.target.oldValue : void 0, key: e.type !== "update" ? path : path.slice(path.lastIndexOf(".") + 1) || "", keyExisted: e.type !== "update" ? e.target.keyExisted : true, object };
562
+ e.currentTarget = { path, value, oldValue: e.type !== "update" ? e.target.oldValue : void 0, key: e.type !== "update" ? path : path.slice(path.lastIndexOf(".") + 1) || "", hadKey: e.type !== "update" ? e.target.hadKey : true, object };
561
563
  for (let i = 0, len = cords.length, tDepth; i < len; i++) {
562
564
  if (e.immediatePropagationStopped) break;
563
565
  if (cords[i].capture !== isCapture) continue;
@@ -612,21 +614,20 @@ var Reactor = class {
612
614
  }
613
615
  getContext(path) {
614
616
  const lastDot = path.lastIndexOf("."), value = getAny(this.core, path), object = lastDot === -1 ? this.core : getAny(this.core, path.slice(0, lastDot));
615
- return { path, value, key: path.slice(lastDot + 1) || "", keyExisted: true, object };
617
+ return { path, value, key: path.slice(lastDot + 1) || "", hadKey: true, object };
616
618
  }
617
619
  bindSignal(cord, sig) {
618
620
  if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
619
621
  return cord.sclup = !sig || sig.aborted ? NOOP : () => sig.removeEventListener("abort", cord.clup), cord.clup;
620
622
  }
621
- cloned(obj, raw, seen = /* @__PURE__ */ new WeakMap()) {
622
- if (!obj || "object" !== typeof obj) return obj;
623
- obj = obj[RAW] || obj;
624
- const cloned = seen.get(obj);
623
+ cloned(target, raw, seen = /* @__PURE__ */ new WeakMap()) {
624
+ if (!target || "object" !== typeof target) return target;
625
+ const obj = target[RAW] || target, cloned = seen.get(obj);
625
626
  if (cloned) return cloned;
626
627
  if (!canHandle(obj, this.config, false)) return obj;
627
628
  const version = obj[VERSION] || 0, cached = !raw && this.config.smartCloning && (this.snapCache ??= /* @__PURE__ */ new WeakMap()).get(obj);
628
629
  if (cached && obj[SSVERSION] === version) return cached;
629
- const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj[RAW] || obj;
630
+ const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
630
631
  seen.set(obj, clone);
631
632
  const keys = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
632
633
  for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = this.cloned(obj[keys[i]], raw, seen);
@@ -810,19 +811,8 @@ var Reactor = class {
810
811
  for (let i = 0, len = cords.length; i < len; i++) if (Object.is(cords[i].cb, callback) && cords[i].capture === capture) return cords[i].sclup(), cords.splice((len--, i--), 1), !cords.length && this.listeners.delete(path), true;
811
812
  return false;
812
813
  }
813
- /**
814
- * Creates a snapshot; possibly clone of state (or a state branch).
815
- * You could alternatively use or serialize your proxied state "as is" except the environment demands no proxies or new references.
816
- * @param raw Use raw (deep unproxied & uncloned) version of branch.
817
- * @param branch Branch to clone.
818
- * @returns Snapshot deep or smart (structurally shared) clone.
819
- * @example
820
- * const snap = rtr.snapshot();
821
- * @example
822
- * const snap = rtr.snapshot(false, rtr.core.history.past);
823
- */
824
- snapshot(raw = !this.config.smartCloning, branch = this.core) {
825
- return this.cloned(branch, raw);
814
+ snapshot(raw = !this.config.smartCloning, branch) {
815
+ return this.cloned(arguments.length < 2 ? this.core : branch, raw);
826
816
  }
827
817
  /**
828
818
  * Cascades object updates into direct child paths.
@@ -873,11 +863,11 @@ var Reactor = class {
873
863
  }
874
864
  };
875
865
 
876
- // src/core/mixins.ts
877
- var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "cascade", "snapshot", "reset", "destroy"];
866
+ // src/ts/core/mixins.ts
867
+ var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "snapshot", "cascade", "plugIn", "reset", "destroy"];
878
868
  function reactive(target, build, preferences = NIL) {
879
869
  if ("__Reactor__" in target) return target;
880
- const descriptors = {}, rtr = target instanceof Reactor ? target : new Reactor(target, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
870
+ const descriptors = {}, rtr = getReactor(target, true, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
881
871
  for (let i = 0, len = methods.length; i < len; i++) {
882
872
  let key = methods[i];
883
873
  if (hasAffix) (preferences.whitelist?.includes(key) ?? true) && (key = `${preferences.prefix || ""}${key}${preferences.suffix || ""}`);
@@ -887,8 +877,11 @@ function reactive(target, build, preferences = NIL) {
887
877
  descriptors["__Reactor__"] = { value: rtr, ...locks };
888
878
  return Object.defineProperties(rtr.core, descriptors), rtr.core;
889
879
  }
880
+ function getReactor(target, create = false, build) {
881
+ return (target instanceof Reactor ? target : target.__Reactor__) || (create ? new Reactor(target, build) : void 0);
882
+ }
890
883
 
891
- // src/utils/methd.ts
884
+ // src/ts/utils/methd.ts
892
885
  function onAllMethods(owner, callback, skipOwn = true, nested = false) {
893
886
  let proto = owner;
894
887
  while (proto && proto !== Object.prototype) {
@@ -916,7 +909,7 @@ function guardMethod(fn, onError = (e) => console.error(e)) {
916
909
  });
917
910
  }
918
911
 
919
- // src/plugins/base.ts
912
+ // src/ts/plugins/base.ts
920
913
  var BaseReactorPlugin = class {
921
914
  static plugName;
922
915
  get name() {
@@ -954,7 +947,7 @@ var BaseReactorPlugin = class {
954
947
  // `()=>{}`: needs to be bounded even before initialization
955
948
  };
956
949
 
957
- // src/utils/store.ts
950
+ // src/ts/utils/store.ts
958
951
  var BaseStorageAdapter = class {
959
952
  static name;
960
953
  config;
@@ -1088,7 +1081,7 @@ var IndexedDBAdapter = class extends AsyncStorageAdapter {
1088
1081
  };
1089
1082
  var INDEXED_DB_ADAPTER_BUILD = { dbName: "REACTOR_IDB", stores: ["VAULT"], version: 1, onidb: NOOP, onupgradeneeded: NOOP, onversionchange: NOOP, onsuccess: NOOP, onerror: NOOP, onblocked: NOOP };
1090
1083
 
1091
- // src/utils/fn.ts
1084
+ // src/ts/utils/fn.ts
1092
1085
  function setTimeout2(handler, timeout, ...args) {
1093
1086
  const sig = args[0] instanceof AbortSignal ? args.shift() : void 0;
1094
1087
  if (sig?.aborted) return -1;
@@ -1098,7 +1091,7 @@ function setTimeout2(handler, timeout, ...args) {
1098
1091
  return sig.addEventListener("abort", kill, { once: true }), id;
1099
1092
  }
1100
1093
 
1101
- // src/plugins/persist.ts
1094
+ // src/ts/plugins/persist.ts
1102
1095
  var PersistPlugin = class extends BaseReactorPlugin {
1103
1096
  static plugName = "persist";
1104
1097
  adapter;
@@ -1151,17 +1144,18 @@ var PersistPlugin = class extends BaseReactorPlugin {
1151
1144
  };
1152
1145
  var PERSIST_PLUGIN_BUILD = { disabled: false, key: "REACTOR_STORE", throttle: 2500, useSnapshot: false };
1153
1146
 
1154
- // src/utils/num.ts
1147
+ // src/ts/utils/num.ts
1155
1148
  function clamp(min = 0, val, max = Infinity) {
1156
1149
  return Math.min(Math.max(val, min), max);
1157
1150
  }
1158
1151
 
1159
- // src/plugins/timeTravel.ts
1152
+ // src/ts/plugins/timeTravel.ts
1160
1153
  var TimeTravelPlugin = class extends BaseReactorPlugin {
1161
1154
  static plugName = "timeTravel";
1155
+ lastTimestamp = 0;
1162
1156
  playbackTimeoutId = -1;
1163
1157
  constructor(config, rtr) {
1164
- super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { history: [], initialState: null, currentFrame: 0, paused: true });
1158
+ super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { initialState: null, history: [], currentFrame: 0, paused: true });
1165
1159
  }
1166
1160
  // ===========================================================================
1167
1161
  // THE FOUNDATION & WIRETAP (Passive Recording)
@@ -1169,6 +1163,7 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1169
1163
  wire() {
1170
1164
  this.rtr.config.referenceTracking = this.rtr.config.smartCloning = this.rtr.config.eventTimeStamps = true;
1171
1165
  if (!this.state.history.length || this.state.initialState == null) this.state.initialState = this.rtr.snapshot();
1166
+ this.lastTimestamp = performance.now();
1172
1167
  this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
1173
1168
  this.config.on("paths", this.handlePathsState, { signal: this.signal, immediate: true });
1174
1169
  !this.state.paused && this.play();
@@ -1182,16 +1177,17 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1182
1177
  if (!this.state.paused) return;
1183
1178
  if (this.state.currentFrame < this.state.history.length) this.state.history = this.state.history.slice(0, this.state.currentFrame);
1184
1179
  if (this.state.history.length >= this.config.maxHistoryLength) this.state.history = this.state.history.slice(1);
1185
- this.state.history.push({ timestamp: e.timestamp ?? performance.now(), path: e.target.path, type: e.staticType, value: this.rtr.snapshot(false, e.target.value), oldValue: this.rtr.snapshot(false, e.target.oldValue), keyExisted: e.target.keyExisted, rejected: e.rejected });
1180
+ this.state.history.push({ path: e.target.path, value: this.rtr.snapshot(false, e.target.value), oldValue: this.rtr.snapshot(false, e.target.oldValue), type: e.staticType, rejected: e.rejected, timedelta: e.timestamp - this.lastTimestamp, hadKey: e.target.hadKey });
1186
1181
  this.state.currentFrame = this.state.history.length;
1182
+ this.lastTimestamp = e.timestamp;
1187
1183
  }
1188
1184
  /** Clears timeline history and resets playhead/genesis to the current reactor state. */
1189
1185
  clear() {
1190
1186
  this.pause();
1191
1187
  this.playbackTimeoutId = -1;
1192
- this.state.history = [];
1193
- this.state.currentFrame = 0;
1188
+ this.state.history.length = this.state.currentFrame = 0;
1194
1189
  this.state.initialState = this.rtr.snapshot();
1190
+ this.lastTimestamp = performance.now();
1195
1191
  }
1196
1192
  // ===========================================================================
1197
1193
  // THE TIME MACHINE (Manual Controls)
@@ -1204,7 +1200,7 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1204
1200
  const e = this.state.history[forward ? this.state.currentFrame : this.state.currentFrame - 1];
1205
1201
  if (!e) break;
1206
1202
  if (forward) e.type === "delete" ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.value, this.rtr.config));
1207
- else !e.keyExisted ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.oldValue, this.rtr.config));
1203
+ else !e.hadKey ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.oldValue, this.rtr.config));
1208
1204
  forward ? this.state.currentFrame++ : this.state.currentFrame--;
1209
1205
  if (e.rejected) this.rtr.log(`[Reactor ${this.name} Plug] ${forward ? "Replaying" : "Reversing"} REJECTED intent at "${e.path}"`);
1210
1206
  }
@@ -1227,9 +1223,9 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1227
1223
  async automove(forward = true) {
1228
1224
  this.state.paused = false;
1229
1225
  while ((forward ? this.state.currentFrame < this.state.history.length : this.state.currentFrame > 0) && !this.state.paused) {
1230
- const currIndex = forward ? this.state.currentFrame : this.state.currentFrame - 1, e = this.state.history[currIndex], nextE = this.state.history[forward ? currIndex + 1 : currIndex - 1], delay = nextE && e ? Math.abs(nextE.timestamp - e.timestamp) : 0;
1226
+ const currIndex = forward ? this.state.currentFrame : this.state.currentFrame - 1, e = this.state.history[forward ? currIndex + 1 : currIndex - 1];
1231
1227
  this.jumpTo(this.state.currentFrame + (forward ? 1 : -1), true);
1232
- if (delay > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), clamp(0, delay, this.config.maxPlaybackDelay), this.signal));
1228
+ if (e?.timedelta > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), Math.min(e.timedelta, this.config.maxPlaybackDelay), this.signal));
1233
1229
  }
1234
1230
  this.state.paused = true;
1235
1231
  }
@@ -1243,21 +1239,24 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1243
1239
  // TELEMETRY & I/O (Session Import/Export)
1244
1240
  // ===========================================================================
1245
1241
  /** Exports the current session as a JSON string. */
1246
- export() {
1247
- return JSON.stringify(this.state);
1242
+ export(replacer, space) {
1243
+ try {
1244
+ return JSON.stringify(this.state, replacer, space);
1245
+ } catch (e) {
1246
+ return this.rtr.log(`[Reactor ${this.name} Plug] Failed to export session`), "";
1247
+ }
1248
1248
  }
1249
1249
  /** Imports a session from a JSON string, allowing you to replay or analyze past states. */
1250
1250
  import(json) {
1251
1251
  try {
1252
1252
  setAny(this.state, "*", JSON.parse(json));
1253
+ this.lastTimestamp = performance.now();
1253
1254
  const resume = !this.state.paused, target = this.state.currentFrame;
1254
1255
  this.state.paused = false;
1255
- setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config));
1256
- this.rtr.tick();
1257
- this.state.currentFrame = 0;
1258
- this.jumpTo(target), resume && this.play();
1256
+ setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config)), this.rtr.tick();
1257
+ this.state.currentFrame = 0, this.jumpTo(target), resume && this.play();
1259
1258
  } catch (e) {
1260
- this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`, "error");
1259
+ this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`);
1261
1260
  }
1262
1261
  }
1263
1262
  };
@@ -1,5 +1,6 @@
1
- import { P as Paths, I as Inert, B as BaseReactorPlugin, R as Reactor, a as REvent } from './index-C2hyIh0K.cjs';
2
- export { b as ReactorPluginConstructor } from './index-C2hyIh0K.cjs';
1
+ import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-Oie9hhE8.cjs';
2
+ export { c as ReactorPluginConstructor } from './index-Oie9hhE8.cjs';
3
+ export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-WpgWmKu-.cjs';
3
4
 
4
5
  interface StorageAdapterConfig {
5
6
  debug: boolean;
@@ -108,76 +109,4 @@ declare class PersistPlugin<T extends object = any> extends BaseReactorPlugin<T,
108
109
  }
109
110
  declare const PERSIST_PLUGIN_BUILD: Partial<PersistConfig<any>>;
110
111
 
111
- /** The DNA of a specific moment in time, Records the 'Desire' (Intent) or the 'Fact' (State). */
112
- interface HistoryEntry {
113
- /** Was it a 'set' or a 'delete' surgery? */
114
- type: REvent<any, any>["staticType"];
115
- /** The surgical address in the Reactor */
116
- path: string;
117
- /** The data payload at that moment */
118
- value: any;
119
- /** The "Undo" antidote (Previous value), if applicable */
120
- oldValue: any;
121
- /** Did the key for the value exist on its parent object? */
122
- keyExisted: boolean;
123
- /** Did the Power Line disapprove?; why? */
124
- rejected: string;
125
- /** For chronological re-enactment */
126
- timestamp: number;
127
- }
128
- interface TimeTravelConfig<T extends object = any> {
129
- /** Specific paths only, no "*"; instead don't pass anything */
130
- paths?: Paths<T>[];
131
- /** Maximum number of history entries to keep (Memory Cap), you lose replaying Sessions or the Genesis */
132
- maxHistoryLength: number;
133
- /** Max delay between events during playback (ms) */
134
- maxPlaybackDelay: number;
135
- }
136
- interface TimeTravelState {
137
- /** The "Timeline" of mutations (Chronological Log) */
138
- history: HistoryEntry[];
139
- /** The "Genesis" snapshot (Raw Data) */
140
- initialState: any;
141
- /** The manual playhead (Index in the Timeline) */
142
- currentFrame: number;
143
- /** Whether playback is currently paused (Automatic Replay) */
144
- paused: boolean;
145
- }
146
- /**
147
- * The Flight Recorder (Black Box).
148
- * - Implements S.I.A. logic to allow playback, teleportation, redos and undos.
149
- */
150
- declare class TimeTravelPlugin<T extends object = any> extends BaseReactorPlugin<T, TimeTravelConfig<T>, TimeTravelState> {
151
- static readonly plugName = "timeTravel";
152
- protected playbackTimeoutId: number;
153
- constructor(config?: Partial<TimeTravelConfig<T>>, rtr?: Reactor<T>);
154
- wire(): void;
155
- protected handlePathsState({ value: paths, oldValue: prevs }: REvent<TimeTravelConfig<T>, "paths">): void;
156
- /** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
157
- protected record(e: REvent<T, any>): void;
158
- /** Clears timeline history and resets playhead/genesis to the current reactor state. */
159
- clear(): void;
160
- /** Instant state reconstruction (Teleport). Glides through deltas natively. */
161
- jumpTo(index?: number, keepShield?: boolean): void;
162
- /** Step through time, Moves the playhead and teleports the state. */
163
- step(stride?: number, forward?: boolean): void;
164
- /** Step back in time, Moves the playhead backward and teleports the state. */
165
- undo: () => void;
166
- /** Step forward in time, Restores previously undone actions. */
167
- redo: () => void;
168
- /** Core automove engine. Replays or rewinds the "Story" by respecting time gaps. */
169
- automove(forward?: boolean): Promise<void>;
170
- /** Start chronological re-enactment of the session. */
171
- play: () => Promise<void>;
172
- /** Start reverse chronological re-enactment of the session. */
173
- rewind: () => Promise<void>;
174
- /** Pauses the live VCR playback. */
175
- pause: () => void;
176
- /** Exports the current session as a JSON string. */
177
- export(): string;
178
- /** Imports a session from a JSON string, allowing you to replay or analyze past states. */
179
- import(json: string): void;
180
- }
181
- declare const TIME_TRAVEL_PLUGIN_BUILD: Partial<TimeTravelConfig>;
182
-
183
- export { type AsyncStorageAdapterConstructor, BaseReactorPlugin, BaseStorageAdapter, type HistoryEntry, INDEXED_DB_ADAPTER_BUILD, IndexedDBAdapter, type IndexedDBAdapterConfig, LocalStorageAdapter, MemoryStorageAdapter, type MemoryStorageAdapterConfig, PERSIST_PLUGIN_BUILD, type PersistConfig, PersistPlugin, StorageAdapter, type StorageAdapterConfig, type StorageAdapterConstructor, TIME_TRAVEL_PLUGIN_BUILD, type TimeTravelConfig, TimeTravelPlugin, type TimeTravelState };
112
+ export { type AsyncStorageAdapterConstructor, BaseReactorPlugin, BaseStorageAdapter, INDEXED_DB_ADAPTER_BUILD, IndexedDBAdapter, type IndexedDBAdapterConfig, LocalStorageAdapter, MemoryStorageAdapter, type MemoryStorageAdapterConfig, PERSIST_PLUGIN_BUILD, type PersistConfig, PersistPlugin, StorageAdapter, type StorageAdapterConfig, type StorageAdapterConstructor };
package/dist/plugins.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { P as Paths, I as Inert, B as BaseReactorPlugin, R as Reactor, a as REvent } from './index-C2hyIh0K.js';
2
- export { b as ReactorPluginConstructor } from './index-C2hyIh0K.js';
1
+ import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-Oie9hhE8.js';
2
+ export { c as ReactorPluginConstructor } from './index-Oie9hhE8.js';
3
+ export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-B1vedDQc.js';
3
4
 
4
5
  interface StorageAdapterConfig {
5
6
  debug: boolean;
@@ -108,76 +109,4 @@ declare class PersistPlugin<T extends object = any> extends BaseReactorPlugin<T,
108
109
  }
109
110
  declare const PERSIST_PLUGIN_BUILD: Partial<PersistConfig<any>>;
110
111
 
111
- /** The DNA of a specific moment in time, Records the 'Desire' (Intent) or the 'Fact' (State). */
112
- interface HistoryEntry {
113
- /** Was it a 'set' or a 'delete' surgery? */
114
- type: REvent<any, any>["staticType"];
115
- /** The surgical address in the Reactor */
116
- path: string;
117
- /** The data payload at that moment */
118
- value: any;
119
- /** The "Undo" antidote (Previous value), if applicable */
120
- oldValue: any;
121
- /** Did the key for the value exist on its parent object? */
122
- keyExisted: boolean;
123
- /** Did the Power Line disapprove?; why? */
124
- rejected: string;
125
- /** For chronological re-enactment */
126
- timestamp: number;
127
- }
128
- interface TimeTravelConfig<T extends object = any> {
129
- /** Specific paths only, no "*"; instead don't pass anything */
130
- paths?: Paths<T>[];
131
- /** Maximum number of history entries to keep (Memory Cap), you lose replaying Sessions or the Genesis */
132
- maxHistoryLength: number;
133
- /** Max delay between events during playback (ms) */
134
- maxPlaybackDelay: number;
135
- }
136
- interface TimeTravelState {
137
- /** The "Timeline" of mutations (Chronological Log) */
138
- history: HistoryEntry[];
139
- /** The "Genesis" snapshot (Raw Data) */
140
- initialState: any;
141
- /** The manual playhead (Index in the Timeline) */
142
- currentFrame: number;
143
- /** Whether playback is currently paused (Automatic Replay) */
144
- paused: boolean;
145
- }
146
- /**
147
- * The Flight Recorder (Black Box).
148
- * - Implements S.I.A. logic to allow playback, teleportation, redos and undos.
149
- */
150
- declare class TimeTravelPlugin<T extends object = any> extends BaseReactorPlugin<T, TimeTravelConfig<T>, TimeTravelState> {
151
- static readonly plugName = "timeTravel";
152
- protected playbackTimeoutId: number;
153
- constructor(config?: Partial<TimeTravelConfig<T>>, rtr?: Reactor<T>);
154
- wire(): void;
155
- protected handlePathsState({ value: paths, oldValue: prevs }: REvent<TimeTravelConfig<T>, "paths">): void;
156
- /** Chronicling the lifecycle of the system, Captures the essence of every mutation wave that bubbles up. */
157
- protected record(e: REvent<T, any>): void;
158
- /** Clears timeline history and resets playhead/genesis to the current reactor state. */
159
- clear(): void;
160
- /** Instant state reconstruction (Teleport). Glides through deltas natively. */
161
- jumpTo(index?: number, keepShield?: boolean): void;
162
- /** Step through time, Moves the playhead and teleports the state. */
163
- step(stride?: number, forward?: boolean): void;
164
- /** Step back in time, Moves the playhead backward and teleports the state. */
165
- undo: () => void;
166
- /** Step forward in time, Restores previously undone actions. */
167
- redo: () => void;
168
- /** Core automove engine. Replays or rewinds the "Story" by respecting time gaps. */
169
- automove(forward?: boolean): Promise<void>;
170
- /** Start chronological re-enactment of the session. */
171
- play: () => Promise<void>;
172
- /** Start reverse chronological re-enactment of the session. */
173
- rewind: () => Promise<void>;
174
- /** Pauses the live VCR playback. */
175
- pause: () => void;
176
- /** Exports the current session as a JSON string. */
177
- export(): string;
178
- /** Imports a session from a JSON string, allowing you to replay or analyze past states. */
179
- import(json: string): void;
180
- }
181
- declare const TIME_TRAVEL_PLUGIN_BUILD: Partial<TimeTravelConfig>;
182
-
183
- export { type AsyncStorageAdapterConstructor, BaseReactorPlugin, BaseStorageAdapter, type HistoryEntry, INDEXED_DB_ADAPTER_BUILD, IndexedDBAdapter, type IndexedDBAdapterConfig, LocalStorageAdapter, MemoryStorageAdapter, type MemoryStorageAdapterConfig, PERSIST_PLUGIN_BUILD, type PersistConfig, PersistPlugin, StorageAdapter, type StorageAdapterConfig, type StorageAdapterConstructor, TIME_TRAVEL_PLUGIN_BUILD, type TimeTravelConfig, TimeTravelPlugin, type TimeTravelState };
112
+ export { type AsyncStorageAdapterConstructor, BaseReactorPlugin, BaseStorageAdapter, INDEXED_DB_ADAPTER_BUILD, IndexedDBAdapter, type IndexedDBAdapterConfig, LocalStorageAdapter, MemoryStorageAdapter, type MemoryStorageAdapterConfig, PERSIST_PLUGIN_BUILD, type PersistConfig, PersistPlugin, StorageAdapter, type StorageAdapterConfig, type StorageAdapterConstructor };