@legendapp/state 3.0.0-alpha.1 → 3.0.0-alpha.3

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 (327) hide show
  1. package/.DS_Store +0 -0
  2. package/CHANGELOG.md +1 -831
  3. package/LICENSE +1 -21
  4. package/README.md +1 -141
  5. package/as/arrayAsRecord.d.mts +5 -0
  6. package/as/arrayAsRecord.d.ts +5 -0
  7. package/as/arrayAsRecord.js +28 -0
  8. package/as/arrayAsRecord.mjs +26 -0
  9. package/as/arrayAsSet.d.mts +5 -0
  10. package/as/arrayAsSet.d.ts +5 -0
  11. package/as/arrayAsSet.js +13 -0
  12. package/as/arrayAsSet.mjs +11 -0
  13. package/as/arrayAsString.d.mts +5 -0
  14. package/as/arrayAsString.d.ts +5 -0
  15. package/as/arrayAsString.js +13 -0
  16. package/as/arrayAsString.mjs +11 -0
  17. package/as/numberAsString.d.mts +5 -0
  18. package/as/numberAsString.d.ts +5 -0
  19. package/as/numberAsString.js +13 -0
  20. package/as/numberAsString.mjs +11 -0
  21. package/as/recordAsArray.d.mts +5 -0
  22. package/as/recordAsArray.d.ts +5 -0
  23. package/as/recordAsArray.js +25 -0
  24. package/as/recordAsArray.mjs +23 -0
  25. package/as/recordAsString.d.mts +5 -0
  26. package/as/recordAsString.d.ts +5 -0
  27. package/as/recordAsString.js +13 -0
  28. package/as/recordAsString.mjs +11 -0
  29. package/as/setAsArray.d.mts +5 -0
  30. package/as/setAsArray.d.ts +5 -0
  31. package/as/setAsArray.js +13 -0
  32. package/as/setAsArray.mjs +11 -0
  33. package/as/setAsString.d.mts +5 -0
  34. package/as/setAsString.d.ts +5 -0
  35. package/as/setAsString.js +13 -0
  36. package/as/setAsString.mjs +11 -0
  37. package/as/stringAsArray.d.mts +5 -0
  38. package/as/stringAsArray.d.ts +5 -0
  39. package/as/stringAsArray.js +13 -0
  40. package/as/stringAsArray.mjs +11 -0
  41. package/as/stringAsNumber.d.mts +5 -0
  42. package/as/stringAsNumber.d.ts +5 -0
  43. package/as/stringAsNumber.js +16 -0
  44. package/as/stringAsNumber.mjs +14 -0
  45. package/as/stringAsRecord.d.mts +5 -0
  46. package/as/stringAsRecord.d.ts +5 -0
  47. package/as/stringAsRecord.js +15 -0
  48. package/as/stringAsRecord.mjs +13 -0
  49. package/as/stringAsSet.d.mts +5 -0
  50. package/as/stringAsSet.d.ts +5 -0
  51. package/as/stringAsSet.js +13 -0
  52. package/as/stringAsSet.mjs +11 -0
  53. package/babel.d.mts +21 -0
  54. package/babel.d.ts +21 -2
  55. package/babel.js +57 -53
  56. package/babel.mjs +65 -0
  57. package/config/enable$GetSet.js +13 -14
  58. package/config/enable$GetSet.mjs +13 -14
  59. package/config/enableReactComponents.d.mts +9 -0
  60. package/config/enableReactComponents.d.ts +4 -2
  61. package/config/enableReactComponents.js +13 -10
  62. package/config/enableReactComponents.mjs +13 -10
  63. package/config/enableReactNativeComponents.d.mts +22 -0
  64. package/config/enableReactNativeComponents.d.ts +6 -4
  65. package/config/enableReactNativeComponents.js +43 -47
  66. package/config/enableReactNativeComponents.mjs +43 -47
  67. package/config/enableReactTracking.d.mts +7 -0
  68. package/config/enableReactTracking.d.ts +3 -2
  69. package/config/enableReactTracking.js +33 -38
  70. package/config/enableReactTracking.mjs +33 -38
  71. package/config/enableReactUse.d.mts +10 -0
  72. package/config/enableReactUse.d.ts +4 -1
  73. package/config/enableReactUse.js +15 -14
  74. package/config/enableReactUse.mjs +15 -14
  75. package/config/{enable$GetSet.d.ts → enable_GetSet.d.mts} +4 -2
  76. package/config/enable_GetSet.d.ts +10 -0
  77. package/config/enable_PeekAssign.d.mts +10 -0
  78. package/config/enable_PeekAssign.d.ts +4 -2
  79. package/config/enable_PeekAssign.js +13 -14
  80. package/config/enable_PeekAssign.mjs +13 -14
  81. package/helpers/pageHash.d.mts +9 -0
  82. package/helpers/pageHash.d.ts +2 -0
  83. package/helpers/pageHash.js +25 -30
  84. package/helpers/pageHash.mjs +25 -30
  85. package/helpers/pageHashParams.d.mts +9 -0
  86. package/helpers/pageHashParams.d.ts +2 -0
  87. package/helpers/pageHashParams.js +34 -37
  88. package/helpers/pageHashParams.mjs +34 -37
  89. package/helpers/time.d.mts +6 -0
  90. package/helpers/time.d.ts +6 -3
  91. package/helpers/time.js +17 -17
  92. package/helpers/time.mjs +17 -17
  93. package/helpers/trackHistory.d.mts +6 -0
  94. package/helpers/trackHistory.d.ts +4 -2
  95. package/helpers/trackHistory.js +13 -16
  96. package/helpers/trackHistory.mjs +13 -16
  97. package/helpers/undoRedo.d.mts +37 -0
  98. package/helpers/undoRedo.d.ts +5 -3
  99. package/helpers/undoRedo.js +59 -94
  100. package/helpers/undoRedo.mjs +59 -94
  101. package/index.d.mts +404 -0
  102. package/index.d.ts +371 -28
  103. package/index.js +2015 -2166
  104. package/index.mjs +2015 -2166
  105. package/package.json +254 -195
  106. package/persist-plugins/async-storage.d.mts +18 -0
  107. package/persist-plugins/async-storage.d.ts +6 -3
  108. package/persist-plugins/async-storage.js +79 -86
  109. package/persist-plugins/async-storage.mjs +79 -86
  110. package/persist-plugins/indexeddb.d.mts +29 -0
  111. package/persist-plugins/indexeddb.d.ts +6 -3
  112. package/persist-plugins/indexeddb.js +331 -352
  113. package/persist-plugins/indexeddb.mjs +331 -352
  114. package/persist-plugins/local-storage.d.mts +23 -0
  115. package/persist-plugins/local-storage.d.ts +8 -5
  116. package/persist-plugins/local-storage.js +74 -76
  117. package/persist-plugins/local-storage.mjs +74 -76
  118. package/persist-plugins/mmkv.d.mts +18 -0
  119. package/persist-plugins/mmkv.d.ts +6 -3
  120. package/persist-plugins/mmkv.js +82 -86
  121. package/persist-plugins/mmkv.mjs +82 -86
  122. package/react-hooks/createObservableHook.d.mts +5 -0
  123. package/react-hooks/createObservableHook.d.ts +4 -1
  124. package/react-hooks/createObservableHook.js +29 -30
  125. package/react-hooks/createObservableHook.mjs +25 -30
  126. package/react-hooks/useHover.d.mts +5 -0
  127. package/react-hooks/useHover.d.ts +5 -3
  128. package/react-hooks/useHover.js +29 -29
  129. package/react-hooks/useHover.mjs +29 -29
  130. package/react-hooks/useMeasure.d.mts +9 -0
  131. package/react-hooks/useMeasure.d.ts +5 -2
  132. package/react-hooks/useMeasure.js +30 -32
  133. package/react-hooks/useMeasure.mjs +30 -32
  134. package/react-hooks/useObservableNextRouter.d.mts +35 -0
  135. package/react-hooks/useObservableNextRouter.d.ts +9 -7
  136. package/react-hooks/useObservableNextRouter.js +64 -77
  137. package/react-hooks/useObservableNextRouter.mjs +60 -77
  138. package/react.d.mts +157 -0
  139. package/react.d.ts +157 -21
  140. package/react.js +458 -749
  141. package/react.mjs +457 -752
  142. package/sync-plugins/crud.d.mts +54 -0
  143. package/sync-plugins/crud.d.ts +12 -10
  144. package/sync-plugins/crud.js +253 -270
  145. package/sync-plugins/crud.mjs +253 -270
  146. package/sync-plugins/fetch.d.mts +21 -0
  147. package/sync-plugins/fetch.d.ts +7 -4
  148. package/sync-plugins/fetch.js +50 -37
  149. package/sync-plugins/fetch.mjs +50 -37
  150. package/sync-plugins/keel.d.mts +108 -0
  151. package/sync-plugins/keel.d.ts +17 -15
  152. package/sync-plugins/keel.js +229 -462
  153. package/sync-plugins/keel.mjs +227 -464
  154. package/sync-plugins/supabase.d.mts +39 -0
  155. package/sync-plugins/supabase.d.ts +16 -14
  156. package/sync-plugins/supabase.js +128 -128
  157. package/sync-plugins/supabase.mjs +128 -128
  158. package/sync-plugins/tanstack-query.d.mts +14 -0
  159. package/sync-plugins/tanstack-query.d.ts +7 -4
  160. package/sync-plugins/tanstack-query.js +51 -57
  161. package/sync-plugins/tanstack-query.mjs +51 -57
  162. package/sync-plugins/tanstack-react-query.d.mts +8 -0
  163. package/sync-plugins/tanstack-react-query.d.ts +6 -1
  164. package/sync-plugins/tanstack-react-query.js +2 -2
  165. package/sync-plugins/tanstack-react-query.mjs +2 -2
  166. package/sync.d.mts +351 -0
  167. package/sync.d.ts +349 -9
  168. package/sync.js +910 -964
  169. package/sync.mjs +920 -974
  170. package/trace.d.mts +9 -0
  171. package/trace.d.ts +9 -4
  172. package/trace.js +72 -62
  173. package/trace.mjs +72 -62
  174. package/types/babel.d.ts +1 -12
  175. package/babel.js.map +0 -1
  176. package/config/enable$GetSet.js.map +0 -1
  177. package/config/enable$GetSet.mjs.map +0 -1
  178. package/config/enableReactComponents.js.map +0 -1
  179. package/config/enableReactComponents.mjs.map +0 -1
  180. package/config/enableReactNativeComponents.js.map +0 -1
  181. package/config/enableReactNativeComponents.mjs.map +0 -1
  182. package/config/enableReactTracking.js.map +0 -1
  183. package/config/enableReactTracking.mjs.map +0 -1
  184. package/config/enableReactUse.js.map +0 -1
  185. package/config/enableReactUse.mjs.map +0 -1
  186. package/config/enable_PeekAssign.js.map +0 -1
  187. package/config/enable_PeekAssign.mjs.map +0 -1
  188. package/helpers/pageHash.js.map +0 -1
  189. package/helpers/pageHash.mjs.map +0 -1
  190. package/helpers/pageHashParams.js.map +0 -1
  191. package/helpers/pageHashParams.mjs.map +0 -1
  192. package/helpers/time.js.map +0 -1
  193. package/helpers/time.mjs.map +0 -1
  194. package/helpers/trackHistory.js.map +0 -1
  195. package/helpers/trackHistory.mjs.map +0 -1
  196. package/helpers/undoRedo.js.map +0 -1
  197. package/helpers/undoRedo.mjs.map +0 -1
  198. package/history.d.ts +0 -1
  199. package/history.js +0 -24
  200. package/history.js.map +0 -1
  201. package/history.mjs +0 -22
  202. package/history.mjs.map +0 -1
  203. package/index.js.map +0 -1
  204. package/index.mjs.map +0 -1
  205. package/persist-plugins/async-storage.js.map +0 -1
  206. package/persist-plugins/async-storage.mjs.map +0 -1
  207. package/persist-plugins/indexeddb.js.map +0 -1
  208. package/persist-plugins/indexeddb.mjs.map +0 -1
  209. package/persist-plugins/local-storage.js.map +0 -1
  210. package/persist-plugins/local-storage.mjs.map +0 -1
  211. package/persist-plugins/mmkv.js.map +0 -1
  212. package/persist-plugins/mmkv.mjs.map +0 -1
  213. package/react-hooks/createObservableHook.js.map +0 -1
  214. package/react-hooks/createObservableHook.mjs.map +0 -1
  215. package/react-hooks/useHover.js.map +0 -1
  216. package/react-hooks/useHover.mjs.map +0 -1
  217. package/react-hooks/useMeasure.js.map +0 -1
  218. package/react-hooks/useMeasure.mjs.map +0 -1
  219. package/react-hooks/useObservableNextRouter.js.map +0 -1
  220. package/react-hooks/useObservableNextRouter.mjs.map +0 -1
  221. package/react.js.map +0 -1
  222. package/react.mjs.map +0 -1
  223. package/src/ObservableObject.ts +0 -1350
  224. package/src/ObservablePrimitive.ts +0 -62
  225. package/src/babel/index.ts +0 -83
  226. package/src/batching.ts +0 -357
  227. package/src/computed.ts +0 -18
  228. package/src/config/enable$GetSet.ts +0 -30
  229. package/src/config/enableReactComponents.ts +0 -26
  230. package/src/config/enableReactNativeComponents.ts +0 -102
  231. package/src/config/enableReactTracking.ts +0 -62
  232. package/src/config/enableReactUse.ts +0 -32
  233. package/src/config/enable_PeekAssign.ts +0 -31
  234. package/src/config.ts +0 -47
  235. package/src/createObservable.ts +0 -47
  236. package/src/event.ts +0 -26
  237. package/src/globals.ts +0 -235
  238. package/src/helpers/pageHash.ts +0 -41
  239. package/src/helpers/pageHashParams.ts +0 -55
  240. package/src/helpers/time.ts +0 -30
  241. package/src/helpers/trackHistory.ts +0 -29
  242. package/src/helpers/undoRedo.ts +0 -111
  243. package/src/helpers.ts +0 -231
  244. package/src/is.ts +0 -63
  245. package/src/linked.ts +0 -17
  246. package/src/observable.ts +0 -32
  247. package/src/observableInterfaces.ts +0 -151
  248. package/src/observableTypes.ts +0 -232
  249. package/src/observe.ts +0 -89
  250. package/src/old-plugins/firebase.ts +0 -1053
  251. package/src/onChange.ts +0 -146
  252. package/src/persist/configureObservablePersistence.ts +0 -7
  253. package/src/persist/fieldTransformer.ts +0 -149
  254. package/src/persist/observablePersistRemoteFunctionsAdapter.ts +0 -39
  255. package/src/persist/persistObservable.ts +0 -1034
  256. package/src/persist-plugins/async-storage.ts +0 -99
  257. package/src/persist-plugins/indexeddb.ts +0 -439
  258. package/src/persist-plugins/local-storage.ts +0 -86
  259. package/src/persist-plugins/mmkv.ts +0 -91
  260. package/src/proxy.ts +0 -28
  261. package/src/react/Computed.tsx +0 -8
  262. package/src/react/For.tsx +0 -116
  263. package/src/react/Memo.tsx +0 -4
  264. package/src/react/Reactive.tsx +0 -53
  265. package/src/react/Show.tsx +0 -33
  266. package/src/react/Switch.tsx +0 -43
  267. package/src/react/react-globals.ts +0 -3
  268. package/src/react/reactInterfaces.ts +0 -32
  269. package/src/react/reactive-observer.tsx +0 -210
  270. package/src/react/useComputed.ts +0 -36
  271. package/src/react/useEffectOnce.ts +0 -41
  272. package/src/react/useIsMounted.ts +0 -16
  273. package/src/react/useMount.ts +0 -15
  274. package/src/react/useObservable.ts +0 -24
  275. package/src/react/useObservableReducer.ts +0 -52
  276. package/src/react/useObservableState.ts +0 -30
  277. package/src/react/useObserve.ts +0 -54
  278. package/src/react/useObserveEffect.ts +0 -40
  279. package/src/react/usePauseProvider.tsx +0 -16
  280. package/src/react/useSelector.ts +0 -167
  281. package/src/react/useUnmount.ts +0 -8
  282. package/src/react/useWhen.ts +0 -9
  283. package/src/react-hooks/createObservableHook.ts +0 -53
  284. package/src/react-hooks/useHover.ts +0 -40
  285. package/src/react-hooks/useMeasure.ts +0 -48
  286. package/src/react-hooks/useObservableNextRouter.ts +0 -137
  287. package/src/retry.ts +0 -71
  288. package/src/setupTracking.ts +0 -26
  289. package/src/sync/activateSyncedNode.ts +0 -128
  290. package/src/sync/configureObservableSync.ts +0 -7
  291. package/src/sync/persistTypes.ts +0 -216
  292. package/src/sync/syncHelpers.ts +0 -180
  293. package/src/sync/syncObservable.ts +0 -1056
  294. package/src/sync/syncObservableAdapter.ts +0 -31
  295. package/src/sync/syncTypes.ts +0 -189
  296. package/src/sync/synced.ts +0 -21
  297. package/src/sync-plugins/crud.ts +0 -412
  298. package/src/sync-plugins/fetch.ts +0 -80
  299. package/src/sync-plugins/keel.ts +0 -495
  300. package/src/sync-plugins/supabase.ts +0 -249
  301. package/src/sync-plugins/tanstack-query.ts +0 -113
  302. package/src/sync-plugins/tanstack-react-query.ts +0 -12
  303. package/src/trace/traceHelpers.ts +0 -11
  304. package/src/trace/useTraceListeners.ts +0 -34
  305. package/src/trace/useTraceUpdates.ts +0 -24
  306. package/src/trace/useVerifyNotTracking.ts +0 -33
  307. package/src/trace/useVerifyOneRender.ts +0 -10
  308. package/src/trackSelector.ts +0 -52
  309. package/src/tracking.ts +0 -43
  310. package/src/types/babel.d.ts +0 -12
  311. package/src/when.ts +0 -75
  312. package/sync-plugins/crud.js.map +0 -1
  313. package/sync-plugins/crud.mjs.map +0 -1
  314. package/sync-plugins/fetch.js.map +0 -1
  315. package/sync-plugins/fetch.mjs.map +0 -1
  316. package/sync-plugins/keel.js.map +0 -1
  317. package/sync-plugins/keel.mjs.map +0 -1
  318. package/sync-plugins/supabase.js.map +0 -1
  319. package/sync-plugins/supabase.mjs.map +0 -1
  320. package/sync-plugins/tanstack-query.js.map +0 -1
  321. package/sync-plugins/tanstack-query.mjs.map +0 -1
  322. package/sync-plugins/tanstack-react-query.js.map +0 -1
  323. package/sync-plugins/tanstack-react-query.mjs.map +0 -1
  324. package/sync.js.map +0 -1
  325. package/sync.mjs.map +0 -1
  326. package/trace.js.map +0 -1
  327. package/trace.mjs.map +0 -1
package/sync.mjs CHANGED
@@ -1,1065 +1,1011 @@
1
- import { isObject, isDate, isNullOrUndefined, isString, isPromise, endBatch, beginBatch, isFunction, observable, when, internal as internal$1, mergeIntoObservable, isEmpty, shouldIgnoreUnobserved, constructObjectWithPath, deconstructObjectWithPath, setAtPath, isArray, whenReady, linked } from '@legendapp/state';
1
+ import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction, mergeIntoObservable, observable, when, linked, internal, isPromise, isEmpty, shouldIgnoreUnobserved, whenReady, constructObjectWithPath, deconstructObjectWithPath, setAtPath, isArray } from '@legendapp/state';
2
2
 
3
- const observableSyncConfiguration = {};
3
+ // sync.ts
4
+
5
+ // src/sync/configureObservableSync.ts
6
+ var observableSyncConfiguration = {};
4
7
  function configureObservableSync(options) {
5
- Object.assign(observableSyncConfiguration, options);
8
+ Object.assign(observableSyncConfiguration, options);
6
9
  }
7
-
8
10
  function removeNullUndefined(a, recursive) {
9
- const out = {};
10
- Object.keys(a).forEach((key) => {
11
- if (a[key] !== null && a[key] !== undefined) {
12
- out[key] = recursive && isObject(a[key]) ? removeNullUndefined(a[key]) : a[key];
13
- }
14
- });
15
- return out;
11
+ const out = {};
12
+ Object.keys(a).forEach((key) => {
13
+ if (a[key] !== null && a[key] !== void 0) {
14
+ out[key] = recursive && isObject(a[key]) ? removeNullUndefined(a[key]) : a[key];
15
+ }
16
+ });
17
+ return out;
16
18
  }
17
19
  function diffObjects(obj1, obj2, deep = false) {
18
- const diff = {};
19
- if (!obj1)
20
- return obj2 || diff;
21
- if (!obj2)
22
- return obj1 || diff;
23
- const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
24
- keys.forEach((key) => {
25
- const o1 = obj1[key];
26
- const o2 = obj2[key];
27
- if (deep ? !deepEqual(o1, o2) : o1 !== o2) {
28
- if (!isDate(o1) || !isDate(o2) || o1.getTime() !== o2.getTime()) {
29
- diff[key] = o2;
30
- }
31
- }
32
- });
33
- return diff;
20
+ const diff = {};
21
+ if (!obj1)
22
+ return obj2 || diff;
23
+ if (!obj2)
24
+ return obj1 || diff;
25
+ const keys = /* @__PURE__ */ new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
26
+ keys.forEach((key) => {
27
+ const o1 = obj1[key];
28
+ const o2 = obj2[key];
29
+ if (deep ? !deepEqual(o1, o2) : o1 !== o2) {
30
+ if (!isDate(o1) || !isDate(o2) || o1.getTime() !== o2.getTime()) {
31
+ diff[key] = o2;
32
+ }
33
+ }
34
+ });
35
+ return diff;
34
36
  }
35
37
  function deepEqual(a, b, ignoreFields, nullVsUndefined) {
36
- if (a === b) {
37
- return true;
38
- }
39
- if (isNullOrUndefined(a) !== isNullOrUndefined(b)) {
40
- return false;
41
- }
42
- if (nullVsUndefined) {
43
- a = removeNullUndefined(a, /*recursive*/ true);
44
- b = removeNullUndefined(b, /*recursive*/ true);
45
- }
46
- const replacer = ignoreFields
47
- ? (key, value) => (ignoreFields.includes(key) ? undefined : value)
48
- : undefined;
49
- return JSON.stringify(a, replacer) === JSON.stringify(b, replacer);
38
+ if (a === b) {
39
+ return true;
40
+ }
41
+ if (isNullOrUndefined(a) !== isNullOrUndefined(b)) {
42
+ return false;
43
+ }
44
+ if (nullVsUndefined) {
45
+ a = removeNullUndefined(
46
+ a,
47
+ /*recursive*/
48
+ true
49
+ );
50
+ b = removeNullUndefined(
51
+ b,
52
+ /*recursive*/
53
+ true
54
+ );
55
+ }
56
+ const replacer = ignoreFields ? (key, value) => ignoreFields.includes(key) ? void 0 : value : void 0;
57
+ return JSON.stringify(a, replacer) === JSON.stringify(b, replacer);
50
58
  }
51
59
  function combineTransforms(...transforms) {
52
- return {
53
- load: (value, method) => {
54
- let inValue = value;
55
- transforms.forEach((transform) => {
56
- if (transform.load) {
57
- inValue = transform.load(inValue, method);
58
- }
59
- });
60
- return inValue;
61
- },
62
- save: (value) => {
63
- let outValue = value;
64
- transforms.forEach((transform) => {
65
- if (transform.save) {
66
- outValue = transform.save(outValue);
67
- }
68
- });
69
- return outValue;
70
- },
71
- };
60
+ return {
61
+ load: (value, method) => {
62
+ let inValue = value;
63
+ transforms.forEach((transform) => {
64
+ if (transform.load) {
65
+ inValue = transform.load(inValue, method);
66
+ }
67
+ });
68
+ return inValue;
69
+ },
70
+ save: (value) => {
71
+ let outValue = value;
72
+ transforms.forEach((transform) => {
73
+ if (transform.save) {
74
+ outValue = transform.save(outValue);
75
+ }
76
+ });
77
+ return outValue;
78
+ }
79
+ };
72
80
  }
73
- const ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
81
+ var ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
74
82
  function transformStringifyKeys(...keys) {
75
- return {
76
- load: (value) => {
77
- keys.forEach((key) => {
78
- const keyRemote = isObject(key) ? key.from : key;
79
- const keyLocal = isObject(key) ? key.to : key;
80
- const v = value[keyRemote];
81
- if (!isNullOrUndefined(v)) {
82
- value[keyLocal] = isString(v) ? JSON.parse(v) : v;
83
- }
84
- if (keyLocal !== keyRemote) {
85
- delete value[keyRemote];
86
- }
87
- });
88
- return value;
89
- },
90
- save: (value) => {
91
- keys.forEach((key) => {
92
- const keyRemote = isObject(key) ? key.from : key;
93
- const keyLocal = isObject(key) ? key.to : key;
94
- const v = value[keyLocal];
95
- if (!isNullOrUndefined(v) && !isString(v)) {
96
- value[keyRemote] = JSON.stringify(v);
97
- }
98
- if (keyLocal !== keyRemote) {
99
- delete value[keyLocal];
100
- }
101
- });
102
- return value;
103
- },
104
- };
83
+ return {
84
+ load: (value) => {
85
+ keys.forEach((key) => {
86
+ const keyRemote = isObject(key) ? key.from : key;
87
+ const keyLocal = isObject(key) ? key.to : key;
88
+ const v = value[keyRemote];
89
+ if (!isNullOrUndefined(v)) {
90
+ value[keyLocal] = isString(v) ? JSON.parse(v) : v;
91
+ }
92
+ if (keyLocal !== keyRemote) {
93
+ delete value[keyRemote];
94
+ }
95
+ });
96
+ return value;
97
+ },
98
+ save: (value) => {
99
+ keys.forEach((key) => {
100
+ const keyRemote = isObject(key) ? key.from : key;
101
+ const keyLocal = isObject(key) ? key.to : key;
102
+ const v = value[keyLocal];
103
+ if (!isNullOrUndefined(v) && !isString(v)) {
104
+ value[keyRemote] = JSON.stringify(v);
105
+ }
106
+ if (keyLocal !== keyRemote) {
107
+ delete value[keyLocal];
108
+ }
109
+ });
110
+ return value;
111
+ }
112
+ };
105
113
  }
106
114
  function transformStringifyDates(...args) {
107
- return {
108
- load: (value) => {
109
- const keys = args.length > 0 ? args : Object.keys(value);
110
- for (let i = 0; i < keys.length; i++) {
111
- const key = keys[i];
112
- const keyValue = value[key];
113
- if (isString(keyValue) && keyValue.match(ISO8601)) {
114
- value[key] = new Date(keyValue);
115
- }
116
- }
117
- return value;
118
- },
119
- save: (value) => {
120
- const keys = args.length > 0 ? args : Object.keys(value);
121
- for (let i = 0; i < keys.length; i++) {
122
- const key = keys[i];
123
- const keyValue = value[key];
124
- if (isDate(keyValue)) {
125
- value[key] = keyValue.toISOString();
126
- }
127
- }
128
- return value;
129
- },
130
- };
115
+ return {
116
+ load: (value) => {
117
+ const keys = args.length > 0 ? args : Object.keys(value);
118
+ for (let i = 0; i < keys.length; i++) {
119
+ const key = keys[i];
120
+ const keyValue = value[key];
121
+ if (isString(keyValue) && keyValue.match(ISO8601)) {
122
+ value[key] = new Date(keyValue);
123
+ }
124
+ }
125
+ return value;
126
+ },
127
+ save: (value) => {
128
+ const keys = args.length > 0 ? args : Object.keys(value);
129
+ for (let i = 0; i < keys.length; i++) {
130
+ const key = keys[i];
131
+ const keyValue = value[key];
132
+ if (isDate(keyValue)) {
133
+ value[key] = keyValue.toISOString();
134
+ }
135
+ }
136
+ return value;
137
+ }
138
+ };
131
139
  }
132
-
133
140
  function syncObservableAdapter({ get, set }) {
134
- const ret = {};
135
- if (get) {
136
- ret.get = (async (params) => {
137
- try {
138
- let value = get(params);
139
- if (isPromise(value)) {
140
- value = await value;
141
- }
142
- params.onChange({
143
- value,
144
- lastSync: params.lastSync,
145
- mode: params.mode,
146
- });
147
- params.onGet();
148
- // eslint-disable-next-line no-empty
149
- }
150
- catch (_a) { }
141
+ const ret = {};
142
+ if (get) {
143
+ ret.get = async (params) => {
144
+ try {
145
+ let value = get(params);
146
+ if (isPromise(value)) {
147
+ value = await value;
148
+ }
149
+ params.onChange({
150
+ value,
151
+ lastSync: params.lastSync,
152
+ mode: params.mode
151
153
  });
152
- }
153
- if (set) {
154
- ret.set = set;
155
- }
156
- return ret;
154
+ params.onGet();
155
+ } catch (e) {
156
+ }
157
+ };
158
+ }
159
+ if (set) {
160
+ ret.set = set;
161
+ }
162
+ return ret;
157
163
  }
158
164
 
159
- const { createPreviousHandler, clone, getValueAtPath, globalState: globalState$1, symbolLinked: symbolLinked$1, getNode, getNodeValue: getNodeValue$1 } = internal$1;
160
- const mapSyncPlugins = new WeakMap();
161
- const metadatas = new WeakMap();
162
- const promisesLocalSaves = new Set();
165
+ // src/sync/syncObservable.ts
166
+ var { createPreviousHandler, clone, getValueAtPath, globalState, symbolLinked, getNode, getNodeValue } = internal;
167
+ var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
168
+ var metadatas = /* @__PURE__ */ new WeakMap();
169
+ var promisesLocalSaves = /* @__PURE__ */ new Set();
163
170
  function parseLocalConfig(config) {
164
- return config
165
- ? isString(config)
166
- ? { table: config, config: { name: config } }
167
- : { table: config.name, config }
168
- : {};
171
+ return config ? isString(config) ? { table: config, config: { name: config } } : { table: config.name, config } : {};
169
172
  }
170
173
  function doInOrder(arg1, arg2) {
171
- return isPromise(arg1) ? arg1.then(arg2) : arg2(arg1);
174
+ return isPromise(arg1) ? arg1.then(arg2) : arg2(arg1);
172
175
  }
173
176
  function onChangeRemote(cb) {
174
- endBatch(true);
175
- // Remote changes should only update local state
176
- globalState$1.isLoadingRemote = true;
177
- beginBatch();
178
- cb();
179
- // Reset isLoadingRemote before ending the batch so it doesn't
180
- // apply to any side effects
181
- globalState$1.isLoadingRemote = false;
182
- endBatch(true);
177
+ endBatch(true);
178
+ globalState.isLoadingRemote = true;
179
+ beginBatch();
180
+ cb();
181
+ globalState.isLoadingRemote = false;
182
+ endBatch(true);
183
183
  }
184
184
  function transformSaveData(value, path, pathTypes, { transform }) {
185
- if (transform === null || transform === void 0 ? void 0 : transform.save) {
186
- const constructed = constructObjectWithPath(path, pathTypes, value);
187
- const saved = transform.save(constructed);
188
- value = deconstructObjectWithPath(path, pathTypes, saved);
189
- }
190
- return value;
185
+ if (transform == null ? void 0 : transform.save) {
186
+ const constructed = constructObjectWithPath(path, pathTypes, value);
187
+ const saved = transform.save(constructed);
188
+ value = deconstructObjectWithPath(path, pathTypes, saved);
189
+ }
190
+ return value;
191
191
  }
192
192
  function transformLoadData(value, { transform }, doUserTransform, method) {
193
- if (doUserTransform && (transform === null || transform === void 0 ? void 0 : transform.load)) {
194
- value = transform.load(value, method);
195
- }
196
- return value;
193
+ if (doUserTransform && (transform == null ? void 0 : transform.load)) {
194
+ value = transform.load(value, method);
195
+ }
196
+ return value;
197
197
  }
198
198
  async function updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata) {
199
- const saves = Array.from(promisesLocalSaves);
200
- if (saves.length > 0) {
201
- await Promise.all(saves);
202
- }
203
- const { pluginPersist } = localState;
204
- const { table, config } = parseLocalConfig(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.persist);
205
- // Save metadata
206
- const oldMetadata = metadatas.get(value$);
207
- const { lastSync, pending } = newMetadata;
208
- const needsUpdate = pending || (lastSync && (!oldMetadata || lastSync !== oldMetadata.lastSync));
209
- if (needsUpdate) {
210
- const metadata = Object.assign({}, oldMetadata, newMetadata);
211
- metadatas.set(value$, metadata);
212
- if (pluginPersist) {
213
- await pluginPersist.setMetadata(table, metadata, config);
214
- }
215
- if (lastSync) {
216
- syncState.assign({
217
- lastSync: lastSync,
218
- });
219
- }
220
- }
199
+ const saves = Array.from(promisesLocalSaves);
200
+ if (saves.length > 0) {
201
+ await Promise.all(saves);
202
+ }
203
+ const { pluginPersist } = localState;
204
+ const { table, config } = parseLocalConfig(syncOptions == null ? void 0 : syncOptions.persist);
205
+ const oldMetadata = metadatas.get(value$);
206
+ const { lastSync } = newMetadata;
207
+ const metadata = Object.assign({}, oldMetadata, newMetadata);
208
+ metadatas.set(value$, metadata);
209
+ if (pluginPersist) {
210
+ await pluginPersist.setMetadata(table, metadata, config);
211
+ }
212
+ if (lastSync) {
213
+ syncState.assign({
214
+ lastSync
215
+ });
216
+ }
221
217
  }
222
218
  function updateMetadata(value$, localState, syncState, syncOptions, newMetadata) {
223
- if (localState.timeoutSaveMetadata) {
224
- clearTimeout(localState.timeoutSaveMetadata);
225
- }
226
- localState.timeoutSaveMetadata = setTimeout(() => updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata), 0);
219
+ if (localState.timeoutSaveMetadata) {
220
+ clearTimeout(localState.timeoutSaveMetadata);
221
+ }
222
+ localState.timeoutSaveMetadata = setTimeout(
223
+ () => updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata),
224
+ 0
225
+ );
227
226
  }
228
- let _queuedChanges = [];
229
- const _queuedRemoteChanges = new Map();
230
- const _queuedRemoteChangesTimeouts = new Map();
227
+ var _queuedChanges = [];
228
+ var _queuedRemoteChanges = /* @__PURE__ */ new Map();
229
+ var _queuedRemoteChangesTimeouts = /* @__PURE__ */ new Map();
231
230
  function mergeChanges(changes) {
232
- const changesByPath = new Map();
233
- const changesOut = [];
234
- // TODO: This could be even more robust by going deeper into paths like the firebase plugin's _updatePendingSave
235
- for (let i = 0; i < changes.length; i++) {
236
- const change = changes[i];
237
- const pathStr = change.path.join('/');
238
- const existing = changesByPath.get(pathStr);
239
- if (existing) {
240
- // If setting a value back to what it was, no need to save it
241
- if (change.valueAtPath === existing.prevAtPath) {
242
- changesOut.splice(changesOut.indexOf(change), 1);
243
- }
244
- else {
245
- existing.valueAtPath = change.valueAtPath;
246
- }
247
- }
248
- else {
249
- changesByPath.set(pathStr, change);
250
- changesOut.push(change);
251
- }
231
+ const changesByPath = /* @__PURE__ */ new Map();
232
+ const changesOut = [];
233
+ for (let i = 0; i < changes.length; i++) {
234
+ const change = changes[i];
235
+ const pathStr = change.path.join("/");
236
+ const existing = changesByPath.get(pathStr);
237
+ if (existing) {
238
+ if (change.valueAtPath === existing.prevAtPath) {
239
+ changesOut.splice(changesOut.indexOf(change), 1);
240
+ } else {
241
+ existing.valueAtPath = change.valueAtPath;
242
+ }
243
+ } else {
244
+ changesByPath.set(pathStr, change);
245
+ changesOut.push(change);
252
246
  }
253
- return changesOut;
247
+ }
248
+ return changesOut;
254
249
  }
255
250
  function mergeQueuedChanges(allChanges) {
256
- const changesByObsRemote = new Map();
257
- const changesByObsLocal = new Map();
258
- const previousByObs = new Map();
259
- const outRemote = new Map();
260
- const outLocal = new Map();
261
- for (let i = 0; i < allChanges.length; i++) {
262
- const value = allChanges[i];
263
- const { value$: obs, changes, inRemoteChange, getPrevious } = value;
264
- const targetMap = inRemoteChange ? outRemote : outLocal;
265
- const changesMap = inRemoteChange ? changesByObsRemote : changesByObsLocal;
266
- const existing = changesMap.get(obs);
267
- const newChanges = existing ? [...existing, ...changes] : changes;
268
- const merged = mergeChanges(newChanges);
269
- changesMap.set(obs, merged);
270
- value.changes = merged;
271
- if (!previousByObs.has(obs)) {
272
- previousByObs.set(obs, getPrevious());
273
- }
274
- value.valuePrevious = previousByObs.get(obs);
275
- targetMap.set(obs, value);
251
+ const changesByObsRemote = /* @__PURE__ */ new Map();
252
+ const changesByObsLocal = /* @__PURE__ */ new Map();
253
+ const previousByObs = /* @__PURE__ */ new Map();
254
+ const outRemote = /* @__PURE__ */ new Map();
255
+ const outLocal = /* @__PURE__ */ new Map();
256
+ for (let i = 0; i < allChanges.length; i++) {
257
+ const value = allChanges[i];
258
+ const { value$: obs, changes, inRemoteChange, getPrevious } = value;
259
+ const targetMap = inRemoteChange ? outRemote : outLocal;
260
+ const changesMap = inRemoteChange ? changesByObsRemote : changesByObsLocal;
261
+ const existing = changesMap.get(obs);
262
+ const newChanges = existing ? [...existing, ...changes] : changes;
263
+ const merged = mergeChanges(newChanges);
264
+ changesMap.set(obs, merged);
265
+ value.changes = merged;
266
+ if (!previousByObs.has(obs)) {
267
+ previousByObs.set(obs, getPrevious());
276
268
  }
277
- return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
269
+ value.valuePrevious = previousByObs.get(obs);
270
+ targetMap.set(obs, value);
271
+ }
272
+ return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
278
273
  }
279
274
  async function processQueuedChanges() {
280
- var _a;
281
- // Get a local copy of the queued changes and clear the global queue
282
- const queuedChanges = mergeQueuedChanges(_queuedChanges);
283
- _queuedChanges = [];
284
- const pendingSyncOptions = new Set();
285
- for (let i = 0; i < queuedChanges.length; i++) {
286
- const change = queuedChanges[i];
287
- if (!change.inRemoteChange) {
288
- if (!_queuedRemoteChanges.has(change.syncOptions)) {
289
- _queuedRemoteChanges.set(change.syncOptions, []);
290
- }
291
- pendingSyncOptions.add(change.syncOptions);
292
- _queuedRemoteChanges.get(change.syncOptions).push(change);
293
- }
275
+ var _a, _b;
276
+ const queuedChanges = mergeQueuedChanges(_queuedChanges);
277
+ _queuedChanges = [];
278
+ const pendingSyncOptions = /* @__PURE__ */ new Set();
279
+ for (let i = 0; i < queuedChanges.length; i++) {
280
+ const change = queuedChanges[i];
281
+ if (!change.inRemoteChange) {
282
+ if (!_queuedRemoteChanges.has(change.syncOptions)) {
283
+ _queuedRemoteChanges.set(change.syncOptions, []);
284
+ }
285
+ pendingSyncOptions.add(change.syncOptions);
286
+ _queuedRemoteChanges.get(change.syncOptions).push(change);
294
287
  }
295
- // Note: Summary of the order of operations these functions:
296
- // 1. Prepare all changes for saving. This may involve waiting for promises if the user has asynchronous transform.
297
- // We need to prepare all of the changes in the queue before saving so that the saves happen in the correct order,
298
- // since some may take longer to transformSaveData than others.
299
- // 2. Save pending to the metadata table first. If this is the only operation that succeeds, it would try to save
300
- // the current value again on next load, which isn't too bad.
301
- // 3. Save local changes to storage. If they never make it to remote, then on the next load they will be pending
302
- // and attempted again.
303
- // 4. Wait for remote load or error if allowed
304
- // 5. Save to remote
305
- // 6. On successful save, merge changes (if any) back into observable
306
- // 7. Lastly, update metadata to clear pending and update lastSync. Doing this earlier could potentially cause
307
- // sync inconsistences so it's very important that this is last.
308
- const preppedChangesLocal = await Promise.all(queuedChanges.map(prepChangeLocal));
309
- // TODO Clean this up: We only need to prep this now in order to save pending changes, don't need any of the other stuff. Should split that up?
310
- await Promise.all(queuedChanges.map(prepChangeRemote));
311
- await Promise.all(preppedChangesLocal.map(doChangeLocal));
312
- for (const options of pendingSyncOptions) {
313
- const timeout = (_a = options.debounceSet) !== null && _a !== void 0 ? _a : observableSyncConfiguration === null || observableSyncConfiguration === void 0 ? void 0 : observableSyncConfiguration.debounceSet;
314
- const timeoutSaveRemote = _queuedRemoteChangesTimeouts.get(options);
315
- const run = () => processQueuedRemoteChanges(options);
316
- if (timeout) {
317
- if (timeoutSaveRemote) {
318
- clearTimeout(timeoutSaveRemote);
319
- }
320
- _queuedRemoteChangesTimeouts.set(options, setTimeout(run, timeout));
321
- }
322
- else {
323
- run();
324
- }
288
+ }
289
+ const preppedChangesLocal = await Promise.all(queuedChanges.map(prepChangeLocal));
290
+ await Promise.all(queuedChanges.map(prepChangeRemote));
291
+ await Promise.all(preppedChangesLocal.map(doChangeLocal));
292
+ for (const options of pendingSyncOptions) {
293
+ const timeout = (_b = options.debounceSet) != null ? _b : (_a = observableSyncConfiguration) == null ? void 0 : _a.debounceSet;
294
+ const timeoutSaveRemote = _queuedRemoteChangesTimeouts.get(options);
295
+ const run = () => processQueuedRemoteChanges(options);
296
+ if (timeout) {
297
+ if (timeoutSaveRemote) {
298
+ clearTimeout(timeoutSaveRemote);
299
+ }
300
+ _queuedRemoteChangesTimeouts.set(options, setTimeout(run, timeout));
301
+ } else {
302
+ run();
325
303
  }
304
+ }
326
305
  }
327
306
  async function processQueuedRemoteChanges(syncOptions) {
328
- const arr = _queuedRemoteChanges.get(syncOptions);
329
- if (arr === null || arr === void 0 ? void 0 : arr.length) {
330
- const queuedRemoteChanges = mergeQueuedChanges(arr);
331
- _queuedRemoteChanges.set(syncOptions, []);
332
- const preppedChangesRemote = await Promise.all(queuedRemoteChanges.map(prepChangeRemote));
333
- preppedChangesRemote.forEach(doChangeRemote);
334
- }
307
+ const arr = _queuedRemoteChanges.get(syncOptions);
308
+ if (arr == null ? void 0 : arr.length) {
309
+ const queuedRemoteChanges = mergeQueuedChanges(arr);
310
+ _queuedRemoteChanges.set(syncOptions, []);
311
+ const preppedChangesRemote = await Promise.all(queuedRemoteChanges.map(prepChangeRemote));
312
+ preppedChangesRemote.forEach(doChangeRemote);
313
+ }
335
314
  }
336
315
  async function prepChangeLocal(queuedChange) {
337
- const { syncState, changes, localState, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
338
- const persist = syncOptions.persist;
339
- const { pluginSync } = localState;
340
- const { config: configLocal } = parseLocalConfig(persist);
341
- const configRemote = syncOptions;
342
- const saveLocal = (persist === null || persist === void 0 ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
343
- const saveRemote = !!(!inRemoteChange &&
344
- (pluginSync === null || pluginSync === void 0 ? void 0 : pluginSync.set) &&
345
- (configRemote === null || configRemote === void 0 ? void 0 : configRemote.enableSync) !== false &&
346
- syncState.isSyncEnabled.peek());
347
- if (saveLocal || saveRemote) {
348
- if (saveLocal && !syncState.isPersistLoaded.peek()) {
349
- console.error('[legend-state] WARNING: An observable was changed before being loaded from persist', persist);
350
- return undefined;
351
- }
352
- const changesLocal = [];
353
- const changesPaths = new Set();
354
- let promisesTransform = [];
355
- // Reverse order
356
- for (let i = changes.length - 1; i >= 0; i--) {
357
- const { path } = changes[i];
358
- let found = false;
359
- // Optimization to only save the latest update at each path. We might have multiple changes at the same path
360
- // and we only need the latest value, so it starts from the end of the array, skipping any earlier changes
361
- // already processed. If a later change modifies a parent of an earlier change (which happens on delete()
362
- // it should be ignored as it's superseded by the parent modification.
363
- if (changesPaths.size > 0) {
364
- for (let u = 0; u < path.length; u++) {
365
- if (changesPaths.has((u === path.length - 1 ? path : path.slice(0, u + 1)).join('/'))) {
366
- found = true;
367
- break;
368
- }
369
- }
370
- }
371
- if (!found) {
372
- const pathStr = path.join('/');
373
- changesPaths.add(pathStr);
374
- const { prevAtPath, valueAtPath, pathTypes } = changes[i];
375
- if (saveLocal) {
376
- const promiseTransformLocal = transformSaveData(valueAtPath, path, pathTypes, configLocal);
377
- promisesTransform.push(doInOrder(promiseTransformLocal, (valueTransformed) => {
378
- // Prepare the local change with the transformed path/value
379
- changesLocal.push({
380
- path,
381
- pathTypes,
382
- prevAtPath,
383
- valueAtPath: valueTransformed,
384
- pathStr,
385
- });
386
- }));
387
- }
388
- }
389
- }
390
- // If there's any transform promises, wait for them before saving
391
- promisesTransform = promisesTransform.filter(Boolean);
392
- if (promisesTransform.length > 0) {
393
- await Promise.all(promisesTransform);
394
- }
395
- return { queuedChange, changesLocal, saveRemote };
316
+ const { syncState, changes, localState, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
317
+ const persist = syncOptions.persist;
318
+ const { pluginSync } = localState;
319
+ const { config: configLocal } = parseLocalConfig(persist);
320
+ const configRemote = syncOptions;
321
+ const saveLocal = (persist == null ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
322
+ const saveRemote = !!(!inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek());
323
+ if (saveLocal || saveRemote) {
324
+ if (saveLocal && !syncState.isPersistLoaded.peek()) {
325
+ console.error(
326
+ "[legend-state] WARNING: An observable was changed before being loaded from persist",
327
+ persist
328
+ );
329
+ return void 0;
330
+ }
331
+ const changesLocal = [];
332
+ const changesPaths = /* @__PURE__ */ new Set();
333
+ let promisesTransform = [];
334
+ for (let i = changes.length - 1; i >= 0; i--) {
335
+ const { path } = changes[i];
336
+ let found = false;
337
+ if (changesPaths.size > 0) {
338
+ for (let u = 0; u < path.length; u++) {
339
+ if (changesPaths.has((u === path.length - 1 ? path : path.slice(0, u + 1)).join("/"))) {
340
+ found = true;
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ if (!found) {
346
+ const pathStr = path.join("/");
347
+ changesPaths.add(pathStr);
348
+ const { prevAtPath, valueAtPath, pathTypes } = changes[i];
349
+ if (saveLocal) {
350
+ const promiseTransformLocal = transformSaveData(
351
+ valueAtPath,
352
+ path,
353
+ pathTypes,
354
+ configLocal
355
+ );
356
+ promisesTransform.push(
357
+ doInOrder(promiseTransformLocal, (valueTransformed) => {
358
+ changesLocal.push({
359
+ path,
360
+ pathTypes,
361
+ prevAtPath,
362
+ valueAtPath: valueTransformed,
363
+ pathStr
364
+ });
365
+ })
366
+ );
367
+ }
368
+ }
396
369
  }
370
+ promisesTransform = promisesTransform.filter(Boolean);
371
+ if (promisesTransform.length > 0) {
372
+ await Promise.all(promisesTransform);
373
+ }
374
+ return { queuedChange, changesLocal, saveRemote };
375
+ }
397
376
  }
398
377
  async function prepChangeRemote(queuedChange) {
399
- const { syncState, changes, localState, syncOptions: syncOptions, inRemoteChange, isApplyingPending, valuePrevious, } = queuedChange;
400
- const persist = syncOptions.persist;
401
- const { pluginSync } = localState;
402
- const { config: configLocal } = parseLocalConfig(persist);
403
- const configRemote = syncOptions;
404
- const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
405
- const saveRemote = !inRemoteChange && (pluginSync === null || pluginSync === void 0 ? void 0 : pluginSync.set) && (configRemote === null || configRemote === void 0 ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek();
406
- if (saveLocal || saveRemote) {
407
- if (saveLocal && !syncState.isPersistLoaded.peek()) {
408
- console.error('[legend-state] WARNING: An observable was changed before being loaded from persist', persist);
409
- return undefined;
410
- }
411
- const changesRemote = [];
412
- const changesPaths = new Set();
413
- let promisesTransform = [];
414
- // Reverse order
415
- for (let i = changes.length - 1; i >= 0; i--) {
416
- const { path } = changes[i];
417
- let found = false;
418
- // Optimization to only save the latest update at each path. We might have multiple changes at the same path
419
- // and we only need the latest value, so it starts from the end of the array, skipping any earlier changes
420
- // already processed. If a later change modifies a parent of an earlier change (which happens on delete()
421
- // it should be ignored as it's superseded by the parent modification.
422
- if (changesPaths.size > 0) {
423
- for (let u = 0; u < path.length; u++) {
424
- if (changesPaths.has((u === path.length - 1 ? path : path.slice(0, u + 1)).join('/'))) {
425
- found = true;
426
- break;
427
- }
378
+ const {
379
+ syncState,
380
+ changes,
381
+ localState,
382
+ syncOptions,
383
+ inRemoteChange,
384
+ isApplyingPending,
385
+ valuePrevious
386
+ } = queuedChange;
387
+ const persist = syncOptions.persist;
388
+ const { pluginSync } = localState;
389
+ const { config: configLocal } = parseLocalConfig(persist);
390
+ const configRemote = syncOptions;
391
+ const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
392
+ const saveRemote = !inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek();
393
+ if (saveLocal || saveRemote) {
394
+ if (saveLocal && !syncState.isPersistLoaded.peek()) {
395
+ console.error(
396
+ "[legend-state] WARNING: An observable was changed before being loaded from persist",
397
+ persist
398
+ );
399
+ return void 0;
400
+ }
401
+ const changesRemote = [];
402
+ const changesPaths = /* @__PURE__ */ new Set();
403
+ let promisesTransform = [];
404
+ for (let i = changes.length - 1; i >= 0; i--) {
405
+ const { path } = changes[i];
406
+ let found = false;
407
+ if (changesPaths.size > 0) {
408
+ for (let u = 0; u < path.length; u++) {
409
+ if (changesPaths.has((u === path.length - 1 ? path : path.slice(0, u + 1)).join("/"))) {
410
+ found = true;
411
+ break;
412
+ }
413
+ }
414
+ }
415
+ if (!found) {
416
+ const pathStr = path.join("/");
417
+ changesPaths.add(pathStr);
418
+ const { prevAtPath, valueAtPath, pathTypes } = changes[i];
419
+ if (saveRemote) {
420
+ const promiseTransformRemote = transformSaveData(
421
+ valueAtPath,
422
+ path,
423
+ pathTypes,
424
+ configRemote || {}
425
+ );
426
+ promisesTransform.push(
427
+ doInOrder(promiseTransformRemote, (valueTransformed) => {
428
+ var _a;
429
+ if (!localState.pendingChanges) {
430
+ localState.pendingChanges = {};
431
+ }
432
+ let found2 = false;
433
+ for (let i2 = 0; !found2 && i2 < path.length - 1; i2++) {
434
+ const pathParent = path.slice(0, i2 + 1).join("/");
435
+ if ((_a = localState.pendingChanges[pathParent]) == null ? void 0 : _a.v) {
436
+ found2 = true;
437
+ const pathChild = path.slice(i2 + 1);
438
+ const pathTypesChild = pathTypes.slice(i2 + 1);
439
+ setAtPath(
440
+ localState.pendingChanges[pathParent].v,
441
+ pathChild,
442
+ pathTypesChild,
443
+ valueAtPath
444
+ );
428
445
  }
429
- }
430
- if (!found) {
431
- const pathStr = path.join('/');
432
- changesPaths.add(pathStr);
433
- const { prevAtPath, valueAtPath, pathTypes } = changes[i];
434
- if (saveRemote) {
435
- const promiseTransformRemote = transformSaveData(valueAtPath, path, pathTypes, configRemote || {});
436
- promisesTransform.push(doInOrder(promiseTransformRemote, (valueTransformed) => {
437
- var _a;
438
- // Prepare pending changes
439
- if (!localState.pendingChanges) {
440
- localState.pendingChanges = {};
441
- }
442
- // First look for existing pending changes at a higher level than this change
443
- // If they exist then merge this change into it
444
- let found = false;
445
- for (let i = 0; !found && i < path.length - 1; i++) {
446
- const pathParent = path.slice(0, i + 1).join('/');
447
- if ((_a = localState.pendingChanges[pathParent]) === null || _a === void 0 ? void 0 : _a.v) {
448
- found = true;
449
- const pathChild = path.slice(i + 1);
450
- const pathTypesChild = pathTypes.slice(i + 1);
451
- setAtPath(localState.pendingChanges[pathParent].v, pathChild, pathTypesChild, valueAtPath);
452
- }
453
- }
454
- if (!found) {
455
- // If an existing pending change is deeper than this change, just delete it
456
- // in favor of this wider change
457
- for (const key in localState.pendingChanges) {
458
- if (key !== pathStr && key.startsWith(pathStr)) {
459
- delete localState.pendingChanges[key];
460
- }
461
- }
462
- // The "p" saved in pending should be the previous state before changes,
463
- // so don't overwrite it if it already exists
464
- if (!localState.pendingChanges[pathStr]) {
465
- localState.pendingChanges[pathStr] = { p: prevAtPath !== null && prevAtPath !== void 0 ? prevAtPath : null, t: pathTypes };
466
- }
467
- // Pending value is the untransformed value because it gets loaded without transformment
468
- // and forwarded through to onObsChange where it gets transformed before save
469
- localState.pendingChanges[pathStr].v = valueAtPath;
470
- }
471
- // Prepare the remote change with the transformed path/value
472
- changesRemote.push({
473
- path,
474
- pathTypes,
475
- prevAtPath,
476
- valueAtPath: valueTransformed,
477
- pathStr,
478
- valuePrevious,
479
- });
480
- }));
446
+ }
447
+ if (!found2) {
448
+ for (const key in localState.pendingChanges) {
449
+ if (key !== pathStr && key.startsWith(pathStr)) {
450
+ delete localState.pendingChanges[key];
451
+ }
481
452
  }
482
- }
483
- }
484
- // If there's any transform promises, wait for them before saving
485
- promisesTransform = promisesTransform.filter(Boolean);
486
- if (promisesTransform.length > 0) {
487
- await Promise.all(promisesTransform);
488
- }
489
- return { queuedChange, changesRemote };
453
+ if (!localState.pendingChanges[pathStr]) {
454
+ localState.pendingChanges[pathStr] = { p: prevAtPath != null ? prevAtPath : null, t: pathTypes };
455
+ }
456
+ localState.pendingChanges[pathStr].v = valueAtPath;
457
+ }
458
+ changesRemote.push({
459
+ path,
460
+ pathTypes,
461
+ prevAtPath,
462
+ valueAtPath: valueTransformed,
463
+ pathStr,
464
+ valuePrevious
465
+ });
466
+ })
467
+ );
468
+ }
469
+ }
490
470
  }
471
+ promisesTransform = promisesTransform.filter(Boolean);
472
+ if (promisesTransform.length > 0) {
473
+ await Promise.all(promisesTransform);
474
+ }
475
+ return { queuedChange, changesRemote };
476
+ }
491
477
  }
492
478
  async function doChangeLocal(changeInfo) {
493
- if (!changeInfo)
494
- return;
495
- const { queuedChange, changesLocal, saveRemote } = changeInfo;
496
- const { value$: obs, syncState, localState, syncOptions: syncOptions } = queuedChange;
497
- const { pluginPersist } = localState;
498
- const persist = syncOptions.persist;
499
- const { table, config: configLocal } = parseLocalConfig(persist);
500
- const shouldSaveMetadata = persist === null || persist === void 0 ? void 0 : persist.retrySync;
501
- if (saveRemote && shouldSaveMetadata) {
502
- // First save pending changes before saving local or remote
503
- await updateMetadataImmediate(obs, localState, syncState, syncOptions, {
504
- pending: localState.pendingChanges,
505
- });
506
- }
507
- if (changesLocal.length > 0) {
508
- // Save the changes to local cache before saving to remote. They are already marked as pending so
509
- // if remote sync fails or the app is closed before remote sync, it will attempt to sync them on the next load.
510
- let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
511
- if (promiseSet) {
512
- promiseSet = promiseSet.then(() => {
513
- promisesLocalSaves.delete(promiseSet);
514
- });
515
- // Keep track of local save promises so that updateMetadata runs only after everything is saved
516
- promisesLocalSaves.add(promiseSet);
517
- // await the local save before proceeding to save remotely
518
- await promiseSet;
519
- }
479
+ if (!changeInfo)
480
+ return;
481
+ const { queuedChange, changesLocal, saveRemote } = changeInfo;
482
+ const { value$: obs, syncState, localState, syncOptions } = queuedChange;
483
+ const { pluginPersist } = localState;
484
+ const persist = syncOptions.persist;
485
+ const { table, config: configLocal } = parseLocalConfig(persist);
486
+ const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
487
+ if (saveRemote && shouldSaveMetadata) {
488
+ await updateMetadataImmediate(obs, localState, syncState, syncOptions, {
489
+ pending: localState.pendingChanges
490
+ });
491
+ }
492
+ if (changesLocal.length > 0) {
493
+ let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
494
+ if (promiseSet) {
495
+ promiseSet = promiseSet.then(() => {
496
+ promisesLocalSaves.delete(promiseSet);
497
+ });
498
+ promisesLocalSaves.add(promiseSet);
499
+ await promiseSet;
520
500
  }
501
+ }
521
502
  }
522
503
  async function doChangeRemote(changeInfo) {
523
- var _a, _b;
524
- if (!changeInfo)
525
- return;
526
- const { queuedChange, changesRemote } = changeInfo;
527
- const { value$: obs, syncState, localState, syncOptions, valuePrevious: previous } = queuedChange;
528
- const { pluginPersist, pluginSync } = localState;
529
- const persist = syncOptions.persist;
530
- const { table, config: configLocal } = parseLocalConfig(persist);
531
- const { allowSetIfGetError, onBeforeSet, onSetError, waitForSet, onAfterSet } = syncOptions || {};
532
- const shouldSaveMetadata = persist === null || persist === void 0 ? void 0 : persist.retrySync;
533
- if (changesRemote.length > 0) {
534
- // Wait for remote to be ready before saving
535
- await when(() => syncState.isLoaded.get() || (allowSetIfGetError && syncState.error.get()));
536
- if (waitForSet) {
537
- const waitFor = isFunction(waitForSet)
538
- ? waitForSet({ changes: changesRemote, value: obs.peek() })
539
- : waitForSet;
540
- if (waitFor) {
541
- await when(waitFor);
504
+ var _a, _b;
505
+ if (!changeInfo)
506
+ return;
507
+ const { queuedChange, changesRemote } = changeInfo;
508
+ const { value$: obs, syncState, localState, syncOptions, valuePrevious: previous } = queuedChange;
509
+ const { pluginPersist, pluginSync } = localState;
510
+ const persist = syncOptions.persist;
511
+ const { table, config: configLocal } = parseLocalConfig(persist);
512
+ const { allowSetIfGetError, onBeforeSet, onSetError, waitForSet, onAfterSet } = syncOptions || {};
513
+ const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
514
+ if (changesRemote.length > 0) {
515
+ await when(() => syncState.isLoaded.get() || allowSetIfGetError && syncState.error.get());
516
+ if (waitForSet) {
517
+ const waitFor = isFunction(waitForSet) ? waitForSet({ changes: changesRemote, value: obs.peek() }) : waitForSet;
518
+ if (waitFor) {
519
+ await when(waitFor);
520
+ }
521
+ }
522
+ let value = obs.peek();
523
+ const transformSave = (_a = syncOptions == null ? void 0 : syncOptions.transform) == null ? void 0 : _a.save;
524
+ if (transformSave) {
525
+ value = transformSave(clone(value));
526
+ }
527
+ onBeforeSet == null ? void 0 : onBeforeSet();
528
+ localState.numSavesOutstanding = (localState.numSavesOutstanding || 0) + 1;
529
+ let savedPromise = pluginSync.set({
530
+ value$: obs,
531
+ syncState,
532
+ options: syncOptions,
533
+ changes: changesRemote,
534
+ value,
535
+ valuePrevious: previous
536
+ });
537
+ if (isPromise(savedPromise)) {
538
+ savedPromise = savedPromise.catch((err) => onSetError == null ? void 0 : onSetError(err));
539
+ }
540
+ const saved = await savedPromise;
541
+ localState.numSavesOutstanding--;
542
+ if (saved !== void 0) {
543
+ const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
544
+ const { changes, lastSync } = saved;
545
+ if (pathStrs.length > 0) {
546
+ let transformedChanges = void 0;
547
+ const metadata = {};
548
+ if (persist) {
549
+ const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
550
+ const pending = localState.pendingChanges;
551
+ for (let i = 0; i < pathStrs.length; i++) {
552
+ const pathStr = pathStrs[i];
553
+ if (pendingMetadata == null ? void 0 : pendingMetadata[pathStr]) {
554
+ delete pendingMetadata[pathStr];
555
+ metadata.pending = pendingMetadata;
542
556
  }
543
- }
544
- let value = obs.peek();
545
- const transformSave = (_a = syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.transform) === null || _a === void 0 ? void 0 : _a.save;
546
- if (transformSave) {
547
- // Clone value before transforming to ensure it doesn't change observable value
548
- value = transformSave(clone(value));
549
- }
550
- onBeforeSet === null || onBeforeSet === void 0 ? void 0 : onBeforeSet();
551
- localState.numSavesOutstanding = (localState.numSavesOutstanding || 0) + 1;
552
- let savedPromise = pluginSync.set({
553
- value$: obs,
554
- syncState: syncState,
555
- options: syncOptions,
556
- changes: changesRemote,
557
- value,
558
- valuePrevious: previous,
559
- });
560
- if (isPromise(savedPromise)) {
561
- savedPromise = savedPromise.catch((err) => onSetError === null || onSetError === void 0 ? void 0 : onSetError(err));
562
- }
563
- const saved = await savedPromise;
564
- localState.numSavesOutstanding--;
565
- // If this remote save changed anything then update cache and metadata
566
- // Because save happens after a timeout and they're batched together, some calls to save will
567
- // return saved data and others won't, so those can be ignored.
568
- if (saved !== undefined) {
569
- const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
570
- const { changes, lastSync } = saved;
571
- if (pathStrs.length > 0) {
572
- let transformedChanges = undefined;
573
- const metadata = {};
574
- if (persist) {
575
- const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) === null || _b === void 0 ? void 0 : _b.pending;
576
- const pending = localState.pendingChanges;
577
- for (let i = 0; i < pathStrs.length; i++) {
578
- const pathStr = pathStrs[i];
579
- // Clear pending for this path
580
- if (pendingMetadata === null || pendingMetadata === void 0 ? void 0 : pendingMetadata[pathStr]) {
581
- // Remove pending from persisted medata state
582
- delete pendingMetadata[pathStr];
583
- metadata.pending = pendingMetadata;
584
- }
585
- // Clear pending for this path if not already removed by above
586
- // pendingMetadata === pending sometimes
587
- if (pending === null || pending === void 0 ? void 0 : pending[pathStr]) {
588
- // Remove pending from local state
589
- delete pending[pathStr];
590
- }
591
- }
592
- if (lastSync) {
593
- metadata.lastSync = lastSync;
594
- }
595
- }
596
- // Remote can optionally have data that needs to be merged back into the observable,
597
- // for example Firebase may update dateModified with the server timestamp
598
- if (changes && !isEmpty(changes)) {
599
- transformedChanges = transformLoadData(changes, syncOptions, false, 'set');
600
- }
601
- if (localState.numSavesOutstanding > 0) {
602
- if (transformedChanges) {
603
- if (!localState.pendingSaveResults) {
604
- localState.pendingSaveResults = [];
605
- }
606
- localState.pendingSaveResults.push(transformedChanges);
607
- }
608
- }
609
- else {
610
- let allChanges = [...(localState.pendingSaveResults || []), transformedChanges].filter((v) => v !== undefined);
611
- if (allChanges.length > 0) {
612
- if (allChanges.some((change) => isPromise(change))) {
613
- allChanges = await Promise.all(allChanges);
614
- }
615
- onChangeRemote(() => mergeIntoObservable(obs, ...allChanges));
616
- }
617
- if (persist) {
618
- if (shouldSaveMetadata && !isEmpty(metadata)) {
619
- updateMetadata(obs, localState, syncState, syncOptions, metadata);
620
- }
621
- }
622
- localState.pendingSaveResults = [];
623
- }
624
- onAfterSet === null || onAfterSet === void 0 ? void 0 : onAfterSet();
557
+ if (pending == null ? void 0 : pending[pathStr]) {
558
+ delete pending[pathStr];
625
559
  }
560
+ }
561
+ if (lastSync) {
562
+ metadata.lastSync = lastSync;
563
+ }
564
+ }
565
+ if (changes && !isEmpty(changes)) {
566
+ transformedChanges = transformLoadData(changes, syncOptions, false, "set");
567
+ }
568
+ if (localState.numSavesOutstanding > 0) {
569
+ if (transformedChanges) {
570
+ if (!localState.pendingSaveResults) {
571
+ localState.pendingSaveResults = [];
572
+ }
573
+ localState.pendingSaveResults.push(transformedChanges);
574
+ }
575
+ } else {
576
+ let allChanges = [...localState.pendingSaveResults || [], transformedChanges].filter(
577
+ (v) => v !== void 0
578
+ );
579
+ if (allChanges.length > 0) {
580
+ if (allChanges.some((change) => isPromise(change))) {
581
+ allChanges = await Promise.all(allChanges);
582
+ }
583
+ onChangeRemote(() => mergeIntoObservable(obs, ...allChanges));
584
+ }
585
+ if (persist) {
586
+ if (shouldSaveMetadata && !isEmpty(metadata)) {
587
+ updateMetadata(obs, localState, syncState, syncOptions, metadata);
588
+ }
589
+ }
590
+ localState.pendingSaveResults = [];
626
591
  }
592
+ onAfterSet == null ? void 0 : onAfterSet();
593
+ }
627
594
  }
595
+ }
628
596
  }
629
597
  function onObsChange(value$, syncState, localState, syncOptions, { changes, loading, remote, getPrevious }) {
630
- if (!loading) {
631
- const inRemoteChange = remote;
632
- const isApplyingPending = localState.isApplyingPending;
633
- // Queue changes in a microtask so that multiple changes within a frame get run together
634
- _queuedChanges.push({
635
- value$: value$,
636
- syncState,
637
- localState,
638
- syncOptions,
639
- changes,
640
- inRemoteChange,
641
- isApplyingPending: isApplyingPending,
642
- getPrevious,
643
- });
644
- if (_queuedChanges.length === 1) {
645
- queueMicrotask(processQueuedChanges);
646
- }
598
+ if (!loading) {
599
+ const inRemoteChange = remote;
600
+ const isApplyingPending = localState.isApplyingPending;
601
+ _queuedChanges.push({
602
+ value$,
603
+ syncState,
604
+ localState,
605
+ syncOptions,
606
+ changes,
607
+ inRemoteChange,
608
+ isApplyingPending,
609
+ getPrevious
610
+ });
611
+ if (_queuedChanges.length === 1) {
612
+ queueMicrotask(processQueuedChanges);
647
613
  }
614
+ }
648
615
  }
649
616
  async function loadLocal(value$, syncOptions, syncState, localState) {
650
- var _a, _b;
651
- const { persist } = syncOptions;
652
- if (persist) {
653
- const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) === null || _a === void 0 ? void 0 : _a.plugin);
654
- const { table, config } = parseLocalConfig(persist);
655
- const node = getNode(value$);
656
- if (!PersistPlugin) {
657
- throw new Error('Local persist is not configured');
658
- }
659
- // Ensure there's only one instance of the cache plugin
660
- if (!mapSyncPlugins.has(PersistPlugin)) {
661
- const persistPlugin = new PersistPlugin();
662
- const mapValue = { plugin: persistPlugin, initialized: observable(false) };
663
- mapSyncPlugins.set(PersistPlugin, mapValue);
664
- if (persistPlugin.initialize) {
665
- const initializePromise = (_b = persistPlugin.initialize) === null || _b === void 0 ? void 0 : _b.call(persistPlugin, (observableSyncConfiguration === null || observableSyncConfiguration === void 0 ? void 0 : observableSyncConfiguration.persist) || {});
666
- if (isPromise(initializePromise)) {
667
- await initializePromise;
668
- }
669
- }
670
- mapValue.initialized.set(true);
671
- }
672
- const { plugin, initialized: initialized$ } = mapSyncPlugins.get(PersistPlugin);
673
- const persistPlugin = plugin;
674
- localState.pluginPersist = persistPlugin;
675
- if (!initialized$.peek()) {
676
- await when(initialized$);
677
- }
678
- // If cache has an asynchronous load, wait for it
679
- if (persistPlugin.loadTable) {
680
- const promise = persistPlugin.loadTable(table, config);
681
- if (promise) {
682
- await promise;
683
- }
684
- }
685
- // Get current value for init
686
- const prevValue = getNodeValue$1(node);
687
- // Get the value from state
688
- let value = persistPlugin.getTable(table, prevValue, config);
689
- const metadata = persistPlugin.getMetadata(table, config);
690
- if (metadata) {
691
- metadatas.set(value$, metadata);
692
- localState.pendingChanges = metadata.pending;
693
- syncState.assign({
694
- lastSync: metadata.lastSync,
695
- });
696
- }
697
- // Merge the data from local cache into the default state
698
- if (value !== undefined) {
699
- const { transform } = config;
700
- value = transformLoadData(value, { transform }, true, 'get');
701
- if (isPromise(value)) {
702
- value = await value;
703
- }
704
- // isLoadingLocal prevents saving remotely when two different caches
705
- // are set on the same observable
706
- internal$1.globalState.isLoadingLocal = true;
707
- // We want to merge the local data on top of any initial state the object is created with
708
- if (value === null && (!prevValue || prevValue[symbolLinked$1])) {
709
- value$.set(value);
710
- }
711
- else {
712
- mergeIntoObservable(value$, value);
713
- }
714
- internal$1.globalState.isLoadingLocal = false;
715
- }
716
- getNodeValue$1(getNode(node.state)).clearPersist = () => Promise.all([
717
- persistPlugin.deleteTable(table, config),
718
- persistPlugin.deleteMetadata(table, config),
719
- ]);
617
+ var _a, _b, _c;
618
+ const { persist } = syncOptions;
619
+ if (persist) {
620
+ const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
621
+ const { table, config } = parseLocalConfig(persist);
622
+ const node = getNode(value$);
623
+ if (!PersistPlugin) {
624
+ throw new Error("Local persist is not configured");
625
+ }
626
+ if (!mapSyncPlugins.has(PersistPlugin)) {
627
+ const persistPlugin2 = new PersistPlugin();
628
+ const mapValue = { plugin: persistPlugin2, initialized: observable(false) };
629
+ mapSyncPlugins.set(PersistPlugin, mapValue);
630
+ if (persistPlugin2.initialize) {
631
+ const initializePromise = (_c = persistPlugin2.initialize) == null ? void 0 : _c.call(persistPlugin2, ((_b = observableSyncConfiguration) == null ? void 0 : _b.persist) || {});
632
+ if (isPromise(initializePromise)) {
633
+ await initializePromise;
634
+ }
635
+ }
636
+ mapValue.initialized.set(true);
637
+ }
638
+ const { plugin, initialized: initialized$ } = mapSyncPlugins.get(PersistPlugin);
639
+ const persistPlugin = plugin;
640
+ localState.pluginPersist = persistPlugin;
641
+ if (!initialized$.peek()) {
642
+ await when(initialized$);
643
+ }
644
+ if (persistPlugin.loadTable) {
645
+ const promise = persistPlugin.loadTable(table, config);
646
+ if (promise) {
647
+ await promise;
648
+ }
720
649
  }
721
- syncState.isPersistLoaded.set(true);
650
+ const prevValue = getNodeValue(node);
651
+ let value = persistPlugin.getTable(table, prevValue, config);
652
+ const metadata = persistPlugin.getMetadata(table, config);
653
+ if (metadata) {
654
+ metadatas.set(value$, metadata);
655
+ localState.pendingChanges = metadata.pending;
656
+ syncState.assign({
657
+ lastSync: metadata.lastSync
658
+ });
659
+ }
660
+ if (value !== void 0) {
661
+ const { transform } = config;
662
+ value = transformLoadData(value, { transform }, true, "get");
663
+ if (isPromise(value)) {
664
+ value = await value;
665
+ }
666
+ internal.globalState.isLoadingLocal = true;
667
+ if (value === null && (!prevValue || prevValue[symbolLinked])) {
668
+ value$.set(value);
669
+ } else {
670
+ mergeIntoObservable(value$, value);
671
+ }
672
+ internal.globalState.isLoadingLocal = false;
673
+ }
674
+ getNodeValue(getNode(node.state)).clearPersist = () => Promise.all([
675
+ persistPlugin.deleteTable(table, config),
676
+ persistPlugin.deleteMetadata(table, config)
677
+ ]);
678
+ }
679
+ syncState.isPersistLoaded.set(true);
722
680
  }
723
681
  function syncObservable(obs$, syncOptionsOrSynced) {
724
- let syncOptions = syncOptionsOrSynced;
725
- // If it's a synced then get the SyncOptions from it
726
- if (isFunction(syncOptions)) {
727
- syncOptions = syncOptions()[symbolLinked$1];
728
- }
729
- const node = getNode(obs$);
730
- // Merge remote sync options with global options
731
- syncOptions = {
732
- syncMode: 'auto',
733
- ...observableSyncConfiguration,
734
- ...removeNullUndefined(syncOptions || {}),
735
- };
736
- const localState = {};
737
- let sync;
738
- const syncState = (node.state = observable({
739
- isPersistLoaded: false,
740
- isLoaded: !syncOptions.get,
741
- isPersistEnabled: true,
742
- isSyncEnabled: true,
743
- clearPersist: undefined,
744
- sync: () => Promise.resolve(),
745
- getPendingChanges: () => localState.pendingChanges,
746
- }));
747
- loadLocal(obs$, syncOptions, syncState, localState);
748
- localState.pluginSync = syncObservableAdapter(syncOptions);
749
- if (syncOptions.get) {
750
- let isSynced = false;
751
- let isSubscribed = false;
752
- let unsubscribe = undefined;
753
- sync = async () => {
754
- var _a, _b;
755
- if (isSynced && shouldIgnoreUnobserved(node, sync)) {
756
- if (unsubscribe) {
757
- isSubscribed = false;
758
- unsubscribe();
759
- unsubscribe = undefined;
760
- }
761
- return;
762
- }
763
- const lastSync = (_a = metadatas.get(obs$)) === null || _a === void 0 ? void 0 : _a.lastSync;
764
- const pending = localState.pendingChanges;
765
- const get = (_b = localState.pluginSync.get) === null || _b === void 0 ? void 0 : _b.bind(localState.pluginSync);
766
- if (get) {
767
- const runGet = () => {
768
- const onChange = async ({ value, mode, lastSync }) => {
769
- mode = mode || syncOptions.mode || 'set';
770
- if (value !== undefined) {
771
- value = transformLoadData(value, syncOptions, true, 'get');
772
- if (isPromise(value)) {
773
- value = await value;
774
- }
775
- const pending = localState.pendingChanges;
776
- const currentValue = obs$.peek();
777
- if (pending) {
778
- let didChangeMetadata = false;
779
- Object.keys(pending).forEach((key) => {
780
- const p = key.split('/').filter((p) => p !== '');
781
- const { v, t } = pending[key];
782
- if (t.length === 0 || !value) {
783
- if (isObject(value) && isObject(v)) {
784
- Object.assign(value, v);
785
- }
786
- else {
787
- value = v;
788
- }
789
- }
790
- else if (value[p[0]] !== undefined) {
791
- const curValue = getValueAtPath(currentValue, p);
792
- const newValue = getValueAtPath(value, p);
793
- if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
794
- delete pending[key];
795
- didChangeMetadata = true;
796
- }
797
- else {
798
- value = setAtPath(value, p, t, v, 'merge', obs$.peek(), (path, value) => {
799
- delete pending[key];
800
- pending[path.join('/')] = {
801
- p: null,
802
- v: value,
803
- t: t.slice(0, path.length),
804
- };
805
- });
806
- }
807
- }
808
- });
809
- if (didChangeMetadata) {
810
- updateMetadata(obs$, localState, syncState, syncOptions, {
811
- pending,
812
- });
813
- }
814
- }
815
- onChangeRemote(() => {
816
- if (mode === 'assign' && isObject(value)) {
817
- obs$.assign(value);
818
- }
819
- else if (mode === 'append' && isArray(value)) {
820
- obs$.push(...value);
821
- }
822
- else if (mode === 'prepend' && isArray(value)) {
823
- obs$.splice(0, 0, ...value);
824
- }
825
- else if (mode === 'merge') {
826
- mergeIntoObservable(obs$, value);
827
- }
828
- else {
829
- obs$.set(value);
830
- }
831
- });
832
- }
833
- if (lastSync && syncOptions.persist) {
834
- updateMetadata(obs$, localState, syncState, syncOptions, {
835
- lastSync,
836
- });
682
+ let syncOptions = syncOptionsOrSynced;
683
+ if (isFunction(syncOptions)) {
684
+ syncOptions = syncOptions()[symbolLinked];
685
+ }
686
+ const node = getNode(obs$);
687
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
688
+ throw new Error("[legend-state] syncObservable called with undefined observable");
689
+ }
690
+ syncOptions = mergeIntoObservable(
691
+ {
692
+ syncMode: "auto"
693
+ },
694
+ observableSyncConfiguration,
695
+ removeNullUndefined(syncOptions || {})
696
+ );
697
+ const localState = {};
698
+ let sync;
699
+ const syncState = node.state = observable({
700
+ isPersistLoaded: false,
701
+ isLoaded: !syncOptions.get,
702
+ isPersistEnabled: true,
703
+ isSyncEnabled: true,
704
+ clearPersist: void 0,
705
+ sync: () => Promise.resolve(),
706
+ getPendingChanges: () => localState.pendingChanges
707
+ });
708
+ loadLocal(obs$, syncOptions, syncState, localState);
709
+ localState.pluginSync = syncObservableAdapter(syncOptions);
710
+ if (syncOptions.get) {
711
+ let isSynced = false;
712
+ let isSubscribed = false;
713
+ let unsubscribe = void 0;
714
+ sync = async () => {
715
+ var _a, _b;
716
+ if (isSynced && shouldIgnoreUnobserved(node, sync)) {
717
+ if (unsubscribe) {
718
+ isSubscribed = false;
719
+ unsubscribe();
720
+ unsubscribe = void 0;
721
+ }
722
+ return;
723
+ }
724
+ const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
725
+ const pending = localState.pendingChanges;
726
+ const get = (_b = localState.pluginSync.get) == null ? void 0 : _b.bind(localState.pluginSync);
727
+ if (get) {
728
+ const runGet = () => {
729
+ const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
730
+ mode = mode || syncOptions.mode || "set";
731
+ if (value !== void 0) {
732
+ value = transformLoadData(value, syncOptions, true, "get");
733
+ if (isPromise(value)) {
734
+ value = await value;
735
+ }
736
+ const pending2 = localState.pendingChanges;
737
+ const currentValue = obs$.peek();
738
+ if (pending2) {
739
+ let didChangeMetadata = false;
740
+ Object.keys(pending2).forEach((key) => {
741
+ const p = key.split("/").filter((p2) => p2 !== "");
742
+ const { v, t } = pending2[key];
743
+ if (t.length === 0 || !value) {
744
+ if (isObject(value) && isObject(v)) {
745
+ Object.assign(value, v);
746
+ } else {
747
+ value = v;
748
+ }
749
+ } else if (value[p[0]] !== void 0) {
750
+ const curValue = getValueAtPath(currentValue, p);
751
+ const newValue = getValueAtPath(value, p);
752
+ if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
753
+ delete pending2[key];
754
+ didChangeMetadata = true;
755
+ } else {
756
+ value = setAtPath(
757
+ value,
758
+ p,
759
+ t,
760
+ v,
761
+ "merge",
762
+ obs$.peek(),
763
+ (path, value2) => {
764
+ delete pending2[key];
765
+ pending2[path.join("/")] = {
766
+ p: null,
767
+ v: value2,
768
+ t: t.slice(0, path.length)
769
+ };
837
770
  }
838
- };
839
- get({
840
- state: syncState,
841
- value$: obs$,
842
- options: syncOptions,
843
- lastSync,
844
- dateModified: lastSync,
845
- onError: (error) => {
846
- var _a;
847
- (_a = syncOptions.onGetError) === null || _a === void 0 ? void 0 : _a.call(syncOptions, error);
848
- },
849
- onGet: () => {
850
- node.state.assign({
851
- isLoaded: true,
852
- error: undefined,
853
- });
854
- },
855
- onChange,
856
- });
857
- if (!isSubscribed && syncOptions.subscribe) {
858
- isSubscribed = true;
859
- unsubscribe = syncOptions.subscribe({
860
- node,
861
- value$: obs$,
862
- update: (params) => {
863
- when(node.state.isLoaded, () => {
864
- params.mode || (params.mode = syncOptions.mode || 'merge');
865
- onChange(params);
866
- });
867
- },
868
- refresh: () => when(node.state.isLoaded, sync),
869
- });
771
+ );
870
772
  }
871
- };
872
- runGet();
873
- }
874
- else {
875
- node.state.assign({
876
- isLoaded: true,
877
- error: undefined,
773
+ }
878
774
  });
879
- }
880
- if (!isSynced) {
881
- isSynced = true;
882
- // Wait for remote to be ready before saving pending
883
- await when(() => syncState.isLoaded.get() || (syncOptions.allowSetIfGetError && syncState.error.get()));
884
- if (pending && !isEmpty(pending)) {
885
- localState.isApplyingPending = true;
886
- const keys = Object.keys(pending);
887
- // Bundle up all the changes from pending
888
- const changes = [];
889
- for (let i = 0; i < keys.length; i++) {
890
- const key = keys[i];
891
- const path = key.split('/').filter((p) => p !== '');
892
- const { p, v, t } = pending[key];
893
- changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
894
- }
895
- // Send the changes into onObsChange so that they get synced remotely
896
- const value = getNodeValue$1(node);
897
- onObsChange(obs$, syncState, localState, syncOptions, {
898
- value,
899
- loading: false,
900
- remote: false,
901
- getPrevious: createPreviousHandler(value, changes),
902
- changes,
903
- });
904
- localState.isApplyingPending = false;
775
+ if (didChangeMetadata) {
776
+ updateMetadata(obs$, localState, syncState, syncOptions, {
777
+ pending: pending2
778
+ });
779
+ }
780
+ }
781
+ onChangeRemote(() => {
782
+ if (mode === "assign" && isObject(value)) {
783
+ obs$.assign(value);
784
+ } else if (mode === "append" && isArray(value)) {
785
+ obs$.push(...value);
786
+ } else if (mode === "prepend" && isArray(value)) {
787
+ obs$.splice(0, 0, ...value);
788
+ } else if (mode === "merge") {
789
+ mergeIntoObservable(obs$, value);
790
+ } else {
791
+ obs$.set(value);
905
792
  }
793
+ });
906
794
  }
907
- };
908
- syncState.assign({ sync });
909
- }
910
- // Wait for this node and all parent nodes up the hierarchy to be loaded
911
- const onAllPersistLoaded = () => {
912
- var _a, _b;
913
- let parentNode = node;
914
- while (parentNode) {
915
- if (((_b = (_a = parentNode.state) === null || _a === void 0 ? void 0 : _a.isPersistLoaded) === null || _b === void 0 ? void 0 : _b.get()) === false) {
916
- return false;
795
+ if (lastSync2 && syncOptions.persist) {
796
+ updateMetadata(obs$, localState, syncState, syncOptions, {
797
+ lastSync: lastSync2
798
+ });
917
799
  }
918
- parentNode = parentNode.parent;
919
- }
920
- return true;
800
+ };
801
+ get({
802
+ state: syncState,
803
+ value$: obs$,
804
+ options: syncOptions,
805
+ lastSync,
806
+ dateModified: lastSync,
807
+ onError: (error) => {
808
+ var _a2;
809
+ (_a2 = syncOptions.onGetError) == null ? void 0 : _a2.call(syncOptions, error);
810
+ },
811
+ onGet: () => {
812
+ node.state.assign({
813
+ isLoaded: true,
814
+ error: void 0
815
+ });
816
+ },
817
+ onChange
818
+ });
819
+ if (!isSubscribed && syncOptions.subscribe) {
820
+ isSubscribed = true;
821
+ unsubscribe = syncOptions.subscribe({
822
+ node,
823
+ value$: obs$,
824
+ update: (params) => {
825
+ when(node.state.isLoaded, () => {
826
+ params.mode || (params.mode = syncOptions.mode || "merge");
827
+ onChange(params);
828
+ });
829
+ },
830
+ refresh: () => when(node.state.isLoaded, sync)
831
+ });
832
+ }
833
+ };
834
+ runGet();
835
+ } else {
836
+ node.state.assign({
837
+ isLoaded: true,
838
+ error: void 0
839
+ });
840
+ }
841
+ if (!isSynced) {
842
+ isSynced = true;
843
+ await when(() => syncState.isLoaded.get() || syncOptions.allowSetIfGetError && syncState.error.get());
844
+ if (pending && !isEmpty(pending)) {
845
+ localState.isApplyingPending = true;
846
+ const keys = Object.keys(pending);
847
+ const changes = [];
848
+ for (let i = 0; i < keys.length; i++) {
849
+ const key = keys[i];
850
+ const path = key.split("/").filter((p2) => p2 !== "");
851
+ const { p, v, t } = pending[key];
852
+ changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
853
+ }
854
+ const value = getNodeValue(node);
855
+ onObsChange(obs$, syncState, localState, syncOptions, {
856
+ value,
857
+ loading: false,
858
+ remote: false,
859
+ getPrevious: createPreviousHandler(value, changes),
860
+ changes
861
+ });
862
+ localState.isApplyingPending = false;
863
+ }
864
+ }
921
865
  };
922
- // When all is loaded locally we can start syncing and listening for changes
923
- when(onAllPersistLoaded, function () {
924
- // If remote is not manual, then sync() is called automatically
925
- if (syncOptions.get && syncOptions.syncMode === 'auto') {
926
- sync();
927
- }
928
- if ((syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.set) || (syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.persist)) {
929
- obs$.onChange(onObsChange.bind(this, obs$, syncState, localState, syncOptions));
930
- }
931
- });
932
- return syncState;
866
+ syncState.assign({ sync });
867
+ }
868
+ const onAllPersistLoaded = () => {
869
+ var _a, _b;
870
+ let parentNode = node;
871
+ while (parentNode) {
872
+ if (((_b = (_a = parentNode.state) == null ? void 0 : _a.isPersistLoaded) == null ? void 0 : _b.get()) === false) {
873
+ return false;
874
+ }
875
+ parentNode = parentNode.parent;
876
+ }
877
+ return true;
878
+ };
879
+ when(onAllPersistLoaded, function() {
880
+ if (syncOptions.get && syncOptions.syncMode === "auto") {
881
+ sync();
882
+ }
883
+ if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
884
+ obs$.onChange(
885
+ onObsChange.bind(this, obs$, syncState, localState, syncOptions)
886
+ );
887
+ }
888
+ });
889
+ return syncState;
933
890
  }
934
-
935
- const { getProxy, globalState, runWithRetry, symbolLinked, setNodeValue, getNodeValue } = internal$1;
891
+ var { getProxy, globalState: globalState2, runWithRetry, symbolLinked: symbolLinked2, setNodeValue, getNodeValue: getNodeValue2 } = internal;
936
892
  function enableActivateSyncedNode() {
937
- globalState.activateSyncedNode = function activateSyncedNode(node, newValue) {
938
- const obs$ = getProxy(node);
939
- if (node.activationState) {
940
- // If it is a Synced
941
- const { get, initial, set, retry } = node.activationState;
942
- let onChange = undefined;
943
- const pluginRemote = {};
944
- let promiseReturn = undefined;
945
- // Not sure why this disable is needed, but it's needed to make the linter happy
946
- // eslint-disable-next-line prefer-const
947
- let syncState;
948
- const refresh = () => syncState === null || syncState === void 0 ? void 0 : syncState.sync();
949
- if (get) {
950
- pluginRemote.get = (params) => {
951
- var _a;
952
- onChange = params.onChange;
953
- const updateLastSync = (lastSync) => (params.lastSync = lastSync);
954
- const existingValue = getNodeValue(node);
955
- const value = runWithRetry(node, { attemptNum: 0, retry: retry || ((_a = params.options) === null || _a === void 0 ? void 0 : _a.retry) }, () => {
956
- const paramsToGet = {
957
- value: isFunction(existingValue) || (existingValue === null || existingValue === void 0 ? void 0 : existingValue[symbolLinked]) ? undefined : existingValue,
958
- lastSync: params.lastSync,
959
- updateLastSync,
960
- mode: params.mode,
961
- refresh,
962
- };
963
- const ret = get(paramsToGet);
964
- params.mode = paramsToGet.mode;
965
- return ret;
966
- });
967
- promiseReturn = value;
968
- return value;
969
- };
970
- }
971
- if (set) {
972
- // TODO: Work out these types better
973
- pluginRemote.set = async (params) => {
974
- var _a, _b;
975
- if ((_a = node.state) === null || _a === void 0 ? void 0 : _a.isLoaded.get()) {
976
- const retryAttempts = { attemptNum: 0, retry: retry || ((_b = params.options) === null || _b === void 0 ? void 0 : _b.retry) };
977
- return runWithRetry(node, retryAttempts, async (retryEvent) => {
978
- let changes = {};
979
- let maxModified = 0;
980
- if (!node.state.isLoaded.peek()) {
981
- await whenReady(node.state.isLoaded);
982
- }
983
- const cancelRetry = () => {
984
- retryEvent.cancel = true;
985
- };
986
- await set({
987
- ...params,
988
- node,
989
- update: (params) => {
990
- const { value, lastSync } = params;
991
- maxModified = Math.max(lastSync || 0, maxModified);
992
- changes = mergeIntoObservable(changes, value);
993
- },
994
- retryNum: retryAttempts.attemptNum,
995
- cancelRetry,
996
- refresh,
997
- fromSubscribe: false,
998
- });
999
- return { changes, lastSync: maxModified || undefined };
1000
- });
1001
- }
1002
- };
1003
- }
1004
- const nodeVal = getNodeValue(node);
1005
- if (promiseReturn !== undefined) {
1006
- newValue = promiseReturn;
1007
- }
1008
- else if (nodeVal !== undefined && !isFunction(nodeVal)) {
1009
- newValue = nodeVal;
1010
- }
1011
- else {
1012
- newValue = initial;
1013
- }
1014
- setNodeValue(node, promiseReturn ? undefined : newValue);
1015
- // @ts-expect-error TODO fix these types
1016
- syncState = syncObservable(obs$, { ...node.activationState, ...pluginRemote });
1017
- return { update: onChange, value: newValue };
1018
- }
1019
- else {
1020
- // If it is not a Synced
1021
- let update = undefined;
1022
- const get = async (params) => {
1023
- update = params.refresh;
1024
- if (isPromise(newValue)) {
1025
- try {
1026
- newValue = await newValue;
1027
- }
1028
- catch (_a) {
1029
- // TODO Once we have global retry settings this should retry
1030
- }
1031
- }
1032
- return newValue;
893
+ globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
894
+ const obs$ = getProxy(node);
895
+ if (node.activationState) {
896
+ const { get, initial, set, retry } = node.activationState;
897
+ let onChange = void 0;
898
+ const pluginRemote = {};
899
+ let promiseReturn = void 0;
900
+ let syncState;
901
+ const refresh = () => syncState == null ? void 0 : syncState.sync();
902
+ if (get) {
903
+ pluginRemote.get = (params) => {
904
+ var _a;
905
+ onChange = params.onChange;
906
+ const updateLastSync = (lastSync) => params.lastSync = lastSync;
907
+ const existingValue = getNodeValue2(node);
908
+ const value = runWithRetry(node, { attemptNum: 0, retry: retry || ((_a = params.options) == null ? void 0 : _a.retry) }, () => {
909
+ const paramsToGet = {
910
+ value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked2]) ? void 0 : existingValue,
911
+ lastSync: params.lastSync,
912
+ updateLastSync,
913
+ mode: params.mode,
914
+ refresh
1033
915
  };
1034
- syncObservable(obs$, {
1035
- get,
916
+ const ret = get(paramsToGet);
917
+ params.mode = paramsToGet.mode;
918
+ return ret;
919
+ });
920
+ promiseReturn = value;
921
+ return value;
922
+ };
923
+ }
924
+ if (set) {
925
+ pluginRemote.set = async (params) => {
926
+ var _a, _b;
927
+ if ((_a = node.state) == null ? void 0 : _a.isLoaded.get()) {
928
+ const retryAttempts = { attemptNum: 0, retry: retry || ((_b = params.options) == null ? void 0 : _b.retry) };
929
+ return runWithRetry(node, retryAttempts, async (retryEvent) => {
930
+ let changes = {};
931
+ let maxModified = 0;
932
+ if (!node.state.isLoaded.peek()) {
933
+ await whenReady(node.state.isLoaded);
934
+ }
935
+ const cancelRetry = () => {
936
+ retryEvent.cancel = true;
937
+ };
938
+ await set({
939
+ ...params,
940
+ node,
941
+ update: (params2) => {
942
+ const { value, lastSync } = params2;
943
+ maxModified = Math.max(lastSync || 0, maxModified);
944
+ changes = mergeIntoObservable(changes, value);
945
+ },
946
+ retryNum: retryAttempts.attemptNum,
947
+ cancelRetry,
948
+ refresh,
949
+ fromSubscribe: false
950
+ });
951
+ return { changes, lastSync: maxModified || void 0 };
1036
952
  });
1037
- return { update: update, value: newValue };
1038
- }
1039
- };
953
+ }
954
+ };
955
+ }
956
+ const nodeVal = getNodeValue2(node);
957
+ if (promiseReturn !== void 0) {
958
+ newValue = promiseReturn;
959
+ } else if (nodeVal !== void 0 && !isFunction(nodeVal)) {
960
+ newValue = nodeVal;
961
+ } else {
962
+ newValue = initial;
963
+ }
964
+ setNodeValue(node, promiseReturn ? void 0 : newValue);
965
+ syncState = syncObservable(obs$, { ...node.activationState, ...pluginRemote });
966
+ return { update: onChange, value: newValue };
967
+ } else {
968
+ let update = void 0;
969
+ const get = async (params) => {
970
+ update = params.refresh;
971
+ if (isPromise(newValue)) {
972
+ try {
973
+ newValue = await newValue;
974
+ } catch (e) {
975
+ }
976
+ }
977
+ return newValue;
978
+ };
979
+ syncObservable(obs$, {
980
+ get
981
+ });
982
+ return { update, value: newValue };
983
+ }
984
+ };
1040
985
  }
1041
986
 
987
+ // src/sync/synced.ts
1042
988
  function synced(params) {
1043
- installPersistActivateNode();
1044
- if (isFunction(params)) {
1045
- params = { get: params };
1046
- }
1047
- return linked({ ...params, synced: true });
989
+ installPersistActivateNode();
990
+ if (isFunction(params)) {
991
+ params = { get: params };
992
+ }
993
+ return linked({ ...params, synced: true });
1048
994
  }
1049
- let didInstall = false;
995
+ var didInstall = false;
1050
996
  function installPersistActivateNode() {
1051
- if (!didInstall) {
1052
- enableActivateSyncedNode();
1053
- didInstall = true;
1054
- }
997
+ if (!didInstall) {
998
+ enableActivateSyncedNode();
999
+ didInstall = true;
1000
+ }
1055
1001
  }
1056
1002
 
1003
+ // sync.ts
1057
1004
  function isInRemoteChange() {
1058
- return internal$1.globalState.isLoadingRemote;
1005
+ return internal.globalState.isLoadingRemote;
1059
1006
  }
1060
- const internal = {
1061
- observableSyncConfiguration,
1007
+ var internal3 = {
1008
+ observableSyncConfiguration
1062
1009
  };
1063
1010
 
1064
- export { combineTransforms, configureObservableSync, deepEqual, diffObjects, internal, isInRemoteChange, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
1065
- //# sourceMappingURL=sync.mjs.map
1011
+ export { combineTransforms, configureObservableSync, deepEqual, diffObjects, internal3 as internal, isInRemoteChange, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };