@legendapp/state 3.0.0-beta.29 → 3.0.0-beta.30

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/index.d.mts CHANGED
@@ -391,6 +391,23 @@ interface ObservablePrimitiveState {
391
391
  }
392
392
  declare function ObservablePrimitiveClass<T>(this: ObservablePrimitive<T> & ObservablePrimitiveState, node: NodeInfo): void;
393
393
 
394
+ type MiddlewareEventType = 'listener-added' | 'listener-removed' | 'listeners-cleared';
395
+ interface MiddlewareEvent {
396
+ type: MiddlewareEventType;
397
+ node: NodeInfo;
398
+ listener?: NodeListener;
399
+ timestamp: number;
400
+ }
401
+ type MiddlewareHandler = (event: MiddlewareEvent) => void;
402
+ /**
403
+ * Register a middleware handler for a specific node and event type
404
+ * @param node The node to register the middleware handler for
405
+ * @param type The event type to handle
406
+ * @param handler The middleware handler function
407
+ * @returns A function to remove the handler
408
+ */
409
+ declare function registerMiddleware(node: NodeInfo, type: MiddlewareEventType, handler: MiddlewareHandler): () => void;
410
+
394
411
  declare const internal: {
395
412
  createPreviousHandler: typeof createPreviousHandler;
396
413
  clone: typeof clone;
@@ -425,6 +442,7 @@ declare const internal: {
425
442
  observableFns: Map<string, (node: NodeInfo, ...args: any[]) => any>;
426
443
  optimized: symbol;
427
444
  peek: typeof peek;
445
+ registerMiddleware: typeof registerMiddleware;
428
446
  safeParse: typeof safeParse;
429
447
  safeStringify: typeof safeStringify;
430
448
  set: typeof set;
package/index.d.ts CHANGED
@@ -391,6 +391,23 @@ interface ObservablePrimitiveState {
391
391
  }
392
392
  declare function ObservablePrimitiveClass<T>(this: ObservablePrimitive<T> & ObservablePrimitiveState, node: NodeInfo): void;
393
393
 
394
+ type MiddlewareEventType = 'listener-added' | 'listener-removed' | 'listeners-cleared';
395
+ interface MiddlewareEvent {
396
+ type: MiddlewareEventType;
397
+ node: NodeInfo;
398
+ listener?: NodeListener;
399
+ timestamp: number;
400
+ }
401
+ type MiddlewareHandler = (event: MiddlewareEvent) => void;
402
+ /**
403
+ * Register a middleware handler for a specific node and event type
404
+ * @param node The node to register the middleware handler for
405
+ * @param type The event type to handle
406
+ * @param handler The middleware handler function
407
+ * @returns A function to remove the handler
408
+ */
409
+ declare function registerMiddleware(node: NodeInfo, type: MiddlewareEventType, handler: MiddlewareHandler): () => void;
410
+
394
411
  declare const internal: {
395
412
  createPreviousHandler: typeof createPreviousHandler;
396
413
  clone: typeof clone;
@@ -425,6 +442,7 @@ declare const internal: {
425
442
  observableFns: Map<string, (node: NodeInfo, ...args: any[]) => any>;
426
443
  optimized: symbol;
427
444
  peek: typeof peek;
445
+ registerMiddleware: typeof registerMiddleware;
428
446
  safeParse: typeof safeParse;
429
447
  safeStringify: typeof safeStringify;
430
448
  set: typeof set;
package/index.js CHANGED
@@ -818,6 +818,109 @@ function linked(params, options) {
818
818
  return ret;
819
819
  }
820
820
 
821
+ // src/middleware.ts
822
+ var nodeMiddlewareHandlers = /* @__PURE__ */ new WeakMap();
823
+ var queuedNodes = [];
824
+ var queuedListeners = [];
825
+ var queuedTypes = [];
826
+ var queueSize = 0;
827
+ var isMicrotaskScheduled = false;
828
+ function registerMiddleware(node, type, handler) {
829
+ let handlersMap = nodeMiddlewareHandlers.get(node);
830
+ if (!handlersMap) {
831
+ handlersMap = /* @__PURE__ */ new Map();
832
+ nodeMiddlewareHandlers.set(node, handlersMap);
833
+ }
834
+ let handlers = handlersMap.get(type);
835
+ if (!handlers) {
836
+ handlers = /* @__PURE__ */ new Set();
837
+ handlersMap.set(type, handlers);
838
+ }
839
+ handlers.add(handler);
840
+ return () => {
841
+ const handlersMap2 = nodeMiddlewareHandlers.get(node);
842
+ if (!handlersMap2)
843
+ return;
844
+ const handlers2 = handlersMap2.get(type);
845
+ if (!handlers2)
846
+ return;
847
+ handlers2.delete(handler);
848
+ if (handlers2.size === 0) {
849
+ handlersMap2.delete(type);
850
+ if (handlersMap2.size === 0) {
851
+ nodeMiddlewareHandlers.delete(node);
852
+ }
853
+ }
854
+ };
855
+ }
856
+ function dispatchMiddlewareEvent(node, listener, type) {
857
+ const handlersMap = nodeMiddlewareHandlers.get(node);
858
+ if (!handlersMap || !handlersMap.has(type)) {
859
+ return;
860
+ }
861
+ const handlers = handlersMap.get(type);
862
+ if (!handlers || handlers.size === 0) {
863
+ return;
864
+ }
865
+ queuedNodes[queueSize] = node;
866
+ queuedListeners[queueSize] = listener;
867
+ queuedTypes[queueSize] = type;
868
+ queueSize++;
869
+ if (!isMicrotaskScheduled) {
870
+ isMicrotaskScheduled = true;
871
+ queueMicrotask(processQueuedEvents);
872
+ }
873
+ }
874
+ var eventObj = {
875
+ type: "listener-added",
876
+ node: null,
877
+ listener: void 0,
878
+ timestamp: 0
879
+ };
880
+ function processQueuedEvents() {
881
+ isMicrotaskScheduled = false;
882
+ const timestamp = typeof performance !== "undefined" ? performance.now() : Date.now();
883
+ eventObj.timestamp = timestamp;
884
+ for (let i = 0; i < queueSize; i++) {
885
+ const node = queuedNodes[i];
886
+ const listener = queuedListeners[i];
887
+ const type = queuedTypes[i];
888
+ const handlersMap = nodeMiddlewareHandlers.get(node);
889
+ if (!handlersMap)
890
+ continue;
891
+ const handlers = handlersMap.get(type);
892
+ if (!handlers || handlers.size === 0)
893
+ continue;
894
+ const nodeListeners = node.listeners;
895
+ const nodeListenersImmediate = node.listenersImmediate;
896
+ if (!nodeListeners && !nodeListenersImmediate) {
897
+ continue;
898
+ }
899
+ let isValid = false;
900
+ if (type === "listener-added") {
901
+ isValid = !!(nodeListeners == null ? void 0 : nodeListeners.has(listener)) || !!(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.has(listener));
902
+ } else if (type === "listener-removed") {
903
+ isValid = !(nodeListeners == null ? void 0 : nodeListeners.has(listener)) && !(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.has(listener));
904
+ } else {
905
+ isValid = !(nodeListeners == null ? void 0 : nodeListeners.size) && !(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.size);
906
+ }
907
+ if (isValid) {
908
+ eventObj.type = type;
909
+ eventObj.node = node;
910
+ eventObj.listener = listener;
911
+ const iterableHandlers = Array.from(handlers);
912
+ for (let j = 0; j < iterableHandlers.length; j++) {
913
+ try {
914
+ iterableHandlers[j](eventObj);
915
+ } catch (error) {
916
+ console.error(`Error in middleware handler for ${type}:`, error);
917
+ }
918
+ }
919
+ }
920
+ }
921
+ queueSize = 0;
922
+ }
923
+
821
924
  // src/onChange.ts
822
925
  function onChange(node, callback, options = {}, fromLinks) {
823
926
  var _a;
@@ -888,6 +991,7 @@ function onChange(node, callback, options = {}, fromLinks) {
888
991
  pathParent = [parent.key, ...pathParent];
889
992
  parent = parent.parent;
890
993
  }
994
+ dispatchMiddlewareEvent(node, listener, "listener-added");
891
995
  return () => {
892
996
  listeners.delete(listener);
893
997
  extraDisposes == null ? void 0 : extraDisposes.forEach((fn) => fn());
@@ -896,6 +1000,10 @@ function onChange(node, callback, options = {}, fromLinks) {
896
1000
  parent2.numListenersRecursive--;
897
1001
  parent2 = parent2.parent;
898
1002
  }
1003
+ dispatchMiddlewareEvent(node, listener, "listener-removed");
1004
+ if (listeners.size === 0) {
1005
+ dispatchMiddlewareEvent(node, void 0, "listeners-cleared");
1006
+ }
899
1007
  };
900
1008
  }
901
1009
  function createCb(linkedFromNode, path, callback) {
@@ -2005,6 +2113,9 @@ function activateNodeFunction(node, lazyFn) {
2005
2113
  value = (_d = (_c = activated2.get) == null ? void 0 : _c.call(activated2)) != null ? _d : activated2.initial;
2006
2114
  }
2007
2115
  }
2116
+ if (ignoreThisUpdate) {
2117
+ activatedValue = value;
2118
+ }
2008
2119
  wasPromise = wasPromise || isPromise(value);
2009
2120
  return value;
2010
2121
  },
@@ -2354,6 +2465,7 @@ var internal = {
2354
2465
  observableFns,
2355
2466
  optimized,
2356
2467
  peek,
2468
+ registerMiddleware,
2357
2469
  safeParse,
2358
2470
  safeStringify,
2359
2471
  set,
package/index.mjs CHANGED
@@ -816,6 +816,109 @@ function linked(params, options) {
816
816
  return ret;
817
817
  }
818
818
 
819
+ // src/middleware.ts
820
+ var nodeMiddlewareHandlers = /* @__PURE__ */ new WeakMap();
821
+ var queuedNodes = [];
822
+ var queuedListeners = [];
823
+ var queuedTypes = [];
824
+ var queueSize = 0;
825
+ var isMicrotaskScheduled = false;
826
+ function registerMiddleware(node, type, handler) {
827
+ let handlersMap = nodeMiddlewareHandlers.get(node);
828
+ if (!handlersMap) {
829
+ handlersMap = /* @__PURE__ */ new Map();
830
+ nodeMiddlewareHandlers.set(node, handlersMap);
831
+ }
832
+ let handlers = handlersMap.get(type);
833
+ if (!handlers) {
834
+ handlers = /* @__PURE__ */ new Set();
835
+ handlersMap.set(type, handlers);
836
+ }
837
+ handlers.add(handler);
838
+ return () => {
839
+ const handlersMap2 = nodeMiddlewareHandlers.get(node);
840
+ if (!handlersMap2)
841
+ return;
842
+ const handlers2 = handlersMap2.get(type);
843
+ if (!handlers2)
844
+ return;
845
+ handlers2.delete(handler);
846
+ if (handlers2.size === 0) {
847
+ handlersMap2.delete(type);
848
+ if (handlersMap2.size === 0) {
849
+ nodeMiddlewareHandlers.delete(node);
850
+ }
851
+ }
852
+ };
853
+ }
854
+ function dispatchMiddlewareEvent(node, listener, type) {
855
+ const handlersMap = nodeMiddlewareHandlers.get(node);
856
+ if (!handlersMap || !handlersMap.has(type)) {
857
+ return;
858
+ }
859
+ const handlers = handlersMap.get(type);
860
+ if (!handlers || handlers.size === 0) {
861
+ return;
862
+ }
863
+ queuedNodes[queueSize] = node;
864
+ queuedListeners[queueSize] = listener;
865
+ queuedTypes[queueSize] = type;
866
+ queueSize++;
867
+ if (!isMicrotaskScheduled) {
868
+ isMicrotaskScheduled = true;
869
+ queueMicrotask(processQueuedEvents);
870
+ }
871
+ }
872
+ var eventObj = {
873
+ type: "listener-added",
874
+ node: null,
875
+ listener: void 0,
876
+ timestamp: 0
877
+ };
878
+ function processQueuedEvents() {
879
+ isMicrotaskScheduled = false;
880
+ const timestamp = typeof performance !== "undefined" ? performance.now() : Date.now();
881
+ eventObj.timestamp = timestamp;
882
+ for (let i = 0; i < queueSize; i++) {
883
+ const node = queuedNodes[i];
884
+ const listener = queuedListeners[i];
885
+ const type = queuedTypes[i];
886
+ const handlersMap = nodeMiddlewareHandlers.get(node);
887
+ if (!handlersMap)
888
+ continue;
889
+ const handlers = handlersMap.get(type);
890
+ if (!handlers || handlers.size === 0)
891
+ continue;
892
+ const nodeListeners = node.listeners;
893
+ const nodeListenersImmediate = node.listenersImmediate;
894
+ if (!nodeListeners && !nodeListenersImmediate) {
895
+ continue;
896
+ }
897
+ let isValid = false;
898
+ if (type === "listener-added") {
899
+ isValid = !!(nodeListeners == null ? void 0 : nodeListeners.has(listener)) || !!(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.has(listener));
900
+ } else if (type === "listener-removed") {
901
+ isValid = !(nodeListeners == null ? void 0 : nodeListeners.has(listener)) && !(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.has(listener));
902
+ } else {
903
+ isValid = !(nodeListeners == null ? void 0 : nodeListeners.size) && !(nodeListenersImmediate == null ? void 0 : nodeListenersImmediate.size);
904
+ }
905
+ if (isValid) {
906
+ eventObj.type = type;
907
+ eventObj.node = node;
908
+ eventObj.listener = listener;
909
+ const iterableHandlers = Array.from(handlers);
910
+ for (let j = 0; j < iterableHandlers.length; j++) {
911
+ try {
912
+ iterableHandlers[j](eventObj);
913
+ } catch (error) {
914
+ console.error(`Error in middleware handler for ${type}:`, error);
915
+ }
916
+ }
917
+ }
918
+ }
919
+ queueSize = 0;
920
+ }
921
+
819
922
  // src/onChange.ts
820
923
  function onChange(node, callback, options = {}, fromLinks) {
821
924
  var _a;
@@ -886,6 +989,7 @@ function onChange(node, callback, options = {}, fromLinks) {
886
989
  pathParent = [parent.key, ...pathParent];
887
990
  parent = parent.parent;
888
991
  }
992
+ dispatchMiddlewareEvent(node, listener, "listener-added");
889
993
  return () => {
890
994
  listeners.delete(listener);
891
995
  extraDisposes == null ? void 0 : extraDisposes.forEach((fn) => fn());
@@ -894,6 +998,10 @@ function onChange(node, callback, options = {}, fromLinks) {
894
998
  parent2.numListenersRecursive--;
895
999
  parent2 = parent2.parent;
896
1000
  }
1001
+ dispatchMiddlewareEvent(node, listener, "listener-removed");
1002
+ if (listeners.size === 0) {
1003
+ dispatchMiddlewareEvent(node, void 0, "listeners-cleared");
1004
+ }
897
1005
  };
898
1006
  }
899
1007
  function createCb(linkedFromNode, path, callback) {
@@ -2003,6 +2111,9 @@ function activateNodeFunction(node, lazyFn) {
2003
2111
  value = (_d = (_c = activated2.get) == null ? void 0 : _c.call(activated2)) != null ? _d : activated2.initial;
2004
2112
  }
2005
2113
  }
2114
+ if (ignoreThisUpdate) {
2115
+ activatedValue = value;
2116
+ }
2006
2117
  wasPromise = wasPromise || isPromise(value);
2007
2118
  return value;
2008
2119
  },
@@ -2352,6 +2463,7 @@ var internal = {
2352
2463
  observableFns,
2353
2464
  optimized,
2354
2465
  peek,
2466
+ registerMiddleware,
2355
2467
  safeParse,
2356
2468
  safeStringify,
2357
2469
  set,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/state",
3
- "version": "3.0.0-beta.29",
3
+ "version": "3.0.0-beta.30",
4
4
  "description": "legend-state",
5
5
  "sideEffects": false,
6
6
  "private": false,
package/sync.js CHANGED
@@ -234,7 +234,17 @@ function createRevertChanges(obs$, changes) {
234
234
  }
235
235
 
236
236
  // src/sync/syncObservable.ts
237
- var { clone: clone2, deepMerge, getNode, getNodeValue, getValueAtPath, globalState, symbolLinked, createPreviousHandler } = state.internal;
237
+ var {
238
+ clone: clone2,
239
+ createPreviousHandler,
240
+ deepMerge,
241
+ getNode,
242
+ getNodeValue,
243
+ getValueAtPath,
244
+ globalState,
245
+ registerMiddleware,
246
+ symbolLinked
247
+ } = state.internal;
238
248
  var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
239
249
  var allSyncStates = /* @__PURE__ */ new Map();
240
250
  var metadatas = /* @__PURE__ */ new WeakMap();
@@ -937,236 +947,237 @@ function syncObservable(obs$, syncOptionsOrSynced) {
937
947
  }
938
948
  const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
939
949
  const pending = localState.pendingChanges;
940
- if (get || subscribe) {
941
- const { waitFor } = syncOptions;
942
- const runGet = () => {
943
- var _a2;
944
- const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
945
- mode = mode || syncOptions.mode || "set";
946
- if (value !== void 0) {
947
- value = transformLoadData(value, syncOptions, true, "get");
948
- if (state.isPromise(value)) {
949
- value = await value;
950
- }
951
- const pending2 = localState.pendingChanges;
952
- const currentValue = obs$.peek();
953
- if (pending2) {
954
- let didChangeMetadata = false;
955
- Object.keys(pending2).forEach((key) => {
956
- const p = key.split("/").filter((k) => k !== "");
957
- const { v, t } = pending2[key];
958
- if (t.length === 0 || !value) {
950
+ const { waitFor } = syncOptions;
951
+ const runGet = () => {
952
+ var _a2;
953
+ const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
954
+ mode = mode || syncOptions.mode || "set";
955
+ if (value !== void 0) {
956
+ value = transformLoadData(value, syncOptions, true, "get");
957
+ if (state.isPromise(value)) {
958
+ value = await value;
959
+ }
960
+ const pending2 = localState.pendingChanges;
961
+ const currentValue = obs$.peek();
962
+ if (pending2) {
963
+ let didChangeMetadata = false;
964
+ Object.keys(pending2).forEach((key) => {
965
+ const p = key.split("/").filter((k) => k !== "");
966
+ const { v, t } = pending2[key];
967
+ if (t.length === 0 || !value) {
968
+ const oldValue = clone2(value);
969
+ pending2[key].p = key ? oldValue[key] : oldValue;
970
+ if (state.isObject(value) && state.isObject(v)) {
971
+ Object.assign(value, key ? { [key]: v } : v);
972
+ } else if (!key) {
973
+ value = v;
974
+ }
975
+ } else if (value[p[0]] !== void 0) {
976
+ const curValue = getValueAtPath(currentValue, p);
977
+ const newValue = getValueAtPath(value, p);
978
+ if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
979
+ delete pending2[key];
980
+ didChangeMetadata = true;
981
+ } else {
959
982
  const oldValue = clone2(value);
960
- pending2[key].p = key ? oldValue[key] : oldValue;
961
- if (state.isObject(value) && state.isObject(v)) {
962
- Object.assign(value, key ? { [key]: v } : v);
963
- } else if (!key) {
964
- value = v;
965
- }
966
- } else if (value[p[0]] !== void 0) {
967
- const curValue = getValueAtPath(currentValue, p);
968
- const newValue = getValueAtPath(value, p);
969
- if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
970
- delete pending2[key];
971
- didChangeMetadata = true;
972
- } else {
973
- const oldValue = clone2(value);
974
- pending2[key].p = getValueAtPath(oldValue, p);
975
- didChangeMetadata = true;
976
- value = state.setAtPath(
977
- value,
978
- p,
979
- t,
980
- v,
981
- "merge",
982
- obs$.peek(),
983
- (path, value2) => {
984
- delete pending2[key];
985
- pending2[path.join("/")] = {
986
- p: null,
987
- v: value2,
988
- t: t.slice(0, path.length)
989
- };
990
- }
991
- );
992
- }
983
+ pending2[key].p = getValueAtPath(oldValue, p);
984
+ didChangeMetadata = true;
985
+ value = state.setAtPath(
986
+ value,
987
+ p,
988
+ t,
989
+ v,
990
+ "merge",
991
+ obs$.peek(),
992
+ (path, value2) => {
993
+ delete pending2[key];
994
+ pending2[path.join("/")] = {
995
+ p: null,
996
+ v: value2,
997
+ t: t.slice(0, path.length)
998
+ };
999
+ }
1000
+ );
993
1001
  }
994
- });
995
- if (didChangeMetadata && syncOptions.persist) {
996
- updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
997
- pending: pending2
998
- });
999
1002
  }
1003
+ });
1004
+ if (didChangeMetadata && syncOptions.persist) {
1005
+ updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1006
+ pending: pending2
1007
+ });
1000
1008
  }
1001
- onChangeRemote2(() => {
1002
- if (state.isPlainObject(value)) {
1003
- value = state.ObservableHint.plain(value);
1009
+ }
1010
+ onChangeRemote2(() => {
1011
+ if (state.isPlainObject(value)) {
1012
+ value = state.ObservableHint.plain(value);
1013
+ }
1014
+ if (mode === "assign") {
1015
+ obs$.assign(value);
1016
+ } else if (mode === "append") {
1017
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
1018
+ console.error("[legend-state] mode:append expects the value to be an array");
1004
1019
  }
1005
- if (mode === "assign") {
1006
- obs$.assign(value);
1007
- } else if (mode === "append") {
1008
- if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
1009
- console.error("[legend-state] mode:append expects the value to be an array");
1010
- }
1011
- obs$.push(...value);
1012
- } else if (mode === "prepend") {
1013
- if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
1014
- console.error("[legend-state] mode:prepend expects the value to be an array");
1015
- }
1016
- obs$.splice(0, 0, ...value);
1017
- } else if (mode === "merge") {
1018
- state.mergeIntoObservable(obs$, value);
1019
- } else {
1020
- obs$.set(value);
1020
+ obs$.push(...value);
1021
+ } else if (mode === "prepend") {
1022
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
1023
+ console.error("[legend-state] mode:prepend expects the value to be an array");
1021
1024
  }
1022
- });
1023
- }
1024
- if (lastSync2 && syncOptions.persist) {
1025
- updateMetadata(obs$, localState, syncState$, syncOptions, {
1026
- lastSync: lastSync2
1027
- });
1028
- }
1029
- };
1030
- if (node.activationState) {
1031
- node.activationState.onChange = onChange;
1025
+ obs$.splice(0, 0, ...value);
1026
+ } else if (mode === "merge") {
1027
+ state.mergeIntoObservable(obs$, value);
1028
+ } else {
1029
+ obs$.set(value);
1030
+ }
1031
+ });
1032
1032
  }
1033
- if (!isSubscribed && syncOptions.subscribe) {
1034
- const subscribe2 = syncOptions.subscribe;
1035
- isSubscribed = true;
1036
- const doSubscribe = () => {
1037
- const subscribeParams = {
1038
- node,
1039
- value$: obs$,
1040
- lastSync,
1041
- update: (params) => {
1042
- state.when(
1043
- () => !get || syncState$.isLoaded.get(),
1044
- () => {
1045
- state.when(waitFor || true, () => {
1046
- params.mode || (params.mode = syncOptions.mode || "merge");
1047
- onChange(params);
1048
- if (!syncState$.isLoaded.peek()) {
1049
- syncState$.assign({
1050
- isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1051
- error: void 0,
1052
- isGetting: syncStateValue.numPendingGets > 0
1053
- });
1054
- }
1055
- });
1056
- }
1057
- );
1058
- },
1059
- refresh: () => state.when(syncState$.isLoaded, sync),
1060
- onError: (error) => onGetError(error, {
1061
- source: "subscribe",
1062
- subscribeParams,
1063
- type: "get",
1064
- retry: {}
1065
- })
1066
- };
1067
- unsubscribe = subscribe2(subscribeParams);
1068
- };
1069
- if (waitFor) {
1070
- state.whenReady(waitFor, doSubscribe);
1071
- } else {
1072
- doSubscribe();
1073
- }
1033
+ if (lastSync2 && syncOptions.persist) {
1034
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
1035
+ lastSync: lastSync2
1036
+ });
1074
1037
  }
1075
- const existingValue = getNodeValue(node);
1076
- if (get) {
1077
- const getParams = {
1038
+ };
1039
+ if (node.activationState) {
1040
+ node.activationState.onChange = onChange;
1041
+ }
1042
+ if (!isSubscribed && syncOptions.subscribe) {
1043
+ const subscribe2 = syncOptions.subscribe;
1044
+ const doSubscribe = () => {
1045
+ isSubscribed = true;
1046
+ const subscribeParams = {
1078
1047
  node,
1079
1048
  value$: obs$,
1080
- value: state.isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
1081
- mode: syncOptions.mode,
1082
- refresh: sync,
1083
- options: syncOptions,
1084
1049
  lastSync,
1085
- updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
1086
- onError: onGetError,
1087
- retryNum: 0,
1088
- cancelRetry: false
1089
- };
1090
- let modeBeforeReset = void 0;
1091
- const beforeGetParams = {
1092
- value: getParams.value,
1093
- lastSync,
1094
- pendingChanges: pending && !state.isEmpty(pending) ? pending : void 0,
1095
- clearPendingChanges: async () => {
1096
- localState.pendingChanges = {};
1097
- await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1098
- pending: localState.pendingChanges
1099
- });
1100
- },
1101
- resetCache: () => {
1102
- var _a3;
1103
- modeBeforeReset = getParams.mode;
1104
- getParams.mode = "set";
1105
- return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
1050
+ update: (params) => {
1051
+ state.when(
1052
+ () => !get || syncState$.isLoaded.get(),
1053
+ () => {
1054
+ state.when(waitFor || true, () => {
1055
+ params.mode || (params.mode = syncOptions.mode || "merge");
1056
+ onChange(params);
1057
+ if (!syncState$.isLoaded.peek()) {
1058
+ syncState$.assign({
1059
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1060
+ error: void 0,
1061
+ isGetting: syncStateValue.numPendingGets > 0
1062
+ });
1063
+ }
1064
+ });
1065
+ }
1066
+ );
1106
1067
  },
1107
- cancel: false
1068
+ refresh: () => state.when(syncState$.isLoaded, sync),
1069
+ onError: (error) => onGetError(error, {
1070
+ source: "subscribe",
1071
+ subscribeParams,
1072
+ type: "get",
1073
+ retry: {}
1074
+ })
1108
1075
  };
1109
- (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
1110
- if (!beforeGetParams.cancel) {
1111
- syncState$.assign({
1112
- numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
1113
- isGetting: true
1114
- });
1115
- const got = runWithRetry(getParams, syncOptions.retry, node, (retryEvent) => {
1116
- const params = getParams;
1117
- params.cancelRetry = retryEvent.cancelRetry;
1118
- params.retryNum = retryEvent.retryNum;
1119
- return get(params);
1076
+ unsubscribe = subscribe2(subscribeParams);
1077
+ registerMiddleware(node, "listeners-cleared", () => {
1078
+ if (unsubscribe) {
1079
+ isSubscribed = false;
1080
+ unsubscribe();
1081
+ unsubscribe = void 0;
1082
+ }
1083
+ });
1084
+ registerMiddleware(node, "listener-added", () => {
1085
+ if (!isSubscribed) {
1086
+ doSubscribe();
1087
+ }
1088
+ });
1089
+ };
1090
+ if (waitFor) {
1091
+ state.whenReady(waitFor, doSubscribe);
1092
+ } else {
1093
+ doSubscribe();
1094
+ }
1095
+ }
1096
+ const existingValue = getNodeValue(node);
1097
+ if (get) {
1098
+ const getParams = {
1099
+ node,
1100
+ value$: obs$,
1101
+ value: state.isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
1102
+ mode: syncOptions.mode,
1103
+ refresh: sync,
1104
+ options: syncOptions,
1105
+ lastSync,
1106
+ updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
1107
+ onError: onGetError,
1108
+ retryNum: 0,
1109
+ cancelRetry: false
1110
+ };
1111
+ let modeBeforeReset = void 0;
1112
+ const beforeGetParams = {
1113
+ value: getParams.value,
1114
+ lastSync,
1115
+ pendingChanges: pending && !state.isEmpty(pending) ? pending : void 0,
1116
+ clearPendingChanges: async () => {
1117
+ localState.pendingChanges = {};
1118
+ await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1119
+ pending: localState.pendingChanges
1120
1120
  });
1121
- const numGets = node.numGets = (node.numGets || 0) + 1;
1122
- const handle = (value) => {
1123
- syncState$.numPendingGets.set((v) => v - 1);
1124
- if (isWaitingForLoad) {
1125
- isWaitingForLoad = false;
1126
- syncStateValue.numPendingRemoteLoads--;
1127
- }
1128
- if (numGets >= (node.getNumResolved || 0)) {
1129
- node.getNumResolved = node.numGets;
1130
- onChange({
1131
- value,
1132
- lastSync: getParams.lastSync,
1133
- mode: getParams.mode
1134
- });
1135
- }
1136
- if (modeBeforeReset) {
1137
- getParams.mode = modeBeforeReset;
1138
- modeBeforeReset = void 0;
1139
- }
1140
- syncState$.assign({
1141
- isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1142
- error: void 0,
1143
- isGetting: syncStateValue.numPendingGets > 0
1144
- });
1145
- };
1146
- if (state.isPromise(got)) {
1147
- got.then(handle).catch((error) => {
1148
- onGetError(
1149
- error,
1150
- { getParams, source: "get", type: "get", retry: getParams },
1151
- true
1152
- );
1121
+ },
1122
+ resetCache: () => {
1123
+ var _a3;
1124
+ modeBeforeReset = getParams.mode;
1125
+ getParams.mode = "set";
1126
+ return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
1127
+ },
1128
+ cancel: false
1129
+ };
1130
+ (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
1131
+ if (!beforeGetParams.cancel) {
1132
+ syncState$.assign({
1133
+ numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
1134
+ isGetting: true
1135
+ });
1136
+ const got = runWithRetry(getParams, syncOptions.retry, node, (retryEvent) => {
1137
+ const params = getParams;
1138
+ params.cancelRetry = retryEvent.cancelRetry;
1139
+ params.retryNum = retryEvent.retryNum;
1140
+ return get(params);
1141
+ });
1142
+ const numGets = node.numGets = (node.numGets || 0) + 1;
1143
+ const handle = (value) => {
1144
+ syncState$.numPendingGets.set((v) => v - 1);
1145
+ if (isWaitingForLoad) {
1146
+ isWaitingForLoad = false;
1147
+ syncStateValue.numPendingRemoteLoads--;
1148
+ }
1149
+ if (numGets >= (node.getNumResolved || 0)) {
1150
+ node.getNumResolved = node.numGets;
1151
+ onChange({
1152
+ value,
1153
+ lastSync: getParams.lastSync,
1154
+ mode: getParams.mode
1153
1155
  });
1154
- } else {
1155
- handle(got);
1156
1156
  }
1157
+ if (modeBeforeReset) {
1158
+ getParams.mode = modeBeforeReset;
1159
+ modeBeforeReset = void 0;
1160
+ }
1161
+ syncState$.assign({
1162
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1163
+ error: void 0,
1164
+ isGetting: syncStateValue.numPendingGets > 0
1165
+ });
1166
+ };
1167
+ if (state.isPromise(got)) {
1168
+ got.then(handle).catch((error) => {
1169
+ onGetError(error, { getParams, source: "get", type: "get", retry: getParams }, true);
1170
+ });
1171
+ } else {
1172
+ handle(got);
1157
1173
  }
1158
1174
  }
1159
- };
1160
- if (waitFor) {
1161
- state.whenReady(waitFor, () => state.trackSelector(runGet, sync));
1162
- } else {
1163
- state.trackSelector(runGet, sync);
1164
1175
  }
1176
+ };
1177
+ if (waitFor) {
1178
+ state.whenReady(waitFor, () => state.trackSelector(runGet, sync));
1165
1179
  } else {
1166
- syncState$.assign({
1167
- isLoaded: true,
1168
- error: void 0
1169
- });
1180
+ state.trackSelector(runGet, sync);
1170
1181
  }
1171
1182
  if (!isSynced) {
1172
1183
  isSynced = true;
package/sync.mjs CHANGED
@@ -232,7 +232,17 @@ function createRevertChanges(obs$, changes) {
232
232
  }
233
233
 
234
234
  // src/sync/syncObservable.ts
235
- var { clone: clone2, deepMerge, getNode, getNodeValue, getValueAtPath, globalState, symbolLinked, createPreviousHandler } = internal;
235
+ var {
236
+ clone: clone2,
237
+ createPreviousHandler,
238
+ deepMerge,
239
+ getNode,
240
+ getNodeValue,
241
+ getValueAtPath,
242
+ globalState,
243
+ registerMiddleware,
244
+ symbolLinked
245
+ } = internal;
236
246
  var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
237
247
  var allSyncStates = /* @__PURE__ */ new Map();
238
248
  var metadatas = /* @__PURE__ */ new WeakMap();
@@ -935,236 +945,237 @@ function syncObservable(obs$, syncOptionsOrSynced) {
935
945
  }
936
946
  const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
937
947
  const pending = localState.pendingChanges;
938
- if (get || subscribe) {
939
- const { waitFor } = syncOptions;
940
- const runGet = () => {
941
- var _a2;
942
- const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
943
- mode = mode || syncOptions.mode || "set";
944
- if (value !== void 0) {
945
- value = transformLoadData(value, syncOptions, true, "get");
946
- if (isPromise$1(value)) {
947
- value = await value;
948
- }
949
- const pending2 = localState.pendingChanges;
950
- const currentValue = obs$.peek();
951
- if (pending2) {
952
- let didChangeMetadata = false;
953
- Object.keys(pending2).forEach((key) => {
954
- const p = key.split("/").filter((k) => k !== "");
955
- const { v, t } = pending2[key];
956
- if (t.length === 0 || !value) {
948
+ const { waitFor } = syncOptions;
949
+ const runGet = () => {
950
+ var _a2;
951
+ const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
952
+ mode = mode || syncOptions.mode || "set";
953
+ if (value !== void 0) {
954
+ value = transformLoadData(value, syncOptions, true, "get");
955
+ if (isPromise$1(value)) {
956
+ value = await value;
957
+ }
958
+ const pending2 = localState.pendingChanges;
959
+ const currentValue = obs$.peek();
960
+ if (pending2) {
961
+ let didChangeMetadata = false;
962
+ Object.keys(pending2).forEach((key) => {
963
+ const p = key.split("/").filter((k) => k !== "");
964
+ const { v, t } = pending2[key];
965
+ if (t.length === 0 || !value) {
966
+ const oldValue = clone2(value);
967
+ pending2[key].p = key ? oldValue[key] : oldValue;
968
+ if (isObject(value) && isObject(v)) {
969
+ Object.assign(value, key ? { [key]: v } : v);
970
+ } else if (!key) {
971
+ value = v;
972
+ }
973
+ } else if (value[p[0]] !== void 0) {
974
+ const curValue = getValueAtPath(currentValue, p);
975
+ const newValue = getValueAtPath(value, p);
976
+ if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
977
+ delete pending2[key];
978
+ didChangeMetadata = true;
979
+ } else {
957
980
  const oldValue = clone2(value);
958
- pending2[key].p = key ? oldValue[key] : oldValue;
959
- if (isObject(value) && isObject(v)) {
960
- Object.assign(value, key ? { [key]: v } : v);
961
- } else if (!key) {
962
- value = v;
963
- }
964
- } else if (value[p[0]] !== void 0) {
965
- const curValue = getValueAtPath(currentValue, p);
966
- const newValue = getValueAtPath(value, p);
967
- if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
968
- delete pending2[key];
969
- didChangeMetadata = true;
970
- } else {
971
- const oldValue = clone2(value);
972
- pending2[key].p = getValueAtPath(oldValue, p);
973
- didChangeMetadata = true;
974
- value = setAtPath(
975
- value,
976
- p,
977
- t,
978
- v,
979
- "merge",
980
- obs$.peek(),
981
- (path, value2) => {
982
- delete pending2[key];
983
- pending2[path.join("/")] = {
984
- p: null,
985
- v: value2,
986
- t: t.slice(0, path.length)
987
- };
988
- }
989
- );
990
- }
981
+ pending2[key].p = getValueAtPath(oldValue, p);
982
+ didChangeMetadata = true;
983
+ value = setAtPath(
984
+ value,
985
+ p,
986
+ t,
987
+ v,
988
+ "merge",
989
+ obs$.peek(),
990
+ (path, value2) => {
991
+ delete pending2[key];
992
+ pending2[path.join("/")] = {
993
+ p: null,
994
+ v: value2,
995
+ t: t.slice(0, path.length)
996
+ };
997
+ }
998
+ );
991
999
  }
992
- });
993
- if (didChangeMetadata && syncOptions.persist) {
994
- updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
995
- pending: pending2
996
- });
997
1000
  }
1001
+ });
1002
+ if (didChangeMetadata && syncOptions.persist) {
1003
+ updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1004
+ pending: pending2
1005
+ });
998
1006
  }
999
- onChangeRemote2(() => {
1000
- if (isPlainObject(value)) {
1001
- value = ObservableHint.plain(value);
1007
+ }
1008
+ onChangeRemote2(() => {
1009
+ if (isPlainObject(value)) {
1010
+ value = ObservableHint.plain(value);
1011
+ }
1012
+ if (mode === "assign") {
1013
+ obs$.assign(value);
1014
+ } else if (mode === "append") {
1015
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
1016
+ console.error("[legend-state] mode:append expects the value to be an array");
1002
1017
  }
1003
- if (mode === "assign") {
1004
- obs$.assign(value);
1005
- } else if (mode === "append") {
1006
- if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
1007
- console.error("[legend-state] mode:append expects the value to be an array");
1008
- }
1009
- obs$.push(...value);
1010
- } else if (mode === "prepend") {
1011
- if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
1012
- console.error("[legend-state] mode:prepend expects the value to be an array");
1013
- }
1014
- obs$.splice(0, 0, ...value);
1015
- } else if (mode === "merge") {
1016
- mergeIntoObservable(obs$, value);
1017
- } else {
1018
- obs$.set(value);
1018
+ obs$.push(...value);
1019
+ } else if (mode === "prepend") {
1020
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
1021
+ console.error("[legend-state] mode:prepend expects the value to be an array");
1019
1022
  }
1020
- });
1021
- }
1022
- if (lastSync2 && syncOptions.persist) {
1023
- updateMetadata(obs$, localState, syncState$, syncOptions, {
1024
- lastSync: lastSync2
1025
- });
1026
- }
1027
- };
1028
- if (node.activationState) {
1029
- node.activationState.onChange = onChange;
1023
+ obs$.splice(0, 0, ...value);
1024
+ } else if (mode === "merge") {
1025
+ mergeIntoObservable(obs$, value);
1026
+ } else {
1027
+ obs$.set(value);
1028
+ }
1029
+ });
1030
1030
  }
1031
- if (!isSubscribed && syncOptions.subscribe) {
1032
- const subscribe2 = syncOptions.subscribe;
1033
- isSubscribed = true;
1034
- const doSubscribe = () => {
1035
- const subscribeParams = {
1036
- node,
1037
- value$: obs$,
1038
- lastSync,
1039
- update: (params) => {
1040
- when(
1041
- () => !get || syncState$.isLoaded.get(),
1042
- () => {
1043
- when(waitFor || true, () => {
1044
- params.mode || (params.mode = syncOptions.mode || "merge");
1045
- onChange(params);
1046
- if (!syncState$.isLoaded.peek()) {
1047
- syncState$.assign({
1048
- isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1049
- error: void 0,
1050
- isGetting: syncStateValue.numPendingGets > 0
1051
- });
1052
- }
1053
- });
1054
- }
1055
- );
1056
- },
1057
- refresh: () => when(syncState$.isLoaded, sync),
1058
- onError: (error) => onGetError(error, {
1059
- source: "subscribe",
1060
- subscribeParams,
1061
- type: "get",
1062
- retry: {}
1063
- })
1064
- };
1065
- unsubscribe = subscribe2(subscribeParams);
1066
- };
1067
- if (waitFor) {
1068
- whenReady(waitFor, doSubscribe);
1069
- } else {
1070
- doSubscribe();
1071
- }
1031
+ if (lastSync2 && syncOptions.persist) {
1032
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
1033
+ lastSync: lastSync2
1034
+ });
1072
1035
  }
1073
- const existingValue = getNodeValue(node);
1074
- if (get) {
1075
- const getParams = {
1036
+ };
1037
+ if (node.activationState) {
1038
+ node.activationState.onChange = onChange;
1039
+ }
1040
+ if (!isSubscribed && syncOptions.subscribe) {
1041
+ const subscribe2 = syncOptions.subscribe;
1042
+ const doSubscribe = () => {
1043
+ isSubscribed = true;
1044
+ const subscribeParams = {
1076
1045
  node,
1077
1046
  value$: obs$,
1078
- value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
1079
- mode: syncOptions.mode,
1080
- refresh: sync,
1081
- options: syncOptions,
1082
1047
  lastSync,
1083
- updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
1084
- onError: onGetError,
1085
- retryNum: 0,
1086
- cancelRetry: false
1087
- };
1088
- let modeBeforeReset = void 0;
1089
- const beforeGetParams = {
1090
- value: getParams.value,
1091
- lastSync,
1092
- pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
1093
- clearPendingChanges: async () => {
1094
- localState.pendingChanges = {};
1095
- await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1096
- pending: localState.pendingChanges
1097
- });
1098
- },
1099
- resetCache: () => {
1100
- var _a3;
1101
- modeBeforeReset = getParams.mode;
1102
- getParams.mode = "set";
1103
- return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
1048
+ update: (params) => {
1049
+ when(
1050
+ () => !get || syncState$.isLoaded.get(),
1051
+ () => {
1052
+ when(waitFor || true, () => {
1053
+ params.mode || (params.mode = syncOptions.mode || "merge");
1054
+ onChange(params);
1055
+ if (!syncState$.isLoaded.peek()) {
1056
+ syncState$.assign({
1057
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1058
+ error: void 0,
1059
+ isGetting: syncStateValue.numPendingGets > 0
1060
+ });
1061
+ }
1062
+ });
1063
+ }
1064
+ );
1104
1065
  },
1105
- cancel: false
1066
+ refresh: () => when(syncState$.isLoaded, sync),
1067
+ onError: (error) => onGetError(error, {
1068
+ source: "subscribe",
1069
+ subscribeParams,
1070
+ type: "get",
1071
+ retry: {}
1072
+ })
1106
1073
  };
1107
- (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
1108
- if (!beforeGetParams.cancel) {
1109
- syncState$.assign({
1110
- numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
1111
- isGetting: true
1112
- });
1113
- const got = runWithRetry(getParams, syncOptions.retry, node, (retryEvent) => {
1114
- const params = getParams;
1115
- params.cancelRetry = retryEvent.cancelRetry;
1116
- params.retryNum = retryEvent.retryNum;
1117
- return get(params);
1074
+ unsubscribe = subscribe2(subscribeParams);
1075
+ registerMiddleware(node, "listeners-cleared", () => {
1076
+ if (unsubscribe) {
1077
+ isSubscribed = false;
1078
+ unsubscribe();
1079
+ unsubscribe = void 0;
1080
+ }
1081
+ });
1082
+ registerMiddleware(node, "listener-added", () => {
1083
+ if (!isSubscribed) {
1084
+ doSubscribe();
1085
+ }
1086
+ });
1087
+ };
1088
+ if (waitFor) {
1089
+ whenReady(waitFor, doSubscribe);
1090
+ } else {
1091
+ doSubscribe();
1092
+ }
1093
+ }
1094
+ const existingValue = getNodeValue(node);
1095
+ if (get) {
1096
+ const getParams = {
1097
+ node,
1098
+ value$: obs$,
1099
+ value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
1100
+ mode: syncOptions.mode,
1101
+ refresh: sync,
1102
+ options: syncOptions,
1103
+ lastSync,
1104
+ updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
1105
+ onError: onGetError,
1106
+ retryNum: 0,
1107
+ cancelRetry: false
1108
+ };
1109
+ let modeBeforeReset = void 0;
1110
+ const beforeGetParams = {
1111
+ value: getParams.value,
1112
+ lastSync,
1113
+ pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
1114
+ clearPendingChanges: async () => {
1115
+ localState.pendingChanges = {};
1116
+ await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1117
+ pending: localState.pendingChanges
1118
1118
  });
1119
- const numGets = node.numGets = (node.numGets || 0) + 1;
1120
- const handle = (value) => {
1121
- syncState$.numPendingGets.set((v) => v - 1);
1122
- if (isWaitingForLoad) {
1123
- isWaitingForLoad = false;
1124
- syncStateValue.numPendingRemoteLoads--;
1125
- }
1126
- if (numGets >= (node.getNumResolved || 0)) {
1127
- node.getNumResolved = node.numGets;
1128
- onChange({
1129
- value,
1130
- lastSync: getParams.lastSync,
1131
- mode: getParams.mode
1132
- });
1133
- }
1134
- if (modeBeforeReset) {
1135
- getParams.mode = modeBeforeReset;
1136
- modeBeforeReset = void 0;
1137
- }
1138
- syncState$.assign({
1139
- isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1140
- error: void 0,
1141
- isGetting: syncStateValue.numPendingGets > 0
1142
- });
1143
- };
1144
- if (isPromise$1(got)) {
1145
- got.then(handle).catch((error) => {
1146
- onGetError(
1147
- error,
1148
- { getParams, source: "get", type: "get", retry: getParams },
1149
- true
1150
- );
1119
+ },
1120
+ resetCache: () => {
1121
+ var _a3;
1122
+ modeBeforeReset = getParams.mode;
1123
+ getParams.mode = "set";
1124
+ return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
1125
+ },
1126
+ cancel: false
1127
+ };
1128
+ (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
1129
+ if (!beforeGetParams.cancel) {
1130
+ syncState$.assign({
1131
+ numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
1132
+ isGetting: true
1133
+ });
1134
+ const got = runWithRetry(getParams, syncOptions.retry, node, (retryEvent) => {
1135
+ const params = getParams;
1136
+ params.cancelRetry = retryEvent.cancelRetry;
1137
+ params.retryNum = retryEvent.retryNum;
1138
+ return get(params);
1139
+ });
1140
+ const numGets = node.numGets = (node.numGets || 0) + 1;
1141
+ const handle = (value) => {
1142
+ syncState$.numPendingGets.set((v) => v - 1);
1143
+ if (isWaitingForLoad) {
1144
+ isWaitingForLoad = false;
1145
+ syncStateValue.numPendingRemoteLoads--;
1146
+ }
1147
+ if (numGets >= (node.getNumResolved || 0)) {
1148
+ node.getNumResolved = node.numGets;
1149
+ onChange({
1150
+ value,
1151
+ lastSync: getParams.lastSync,
1152
+ mode: getParams.mode
1151
1153
  });
1152
- } else {
1153
- handle(got);
1154
1154
  }
1155
+ if (modeBeforeReset) {
1156
+ getParams.mode = modeBeforeReset;
1157
+ modeBeforeReset = void 0;
1158
+ }
1159
+ syncState$.assign({
1160
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1161
+ error: void 0,
1162
+ isGetting: syncStateValue.numPendingGets > 0
1163
+ });
1164
+ };
1165
+ if (isPromise$1(got)) {
1166
+ got.then(handle).catch((error) => {
1167
+ onGetError(error, { getParams, source: "get", type: "get", retry: getParams }, true);
1168
+ });
1169
+ } else {
1170
+ handle(got);
1155
1171
  }
1156
1172
  }
1157
- };
1158
- if (waitFor) {
1159
- whenReady(waitFor, () => trackSelector(runGet, sync));
1160
- } else {
1161
- trackSelector(runGet, sync);
1162
1173
  }
1174
+ };
1175
+ if (waitFor) {
1176
+ whenReady(waitFor, () => trackSelector(runGet, sync));
1163
1177
  } else {
1164
- syncState$.assign({
1165
- isLoaded: true,
1166
- error: void 0
1167
- });
1178
+ trackSelector(runGet, sync);
1168
1179
  }
1169
1180
  if (!isSynced) {
1170
1181
  isSynced = true;