@legendapp/state 3.0.0-alpha.0 → 3.0.0-alpha.2

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