@legendapp/state 3.0.0-alpha.4 → 3.0.0-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.DS_Store +0 -0
- package/CHANGELOG.md +831 -1
- package/LICENSE +21 -1
- package/README.md +141 -1
- package/babel.js +0 -2
- package/babel.mjs +0 -2
- package/config/configureLegendState.d.mts +13 -0
- package/config/configureLegendState.d.ts +13 -0
- package/config/configureLegendState.js +45 -0
- package/config/configureLegendState.mjs +43 -0
- package/config/enable$GetSet.js +2 -1
- package/config/enable$GetSet.mjs +2 -1
- package/config/enableReactTracking.js +2 -1
- package/config/enableReactTracking.mjs +2 -1
- package/config/enableReactUse.js +2 -1
- package/config/enableReactUse.mjs +2 -1
- package/config/enable_PeekAssign.js +2 -1
- package/config/enable_PeekAssign.mjs +2 -1
- package/helpers/trackHistory.js +2 -2
- package/helpers/trackHistory.mjs +2 -2
- package/index.d.mts +106 -81
- package/index.d.ts +106 -81
- package/index.js +347 -335
- package/index.mjs +344 -333
- package/package.json +36 -1
- package/persist-plugins/async-storage.d.mts +6 -3
- package/persist-plugins/async-storage.d.ts +6 -3
- package/persist-plugins/async-storage.js +8 -4
- package/persist-plugins/async-storage.mjs +8 -5
- package/persist-plugins/indexeddb.d.mts +6 -4
- package/persist-plugins/indexeddb.d.ts +6 -4
- package/persist-plugins/indexeddb.js +35 -15
- package/persist-plugins/indexeddb.mjs +35 -16
- package/persist-plugins/mmkv.d.mts +5 -1
- package/persist-plugins/mmkv.d.ts +5 -1
- package/persist-plugins/mmkv.js +10 -5
- package/persist-plugins/mmkv.mjs +10 -6
- package/react-reactive/enableReactComponents.d.mts +9 -0
- package/react-reactive/enableReactComponents.d.ts +9 -0
- package/react-reactive/enableReactComponents.js +19 -0
- package/react-reactive/enableReactComponents.mjs +17 -0
- package/react-reactive/enableReactNativeComponents.d.mts +22 -0
- package/react-reactive/enableReactNativeComponents.d.ts +22 -0
- package/react-reactive/enableReactNativeComponents.js +53 -0
- package/react-reactive/enableReactNativeComponents.mjs +51 -0
- package/react-reactive/enableReactive.d.mts +5 -0
- package/react-reactive/enableReactive.d.ts +5 -0
- package/react-reactive/enableReactive.js +24 -0
- package/react-reactive/enableReactive.mjs +22 -0
- package/react-reactive/enableReactive.native.d.mts +5 -0
- package/react-reactive/enableReactive.native.d.ts +5 -0
- package/react-reactive/enableReactive.native.js +58 -0
- package/react-reactive/enableReactive.native.mjs +56 -0
- package/react-reactive/enableReactive.web.d.mts +5 -0
- package/react-reactive/enableReactive.web.d.ts +5 -0
- package/react-reactive/enableReactive.web.js +58 -0
- package/react-reactive/enableReactive.web.mjs +56 -0
- package/react.d.mts +39 -34
- package/react.d.ts +39 -34
- package/react.js +54 -27
- package/react.mjs +55 -28
- package/sync-plugins/crud.d.mts +21 -24
- package/sync-plugins/crud.d.ts +21 -24
- package/sync-plugins/crud.js +241 -140
- package/sync-plugins/crud.mjs +243 -142
- package/sync-plugins/fetch.js +12 -8
- package/sync-plugins/fetch.mjs +13 -9
- package/sync-plugins/firebase.d.mts +27 -0
- package/sync-plugins/firebase.d.ts +27 -0
- package/sync-plugins/firebase.js +373 -0
- package/sync-plugins/firebase.mjs +368 -0
- package/sync-plugins/keel.d.mts +43 -26
- package/sync-plugins/keel.d.ts +43 -26
- package/sync-plugins/keel.js +145 -100
- package/sync-plugins/keel.mjs +147 -100
- package/sync-plugins/supabase.d.mts +19 -9
- package/sync-plugins/supabase.d.ts +19 -9
- package/sync-plugins/supabase.js +52 -22
- package/sync-plugins/supabase.mjs +53 -23
- package/sync-plugins/tanstack-query.d.mts +2 -2
- package/sync-plugins/tanstack-query.d.ts +2 -2
- package/sync-plugins/tanstack-query.js +22 -5
- package/sync-plugins/tanstack-query.mjs +22 -5
- package/sync-plugins/tanstack-react-query.d.mts +1 -1
- package/sync-plugins/tanstack-react-query.d.ts +1 -1
- package/sync-plugins/tanstack-react-query.js +8 -1
- package/sync-plugins/tanstack-react-query.mjs +8 -1
- package/sync.d.mts +74 -200
- package/sync.d.ts +74 -200
- package/sync.js +510 -307
- package/sync.mjs +516 -313
- package/types/babel.d.ts +12 -1
- /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
- /package/config/{enable_GetSet.d.ts → enable$GetSet.d.ts} +0 -0
package/sync.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction,
|
|
2
|
-
|
|
3
|
-
// sync.ts
|
|
1
|
+
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction, syncState, when, linked, internal, observable, isPromise as isPromise$1, mergeIntoObservable, isEmpty, shouldIgnoreUnobserved, whenReady, trackSelector, constructObjectWithPath, setAtPath, isPlainObject, ObservableHint, isArray } from '@legendapp/state';
|
|
4
2
|
|
|
5
3
|
// src/sync/configureObservableSync.ts
|
|
6
4
|
var observableSyncConfiguration = {};
|
|
@@ -137,41 +135,87 @@ function transformStringifyDates(...args) {
|
|
|
137
135
|
}
|
|
138
136
|
};
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
138
|
+
|
|
139
|
+
// src/is.ts
|
|
140
|
+
function isPromise(obj) {
|
|
141
|
+
return obj instanceof Promise;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/sync/retry.ts
|
|
145
|
+
function calculateRetryDelay(retryOptions, retryNum) {
|
|
146
|
+
const { backoff, delay = 1e3, infinite, times = 3, maxDelay = 3e4 } = retryOptions;
|
|
147
|
+
if (infinite || retryNum < times) {
|
|
148
|
+
const delayTime = Math.min(delay * (backoff === "constant" ? 1 : 2 ** retryNum), maxDelay);
|
|
149
|
+
return delayTime;
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
function createRetryTimeout(retryOptions, retryNum, fn) {
|
|
154
|
+
const delayTime = calculateRetryDelay(retryOptions, retryNum);
|
|
155
|
+
if (delayTime) {
|
|
156
|
+
return setTimeout(fn, delayTime);
|
|
157
|
+
} else {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
var mapRetryTimeouts = /* @__PURE__ */ new Map();
|
|
162
|
+
function runWithRetry(state, retryOptions, fn, onError) {
|
|
163
|
+
let value = fn(state);
|
|
164
|
+
if (isPromise(value) && retryOptions) {
|
|
165
|
+
let timeoutRetry;
|
|
166
|
+
if (mapRetryTimeouts.has(state.node)) {
|
|
167
|
+
clearTimeout(mapRetryTimeouts.get(state.node));
|
|
168
|
+
}
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const run = () => {
|
|
171
|
+
value.then((val) => {
|
|
172
|
+
resolve(val);
|
|
173
|
+
}).catch((error) => {
|
|
174
|
+
state.retryNum++;
|
|
175
|
+
if (timeoutRetry) {
|
|
176
|
+
clearTimeout(timeoutRetry);
|
|
177
|
+
}
|
|
178
|
+
if (onError) {
|
|
179
|
+
onError(error, state);
|
|
180
|
+
}
|
|
181
|
+
if (!state.cancelRetry) {
|
|
182
|
+
const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
|
|
183
|
+
value = fn(state);
|
|
184
|
+
run();
|
|
185
|
+
});
|
|
186
|
+
if (timeout === false) {
|
|
187
|
+
state.cancelRetry = true;
|
|
188
|
+
reject(error);
|
|
189
|
+
} else {
|
|
190
|
+
mapRetryTimeouts.set(state.node, timeout);
|
|
191
|
+
timeoutRetry = timeout;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
153
194
|
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
};
|
|
195
|
+
};
|
|
196
|
+
run();
|
|
197
|
+
});
|
|
158
198
|
}
|
|
159
|
-
|
|
160
|
-
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
async function waitForSet(waitForSet2, changes, value, params = {}) {
|
|
202
|
+
const waitFn = isFunction(waitForSet2) ? waitForSet2({ changes, value, ...params }) : waitForSet2;
|
|
203
|
+
if (waitFn) {
|
|
204
|
+
await when(waitFn);
|
|
161
205
|
}
|
|
162
|
-
return ret;
|
|
163
206
|
}
|
|
164
207
|
|
|
165
208
|
// src/sync/syncObservable.ts
|
|
166
|
-
var {
|
|
209
|
+
var { clone, deepMerge, getNode, getNodeValue, getValueAtPath, globalState, symbolLinked, createPreviousHandler } = internal;
|
|
167
210
|
var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
|
|
211
|
+
var allSyncStates = /* @__PURE__ */ new Map();
|
|
168
212
|
var metadatas = /* @__PURE__ */ new WeakMap();
|
|
169
213
|
var promisesLocalSaves = /* @__PURE__ */ new Set();
|
|
170
214
|
function parseLocalConfig(config) {
|
|
171
215
|
return config ? isString(config) ? { table: config, config: { name: config } } : { table: config.name, config } : {};
|
|
172
216
|
}
|
|
173
217
|
function doInOrder(arg1, arg2) {
|
|
174
|
-
return isPromise(arg1) ? arg1.then(arg2) : arg2(arg1);
|
|
218
|
+
return isPromise$1(arg1) ? arg1.then(arg2) : arg2(arg1);
|
|
175
219
|
}
|
|
176
220
|
function onChangeRemote(cb) {
|
|
177
221
|
endBatch(true);
|
|
@@ -181,13 +225,19 @@ function onChangeRemote(cb) {
|
|
|
181
225
|
globalState.isLoadingRemote = false;
|
|
182
226
|
endBatch(true);
|
|
183
227
|
}
|
|
184
|
-
function transformSaveData(value, path, pathTypes, { transform }) {
|
|
228
|
+
async function transformSaveData(value, path, pathTypes, { transform }) {
|
|
185
229
|
if (transform == null ? void 0 : transform.save) {
|
|
186
230
|
const constructed = constructObjectWithPath(path, pathTypes, value);
|
|
187
|
-
const saved = transform.save(constructed);
|
|
188
|
-
value =
|
|
231
|
+
const saved = await transform.save(constructed);
|
|
232
|
+
value = saved;
|
|
233
|
+
const outPath = [];
|
|
234
|
+
for (let i = 0; i < path.length; i++) {
|
|
235
|
+
outPath[i] = Object.keys(value)[0];
|
|
236
|
+
value = value[outPath[i]];
|
|
237
|
+
}
|
|
238
|
+
path = outPath;
|
|
189
239
|
}
|
|
190
|
-
return value;
|
|
240
|
+
return { value, path };
|
|
191
241
|
}
|
|
192
242
|
function transformLoadData(value, { transform }, doUserTransform, method) {
|
|
193
243
|
if (doUserTransform && (transform == null ? void 0 : transform.load)) {
|
|
@@ -195,13 +245,13 @@ function transformLoadData(value, { transform }, doUserTransform, method) {
|
|
|
195
245
|
}
|
|
196
246
|
return value;
|
|
197
247
|
}
|
|
198
|
-
async function updateMetadataImmediate(value$, localState,
|
|
248
|
+
async function updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata) {
|
|
199
249
|
const saves = Array.from(promisesLocalSaves);
|
|
200
250
|
if (saves.length > 0) {
|
|
201
251
|
await Promise.all(saves);
|
|
202
252
|
}
|
|
203
253
|
const { pluginPersist } = localState;
|
|
204
|
-
const { table, config } = parseLocalConfig(syncOptions
|
|
254
|
+
const { table, config } = parseLocalConfig(syncOptions.persist);
|
|
205
255
|
const oldMetadata = metadatas.get(value$);
|
|
206
256
|
const { lastSync } = newMetadata;
|
|
207
257
|
const metadata = Object.assign({}, oldMetadata, newMetadata);
|
|
@@ -210,17 +260,17 @@ async function updateMetadataImmediate(value$, localState, syncState, syncOption
|
|
|
210
260
|
await pluginPersist.setMetadata(table, metadata, config);
|
|
211
261
|
}
|
|
212
262
|
if (lastSync) {
|
|
213
|
-
|
|
263
|
+
syncState2.assign({
|
|
214
264
|
lastSync
|
|
215
265
|
});
|
|
216
266
|
}
|
|
217
267
|
}
|
|
218
|
-
function updateMetadata(value$, localState,
|
|
268
|
+
function updateMetadata(value$, localState, syncState2, syncOptions, newMetadata) {
|
|
219
269
|
if (localState.timeoutSaveMetadata) {
|
|
220
270
|
clearTimeout(localState.timeoutSaveMetadata);
|
|
221
271
|
}
|
|
222
272
|
localState.timeoutSaveMetadata = setTimeout(
|
|
223
|
-
() => updateMetadataImmediate(value$, localState,
|
|
273
|
+
() => updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata),
|
|
224
274
|
0
|
|
225
275
|
);
|
|
226
276
|
}
|
|
@@ -248,26 +298,21 @@ function mergeChanges(changes) {
|
|
|
248
298
|
return changesOut;
|
|
249
299
|
}
|
|
250
300
|
function mergeQueuedChanges(allChanges) {
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const previousByObs = /* @__PURE__ */ new Map();
|
|
301
|
+
const changesByOptionsRemote = /* @__PURE__ */ new Map();
|
|
302
|
+
const changesByOptionsLocal = /* @__PURE__ */ new Map();
|
|
254
303
|
const outRemote = /* @__PURE__ */ new Map();
|
|
255
304
|
const outLocal = /* @__PURE__ */ new Map();
|
|
256
305
|
for (let i = 0; i < allChanges.length; i++) {
|
|
257
306
|
const value = allChanges[i];
|
|
258
|
-
const {
|
|
307
|
+
const { changes, inRemoteChange, syncOptions } = value;
|
|
259
308
|
const targetMap = inRemoteChange ? outRemote : outLocal;
|
|
260
|
-
const changesMap = inRemoteChange ?
|
|
261
|
-
const existing = changesMap.get(
|
|
309
|
+
const changesMap = inRemoteChange ? changesByOptionsRemote : changesByOptionsLocal;
|
|
310
|
+
const existing = changesMap.get(syncOptions);
|
|
262
311
|
const newChanges = existing ? [...existing, ...changes] : changes;
|
|
263
312
|
const merged = mergeChanges(newChanges);
|
|
264
|
-
changesMap.set(
|
|
313
|
+
changesMap.set(syncOptions, merged);
|
|
265
314
|
value.changes = merged;
|
|
266
|
-
|
|
267
|
-
previousByObs.set(obs, getPrevious());
|
|
268
|
-
}
|
|
269
|
-
value.valuePrevious = previousByObs.get(obs);
|
|
270
|
-
targetMap.set(obs, value);
|
|
315
|
+
targetMap.set(syncOptions, value);
|
|
271
316
|
}
|
|
272
317
|
return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
|
|
273
318
|
}
|
|
@@ -313,15 +358,13 @@ async function processQueuedRemoteChanges(syncOptions) {
|
|
|
313
358
|
}
|
|
314
359
|
}
|
|
315
360
|
async function prepChangeLocal(queuedChange) {
|
|
316
|
-
const { syncState, changes,
|
|
361
|
+
const { syncState: syncState2, changes, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
|
|
317
362
|
const persist = syncOptions.persist;
|
|
318
|
-
const { pluginSync } = localState;
|
|
319
363
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
320
|
-
const
|
|
321
|
-
const
|
|
322
|
-
const saveRemote = !!(!inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek());
|
|
364
|
+
const saveLocal = (persist == null ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
|
|
365
|
+
const saveRemote = !!(!inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek());
|
|
323
366
|
if (saveLocal || saveRemote) {
|
|
324
|
-
if (saveLocal && !
|
|
367
|
+
if (saveLocal && !syncState2.isPersistLoaded.peek()) {
|
|
325
368
|
console.error(
|
|
326
369
|
"[legend-state] WARNING: An observable was changed before being loaded from persist",
|
|
327
370
|
persist
|
|
@@ -354,13 +397,13 @@ async function prepChangeLocal(queuedChange) {
|
|
|
354
397
|
configLocal
|
|
355
398
|
);
|
|
356
399
|
promisesTransform.push(
|
|
357
|
-
doInOrder(promiseTransformLocal, (valueTransformed) => {
|
|
400
|
+
doInOrder(promiseTransformLocal, ({ value: valueTransformed, path: pathTransformed }) => {
|
|
358
401
|
changesLocal.push({
|
|
359
|
-
path,
|
|
402
|
+
path: pathTransformed,
|
|
360
403
|
pathTypes,
|
|
361
404
|
prevAtPath,
|
|
362
405
|
valueAtPath: valueTransformed,
|
|
363
|
-
pathStr
|
|
406
|
+
pathStr: path === pathTransformed ? pathStr : pathTransformed.join("/")
|
|
364
407
|
});
|
|
365
408
|
})
|
|
366
409
|
);
|
|
@@ -376,22 +419,19 @@ async function prepChangeLocal(queuedChange) {
|
|
|
376
419
|
}
|
|
377
420
|
async function prepChangeRemote(queuedChange) {
|
|
378
421
|
const {
|
|
379
|
-
syncState,
|
|
422
|
+
syncState: syncState2,
|
|
380
423
|
changes,
|
|
381
424
|
localState,
|
|
382
425
|
syncOptions,
|
|
383
426
|
inRemoteChange,
|
|
384
|
-
isApplyingPending
|
|
385
|
-
valuePrevious
|
|
427
|
+
isApplyingPending
|
|
386
428
|
} = queuedChange;
|
|
387
429
|
const persist = syncOptions.persist;
|
|
388
|
-
const { pluginSync } = localState;
|
|
389
430
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
const saveRemote = !inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek();
|
|
431
|
+
const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
|
|
432
|
+
const saveRemote = !inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek();
|
|
393
433
|
if (saveLocal || saveRemote) {
|
|
394
|
-
if (saveLocal && !
|
|
434
|
+
if (saveLocal && !syncState2.isPersistLoaded.peek()) {
|
|
395
435
|
console.error(
|
|
396
436
|
"[legend-state] WARNING: An observable was changed before being loaded from persist",
|
|
397
437
|
persist
|
|
@@ -421,20 +461,20 @@ async function prepChangeRemote(queuedChange) {
|
|
|
421
461
|
valueAtPath,
|
|
422
462
|
path,
|
|
423
463
|
pathTypes,
|
|
424
|
-
|
|
464
|
+
syncOptions || {}
|
|
425
465
|
);
|
|
426
466
|
promisesTransform.push(
|
|
427
|
-
doInOrder(promiseTransformRemote, (valueTransformed) => {
|
|
467
|
+
doInOrder(promiseTransformRemote, ({ value: valueTransformed, path: pathTransformed }) => {
|
|
428
468
|
var _a;
|
|
429
469
|
if (!localState.pendingChanges) {
|
|
430
470
|
localState.pendingChanges = {};
|
|
431
471
|
}
|
|
432
472
|
let found2 = false;
|
|
433
|
-
for (let i2 = 0; !found2 && i2 <
|
|
434
|
-
const pathParent =
|
|
473
|
+
for (let i2 = 0; !found2 && i2 < pathTransformed.length - 1; i2++) {
|
|
474
|
+
const pathParent = pathTransformed.slice(0, i2 + 1).join("/");
|
|
435
475
|
if ((_a = localState.pendingChanges[pathParent]) == null ? void 0 : _a.v) {
|
|
436
476
|
found2 = true;
|
|
437
|
-
const pathChild =
|
|
477
|
+
const pathChild = pathTransformed.slice(i2 + 1);
|
|
438
478
|
const pathTypesChild = pathTypes.slice(i2 + 1);
|
|
439
479
|
setAtPath(
|
|
440
480
|
localState.pendingChanges[pathParent].v,
|
|
@@ -456,12 +496,11 @@ async function prepChangeRemote(queuedChange) {
|
|
|
456
496
|
localState.pendingChanges[pathStr].v = valueAtPath;
|
|
457
497
|
}
|
|
458
498
|
changesRemote.push({
|
|
459
|
-
path,
|
|
499
|
+
path: pathTransformed,
|
|
460
500
|
pathTypes,
|
|
461
501
|
prevAtPath,
|
|
462
502
|
valueAtPath: valueTransformed,
|
|
463
|
-
pathStr
|
|
464
|
-
valuePrevious
|
|
503
|
+
pathStr
|
|
465
504
|
});
|
|
466
505
|
})
|
|
467
506
|
);
|
|
@@ -479,24 +518,27 @@ async function doChangeLocal(changeInfo) {
|
|
|
479
518
|
if (!changeInfo)
|
|
480
519
|
return;
|
|
481
520
|
const { queuedChange, changesLocal, saveRemote } = changeInfo;
|
|
482
|
-
const { value$: obs, syncState, localState, syncOptions } = queuedChange;
|
|
521
|
+
const { value$: obs, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
483
522
|
const { pluginPersist } = localState;
|
|
484
523
|
const persist = syncOptions.persist;
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
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);
|
|
524
|
+
const saveLocal = !!(persist == null ? void 0 : persist.name);
|
|
525
|
+
if (saveLocal) {
|
|
526
|
+
const { table, config: configLocal } = parseLocalConfig(persist);
|
|
527
|
+
const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
|
|
528
|
+
if (saveRemote && shouldSaveMetadata) {
|
|
529
|
+
await updateMetadataImmediate(obs, localState, syncState2, syncOptions, {
|
|
530
|
+
pending: localState.pendingChanges
|
|
497
531
|
});
|
|
498
|
-
|
|
499
|
-
|
|
532
|
+
}
|
|
533
|
+
if (changesLocal.length > 0) {
|
|
534
|
+
let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
|
|
535
|
+
if (promiseSet) {
|
|
536
|
+
promiseSet = promiseSet.then(() => {
|
|
537
|
+
promisesLocalSaves.delete(promiseSet);
|
|
538
|
+
});
|
|
539
|
+
promisesLocalSaves.add(promiseSet);
|
|
540
|
+
await promiseSet;
|
|
541
|
+
}
|
|
500
542
|
}
|
|
501
543
|
}
|
|
502
544
|
}
|
|
@@ -505,102 +547,148 @@ async function doChangeRemote(changeInfo) {
|
|
|
505
547
|
if (!changeInfo)
|
|
506
548
|
return;
|
|
507
549
|
const { queuedChange, changesRemote } = changeInfo;
|
|
508
|
-
const { value$: obs
|
|
509
|
-
const { pluginPersist
|
|
550
|
+
const { value$: obs$, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
551
|
+
const { pluginPersist } = localState;
|
|
552
|
+
const node = getNode(obs$);
|
|
553
|
+
const state$ = node.state;
|
|
510
554
|
const persist = syncOptions.persist;
|
|
511
555
|
const { table, config: configLocal } = parseLocalConfig(persist);
|
|
512
|
-
const {
|
|
556
|
+
const { onBeforeSet, waitForSet: waitForSetParam, onAfterSet } = syncOptions || {};
|
|
513
557
|
const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
|
|
558
|
+
const saveLocal = !!(persist == null ? void 0 : persist.name);
|
|
514
559
|
if (changesRemote.length > 0) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
-
|
|
560
|
+
if (!syncState2.isLoaded.peek()) {
|
|
561
|
+
await when(syncState2.isLoaded);
|
|
562
|
+
const pending = localState.pendingChanges;
|
|
563
|
+
if (pending) {
|
|
564
|
+
changesRemote.forEach((change) => {
|
|
565
|
+
const key = change.pathStr;
|
|
566
|
+
const pendingAtPath = pending[key];
|
|
567
|
+
if (!isNullOrUndefined(pendingAtPath)) {
|
|
568
|
+
const { p } = pendingAtPath;
|
|
569
|
+
change.prevAtPath = p;
|
|
570
|
+
}
|
|
571
|
+
});
|
|
520
572
|
}
|
|
521
573
|
}
|
|
522
|
-
|
|
574
|
+
if (waitForSetParam) {
|
|
575
|
+
await waitForSet(waitForSetParam, changesRemote, obs$.peek());
|
|
576
|
+
}
|
|
577
|
+
let value = clone(obs$.peek());
|
|
523
578
|
const transformSave = (_a = syncOptions == null ? void 0 : syncOptions.transform) == null ? void 0 : _a.save;
|
|
524
579
|
if (transformSave) {
|
|
525
|
-
value = transformSave(
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
580
|
+
value = transformSave(value);
|
|
581
|
+
}
|
|
582
|
+
state$.numPendingSets.set((v) => (v || 0) + 1);
|
|
583
|
+
state$.isSetting.set(true);
|
|
584
|
+
const beforeSetParams = {
|
|
585
|
+
cancel: false
|
|
586
|
+
};
|
|
587
|
+
onBeforeSet == null ? void 0 : onBeforeSet(beforeSetParams);
|
|
588
|
+
if (!beforeSetParams.cancel) {
|
|
589
|
+
let updateResult = void 0;
|
|
590
|
+
let errorHandled = false;
|
|
591
|
+
const onError = (error, retryParams) => {
|
|
592
|
+
var _a2;
|
|
593
|
+
state$.error.set(error);
|
|
594
|
+
if (!errorHandled) {
|
|
595
|
+
(_a2 = syncOptions.onError) == null ? void 0 : _a2.call(syncOptions, error, {
|
|
596
|
+
setParams,
|
|
597
|
+
source: "set",
|
|
598
|
+
value$: obs$,
|
|
599
|
+
retryParams
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
errorHandled = true;
|
|
603
|
+
};
|
|
604
|
+
const setParams = {
|
|
605
|
+
node,
|
|
606
|
+
value$: obs$,
|
|
607
|
+
changes: changesRemote,
|
|
608
|
+
value,
|
|
609
|
+
onError,
|
|
610
|
+
update: (params) => {
|
|
611
|
+
if (updateResult) {
|
|
612
|
+
const { value: value2, lastSync, mode } = params;
|
|
613
|
+
updateResult = {
|
|
614
|
+
lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
|
|
615
|
+
value: deepMerge(updateResult.value, value2),
|
|
616
|
+
mode
|
|
617
|
+
};
|
|
618
|
+
} else {
|
|
619
|
+
updateResult = params;
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
refresh: syncState2.sync,
|
|
623
|
+
retryNum: 0,
|
|
624
|
+
cancelRetry: false
|
|
625
|
+
};
|
|
626
|
+
const savedPromise = runWithRetry(
|
|
627
|
+
setParams,
|
|
628
|
+
syncOptions.retry,
|
|
629
|
+
async () => {
|
|
630
|
+
return syncOptions.set(setParams);
|
|
631
|
+
},
|
|
632
|
+
onError
|
|
633
|
+
);
|
|
634
|
+
let didError = false;
|
|
635
|
+
if (isPromise$1(savedPromise)) {
|
|
636
|
+
await savedPromise.catch(() => {
|
|
637
|
+
didError = true;
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
if (!didError) {
|
|
641
|
+
const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
|
|
642
|
+
const { value: changes, lastSync } = updateResult || {};
|
|
643
|
+
if (pathStrs.length > 0) {
|
|
644
|
+
let transformedChanges = void 0;
|
|
645
|
+
const metadata = {};
|
|
646
|
+
if (saveLocal) {
|
|
647
|
+
const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
|
|
648
|
+
const pending = localState.pendingChanges;
|
|
649
|
+
for (let i = 0; i < pathStrs.length; i++) {
|
|
650
|
+
const pathStr = pathStrs[i];
|
|
651
|
+
if (pendingMetadata == null ? void 0 : pendingMetadata[pathStr]) {
|
|
652
|
+
delete pendingMetadata[pathStr];
|
|
653
|
+
metadata.pending = pendingMetadata;
|
|
654
|
+
}
|
|
655
|
+
if (pending == null ? void 0 : pending[pathStr]) {
|
|
656
|
+
delete pending[pathStr];
|
|
657
|
+
}
|
|
556
658
|
}
|
|
557
|
-
if (
|
|
558
|
-
|
|
659
|
+
if (lastSync) {
|
|
660
|
+
metadata.lastSync = lastSync;
|
|
559
661
|
}
|
|
560
662
|
}
|
|
561
|
-
if (
|
|
562
|
-
|
|
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);
|
|
663
|
+
if (changes && !isEmpty(changes)) {
|
|
664
|
+
transformedChanges = transformLoadData(changes, syncOptions, false, "set");
|
|
574
665
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
);
|
|
579
|
-
if (allChanges.length > 0) {
|
|
580
|
-
if (allChanges.some((change) => isPromise(change))) {
|
|
581
|
-
allChanges = await Promise.all(allChanges);
|
|
666
|
+
if (transformedChanges !== void 0) {
|
|
667
|
+
if (isPromise$1(transformedChanges)) {
|
|
668
|
+
transformedChanges = await transformedChanges;
|
|
582
669
|
}
|
|
583
|
-
onChangeRemote(() => mergeIntoObservable(obs
|
|
670
|
+
onChangeRemote(() => mergeIntoObservable(obs$, transformedChanges));
|
|
584
671
|
}
|
|
585
|
-
if (
|
|
672
|
+
if (saveLocal) {
|
|
586
673
|
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
587
|
-
updateMetadata(obs
|
|
674
|
+
updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
|
|
588
675
|
}
|
|
589
676
|
}
|
|
590
|
-
localState.pendingSaveResults = [];
|
|
591
677
|
}
|
|
678
|
+
state$.numPendingSets.set((v) => v - 1);
|
|
679
|
+
state$.isSetting.set(state$.numPendingSets.peek() > 0);
|
|
592
680
|
onAfterSet == null ? void 0 : onAfterSet();
|
|
593
681
|
}
|
|
594
682
|
}
|
|
595
683
|
}
|
|
596
684
|
}
|
|
597
|
-
function onObsChange(value$,
|
|
598
|
-
if (!
|
|
599
|
-
const inRemoteChange =
|
|
685
|
+
function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
|
|
686
|
+
if (!isFromPersist) {
|
|
687
|
+
const inRemoteChange = isFromSync;
|
|
600
688
|
const isApplyingPending = localState.isApplyingPending;
|
|
601
689
|
_queuedChanges.push({
|
|
602
690
|
value$,
|
|
603
|
-
syncState,
|
|
691
|
+
syncState: syncState2,
|
|
604
692
|
localState,
|
|
605
693
|
syncOptions,
|
|
606
694
|
changes,
|
|
@@ -613,23 +701,27 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
|
|
|
613
701
|
}
|
|
614
702
|
}
|
|
615
703
|
}
|
|
616
|
-
async function loadLocal(value$, syncOptions, syncState
|
|
704
|
+
async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
617
705
|
var _a, _b, _c;
|
|
618
706
|
const { persist } = syncOptions;
|
|
619
|
-
|
|
707
|
+
const node = getNode(value$);
|
|
708
|
+
const nodeValue = getNodeValue(getNode(node.state));
|
|
709
|
+
const syncStateValue = syncState$.peek();
|
|
710
|
+
const prevResetPersistence = nodeValue.resetPersistence;
|
|
711
|
+
if (persist == null ? void 0 : persist.name) {
|
|
620
712
|
const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
|
|
621
713
|
const { table, config } = parseLocalConfig(persist);
|
|
622
|
-
|
|
714
|
+
syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
|
|
623
715
|
if (!PersistPlugin) {
|
|
624
716
|
throw new Error("Local persist is not configured");
|
|
625
717
|
}
|
|
626
718
|
if (!mapSyncPlugins.has(PersistPlugin)) {
|
|
627
|
-
const persistPlugin2 = new PersistPlugin();
|
|
719
|
+
const persistPlugin2 = isFunction(PersistPlugin) ? new PersistPlugin() : PersistPlugin;
|
|
628
720
|
const mapValue = { plugin: persistPlugin2, initialized: observable(false) };
|
|
629
721
|
mapSyncPlugins.set(PersistPlugin, mapValue);
|
|
630
722
|
if (persistPlugin2.initialize) {
|
|
631
723
|
const initializePromise = (_c = persistPlugin2.initialize) == null ? void 0 : _c.call(persistPlugin2, ((_b = observableSyncConfiguration) == null ? void 0 : _b.persist) || {});
|
|
632
|
-
if (isPromise(initializePromise)) {
|
|
724
|
+
if (isPromise$1(initializePromise)) {
|
|
633
725
|
await initializePromise;
|
|
634
726
|
}
|
|
635
727
|
}
|
|
@@ -653,14 +745,14 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
653
745
|
if (metadata) {
|
|
654
746
|
metadatas.set(value$, metadata);
|
|
655
747
|
localState.pendingChanges = metadata.pending;
|
|
656
|
-
syncState
|
|
748
|
+
syncState$.assign({
|
|
657
749
|
lastSync: metadata.lastSync
|
|
658
750
|
});
|
|
659
751
|
}
|
|
660
752
|
if (value !== void 0) {
|
|
661
753
|
const { transform } = config;
|
|
662
754
|
value = transformLoadData(value, { transform }, true, "get");
|
|
663
|
-
if (isPromise(value)) {
|
|
755
|
+
if (isPromise$1(value)) {
|
|
664
756
|
value = await value;
|
|
665
757
|
}
|
|
666
758
|
internal.globalState.isLoadingLocal = true;
|
|
@@ -671,12 +763,19 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
671
763
|
}
|
|
672
764
|
internal.globalState.isLoadingLocal = false;
|
|
673
765
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
766
|
+
syncStateValue.numPendingLocalLoads--;
|
|
767
|
+
nodeValue.resetPersistence = () => Promise.all(
|
|
768
|
+
[
|
|
769
|
+
prevResetPersistence,
|
|
770
|
+
persistPlugin.deleteTable(table, config),
|
|
771
|
+
persistPlugin.deleteMetadata(table, config)
|
|
772
|
+
].filter(Boolean)
|
|
773
|
+
);
|
|
774
|
+
} else {
|
|
775
|
+
nodeValue.resetPersistence = () => prevResetPersistence == null ? void 0 : prevResetPersistence();
|
|
678
776
|
}
|
|
679
|
-
|
|
777
|
+
nodeValue.clearPersist = nodeValue.resetPersistence;
|
|
778
|
+
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
680
779
|
}
|
|
681
780
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
682
781
|
let syncOptions = syncOptionsOrSynced;
|
|
@@ -687,7 +786,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
687
786
|
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
|
|
688
787
|
throw new Error("[legend-state] syncObservable called with undefined observable");
|
|
689
788
|
}
|
|
690
|
-
syncOptions =
|
|
789
|
+
syncOptions = deepMerge(
|
|
691
790
|
{
|
|
692
791
|
syncMode: "auto"
|
|
693
792
|
},
|
|
@@ -696,24 +795,54 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
696
795
|
);
|
|
697
796
|
const localState = {};
|
|
698
797
|
let sync;
|
|
699
|
-
const syncState =
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
798
|
+
const syncState$ = syncState(obs$);
|
|
799
|
+
const syncStateValue = getNodeValue(getNode(syncState$));
|
|
800
|
+
allSyncStates.set(syncState$, node);
|
|
801
|
+
syncStateValue.getPendingChanges = () => localState.pendingChanges;
|
|
802
|
+
let errorHandled = false;
|
|
803
|
+
const onGetError = (error, params) => {
|
|
804
|
+
var _a;
|
|
805
|
+
syncState$.error.set(error);
|
|
806
|
+
if (!errorHandled) {
|
|
807
|
+
(_a = syncOptions.onError) == null ? void 0 : _a.call(syncOptions, error, { ...params, value$: obs$ });
|
|
808
|
+
}
|
|
809
|
+
errorHandled = true;
|
|
810
|
+
};
|
|
811
|
+
loadLocal(obs$, syncOptions, syncState$, localState);
|
|
812
|
+
let isWaitingForLoad = !!syncOptions.get;
|
|
813
|
+
if (isWaitingForLoad) {
|
|
814
|
+
syncStateValue.numPendingRemoteLoads = (syncStateValue.numPendingRemoteLoads || 0) + 1;
|
|
815
|
+
}
|
|
816
|
+
syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
|
|
817
|
+
let isSynced = false;
|
|
818
|
+
let isSubscribed = false;
|
|
819
|
+
let unsubscribe = void 0;
|
|
820
|
+
const applyPending = (pending) => {
|
|
821
|
+
if (pending && !isEmpty(pending)) {
|
|
822
|
+
localState.isApplyingPending = true;
|
|
823
|
+
const keys = Object.keys(pending);
|
|
824
|
+
const changes = [];
|
|
825
|
+
for (let i = 0; i < keys.length; i++) {
|
|
826
|
+
const key = keys[i];
|
|
827
|
+
const path = key.split("/").filter((p2) => p2 !== "");
|
|
828
|
+
const { p, v, t } = pending[key];
|
|
829
|
+
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
830
|
+
}
|
|
831
|
+
const value = getNodeValue(node);
|
|
832
|
+
onObsChange(obs$, syncState$, localState, syncOptions, {
|
|
833
|
+
value,
|
|
834
|
+
isFromPersist: false,
|
|
835
|
+
isFromSync: false,
|
|
836
|
+
getPrevious: createPreviousHandler(value, changes),
|
|
837
|
+
changes
|
|
838
|
+
});
|
|
839
|
+
localState.isApplyingPending = false;
|
|
840
|
+
}
|
|
841
|
+
};
|
|
710
842
|
if (syncOptions.get) {
|
|
711
|
-
let isSynced = false;
|
|
712
|
-
let isSubscribed = false;
|
|
713
|
-
let unsubscribe = void 0;
|
|
714
843
|
sync = async () => {
|
|
715
|
-
var _a
|
|
716
|
-
if (isSynced && shouldIgnoreUnobserved(node, sync)) {
|
|
844
|
+
var _a;
|
|
845
|
+
if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || shouldIgnoreUnobserved(node, sync))) {
|
|
717
846
|
if (unsubscribe) {
|
|
718
847
|
isSubscribed = false;
|
|
719
848
|
unsubscribe();
|
|
@@ -723,14 +852,16 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
723
852
|
}
|
|
724
853
|
const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
|
|
725
854
|
const pending = localState.pendingChanges;
|
|
726
|
-
const get =
|
|
855
|
+
const get = syncOptions.get;
|
|
727
856
|
if (get) {
|
|
857
|
+
const { waitFor } = syncOptions;
|
|
728
858
|
const runGet = () => {
|
|
859
|
+
var _a2;
|
|
729
860
|
const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
|
|
730
861
|
mode = mode || syncOptions.mode || "set";
|
|
731
862
|
if (value !== void 0) {
|
|
732
863
|
value = transformLoadData(value, syncOptions, true, "get");
|
|
733
|
-
if (isPromise(value)) {
|
|
864
|
+
if (isPromise$1(value)) {
|
|
734
865
|
value = await value;
|
|
735
866
|
}
|
|
736
867
|
const pending2 = localState.pendingChanges;
|
|
@@ -738,9 +869,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
738
869
|
if (pending2) {
|
|
739
870
|
let didChangeMetadata = false;
|
|
740
871
|
Object.keys(pending2).forEach((key) => {
|
|
741
|
-
const p = key.split("/").filter((
|
|
872
|
+
const p = key.split("/").filter((k) => k !== "");
|
|
742
873
|
const { v, t } = pending2[key];
|
|
743
874
|
if (t.length === 0 || !value) {
|
|
875
|
+
const oldValue = clone(value);
|
|
876
|
+
pending2[key].p = oldValue;
|
|
744
877
|
if (isObject(value) && isObject(v)) {
|
|
745
878
|
Object.assign(value, v);
|
|
746
879
|
} else {
|
|
@@ -753,6 +886,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
753
886
|
delete pending2[key];
|
|
754
887
|
didChangeMetadata = true;
|
|
755
888
|
} else {
|
|
889
|
+
const oldValue = clone(value);
|
|
890
|
+
pending2[key].p = getValueAtPath(oldValue, p);
|
|
756
891
|
value = setAtPath(
|
|
757
892
|
value,
|
|
758
893
|
p,
|
|
@@ -772,18 +907,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
772
907
|
}
|
|
773
908
|
}
|
|
774
909
|
});
|
|
775
|
-
if (didChangeMetadata) {
|
|
776
|
-
updateMetadata(obs$, localState, syncState
|
|
910
|
+
if (didChangeMetadata && syncOptions.persist) {
|
|
911
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
777
912
|
pending: pending2
|
|
778
913
|
});
|
|
779
914
|
}
|
|
780
915
|
}
|
|
781
916
|
onChangeRemote(() => {
|
|
782
|
-
if (
|
|
917
|
+
if (isPlainObject(value)) {
|
|
918
|
+
value = ObservableHint.plain(value);
|
|
919
|
+
}
|
|
920
|
+
if (mode === "assign") {
|
|
783
921
|
obs$.assign(value);
|
|
784
|
-
} else if (mode === "append"
|
|
922
|
+
} else if (mode === "append") {
|
|
923
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
924
|
+
console.error("[legend-state] mode:append expects the value to be an array");
|
|
925
|
+
}
|
|
785
926
|
obs$.push(...value);
|
|
786
|
-
} else if (mode === "prepend"
|
|
927
|
+
} else if (mode === "prepend") {
|
|
928
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
929
|
+
console.error("[legend-state] mode:prepend expects the value to be an array");
|
|
930
|
+
}
|
|
787
931
|
obs$.splice(0, 0, ...value);
|
|
788
932
|
} else if (mode === "merge") {
|
|
789
933
|
mergeIntoObservable(obs$, value);
|
|
@@ -793,78 +937,180 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
793
937
|
});
|
|
794
938
|
}
|
|
795
939
|
if (lastSync2 && syncOptions.persist) {
|
|
796
|
-
updateMetadata(obs$, localState, syncState
|
|
940
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
797
941
|
lastSync: lastSync2
|
|
798
942
|
});
|
|
799
943
|
}
|
|
800
944
|
};
|
|
801
|
-
|
|
802
|
-
|
|
945
|
+
if (node.activationState) {
|
|
946
|
+
node.activationState.onChange = onChange;
|
|
947
|
+
}
|
|
948
|
+
if (!isSubscribed && syncOptions.subscribe) {
|
|
949
|
+
const subscribe = syncOptions.subscribe;
|
|
950
|
+
isSubscribed = true;
|
|
951
|
+
const doSubscribe = () => {
|
|
952
|
+
const subscribeParams = {
|
|
953
|
+
node,
|
|
954
|
+
value$: obs$,
|
|
955
|
+
lastSync,
|
|
956
|
+
update: (params) => {
|
|
957
|
+
when(syncState$.isLoaded, () => {
|
|
958
|
+
when(waitFor || true, () => {
|
|
959
|
+
params.mode || (params.mode = syncOptions.mode || "merge");
|
|
960
|
+
onChange(params);
|
|
961
|
+
});
|
|
962
|
+
});
|
|
963
|
+
},
|
|
964
|
+
refresh: () => when(syncState$.isLoaded, sync),
|
|
965
|
+
onError: (error) => onGetError(error, { source: "subscribe", subscribeParams })
|
|
966
|
+
};
|
|
967
|
+
unsubscribe = subscribe(subscribeParams);
|
|
968
|
+
};
|
|
969
|
+
if (waitFor) {
|
|
970
|
+
whenReady(waitFor, doSubscribe);
|
|
971
|
+
} else {
|
|
972
|
+
doSubscribe();
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
const existingValue = getNodeValue(node);
|
|
976
|
+
const onError = (error) => onGetError(error, { getParams, source: "get" });
|
|
977
|
+
const getParams = {
|
|
978
|
+
node,
|
|
803
979
|
value$: obs$,
|
|
980
|
+
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
|
|
981
|
+
mode: syncOptions.mode,
|
|
982
|
+
refresh: sync,
|
|
804
983
|
options: syncOptions,
|
|
805
984
|
lastSync,
|
|
806
|
-
|
|
807
|
-
onError
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
985
|
+
updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
|
|
986
|
+
onError,
|
|
987
|
+
retryNum: 0,
|
|
988
|
+
cancelRetry: false
|
|
989
|
+
};
|
|
990
|
+
let modeBeforeReset = void 0;
|
|
991
|
+
const beforeGetParams = {
|
|
992
|
+
value: getParams.value,
|
|
993
|
+
lastSync,
|
|
994
|
+
pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
|
|
995
|
+
clearPendingChanges: async () => {
|
|
996
|
+
localState.pendingChanges = {};
|
|
997
|
+
await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
|
|
998
|
+
pending: localState.pendingChanges
|
|
815
999
|
});
|
|
816
1000
|
},
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
refresh: () => when(node.state.isLoaded, sync)
|
|
1001
|
+
resetCache: () => {
|
|
1002
|
+
var _a3;
|
|
1003
|
+
modeBeforeReset = getParams.mode;
|
|
1004
|
+
getParams.mode = "set";
|
|
1005
|
+
return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
|
|
1006
|
+
},
|
|
1007
|
+
cancel: false
|
|
1008
|
+
};
|
|
1009
|
+
(_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
|
|
1010
|
+
if (!beforeGetParams.cancel) {
|
|
1011
|
+
syncState$.assign({
|
|
1012
|
+
numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
|
|
1013
|
+
isGetting: true
|
|
831
1014
|
});
|
|
1015
|
+
const got = runWithRetry(
|
|
1016
|
+
getParams,
|
|
1017
|
+
syncOptions.retry,
|
|
1018
|
+
(retryEvent) => {
|
|
1019
|
+
const params = getParams;
|
|
1020
|
+
params.cancelRetry = retryEvent.cancelRetry;
|
|
1021
|
+
params.retryNum = retryEvent.retryNum;
|
|
1022
|
+
return get(params);
|
|
1023
|
+
},
|
|
1024
|
+
onError
|
|
1025
|
+
);
|
|
1026
|
+
const numGets = node.numGets = (node.numGets || 0) + 1;
|
|
1027
|
+
const handle = (value) => {
|
|
1028
|
+
syncState$.numPendingGets.set((v) => v - 1);
|
|
1029
|
+
if (isWaitingForLoad) {
|
|
1030
|
+
isWaitingForLoad = false;
|
|
1031
|
+
syncStateValue.numPendingRemoteLoads--;
|
|
1032
|
+
}
|
|
1033
|
+
if (numGets >= (node.getNumResolved || 0)) {
|
|
1034
|
+
node.getNumResolved = node.numGets;
|
|
1035
|
+
onChange({
|
|
1036
|
+
value,
|
|
1037
|
+
lastSync: getParams.lastSync,
|
|
1038
|
+
mode: getParams.mode
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
if (modeBeforeReset) {
|
|
1042
|
+
getParams.mode = modeBeforeReset;
|
|
1043
|
+
modeBeforeReset = void 0;
|
|
1044
|
+
}
|
|
1045
|
+
syncState$.assign({
|
|
1046
|
+
isLoaded: syncStateValue.numPendingRemoteLoads < 1,
|
|
1047
|
+
error: void 0,
|
|
1048
|
+
isGetting: syncStateValue.numPendingGets > 0
|
|
1049
|
+
});
|
|
1050
|
+
};
|
|
1051
|
+
if (isPromise$1(got)) {
|
|
1052
|
+
got.then(handle);
|
|
1053
|
+
} else {
|
|
1054
|
+
handle(got);
|
|
1055
|
+
}
|
|
832
1056
|
}
|
|
833
1057
|
};
|
|
834
|
-
|
|
1058
|
+
if (waitFor) {
|
|
1059
|
+
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1060
|
+
} else {
|
|
1061
|
+
trackSelector(runGet, sync);
|
|
1062
|
+
}
|
|
835
1063
|
} else {
|
|
836
|
-
|
|
1064
|
+
syncState$.assign({
|
|
837
1065
|
isLoaded: true,
|
|
838
1066
|
error: void 0
|
|
839
1067
|
});
|
|
840
1068
|
}
|
|
841
1069
|
if (!isSynced) {
|
|
842
1070
|
isSynced = true;
|
|
843
|
-
await when(
|
|
844
|
-
|
|
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
|
-
}
|
|
1071
|
+
await when(syncState$.isLoaded);
|
|
1072
|
+
applyPending(pending);
|
|
864
1073
|
}
|
|
865
1074
|
};
|
|
866
|
-
|
|
1075
|
+
syncStateValue.sync = sync;
|
|
1076
|
+
} else {
|
|
1077
|
+
if (!isSynced) {
|
|
1078
|
+
applyPending(localState.pendingChanges);
|
|
1079
|
+
}
|
|
867
1080
|
}
|
|
1081
|
+
syncStateValue.reset = async () => {
|
|
1082
|
+
const wasPersistEnabled = syncStateValue.isPersistEnabled;
|
|
1083
|
+
const wasSyncEnabled = syncStateValue.isSyncEnabled;
|
|
1084
|
+
const metadata = metadatas.get(obs$);
|
|
1085
|
+
if (metadata) {
|
|
1086
|
+
Object.assign(metadata, { lastSync: void 0, pending: void 0 });
|
|
1087
|
+
}
|
|
1088
|
+
Object.assign(syncStateValue, {
|
|
1089
|
+
isPersistEnabled: false,
|
|
1090
|
+
isSyncEnabled: false,
|
|
1091
|
+
lastSync: void 0,
|
|
1092
|
+
numPendingGets: 0,
|
|
1093
|
+
isLoaded: false,
|
|
1094
|
+
isGetting: false,
|
|
1095
|
+
isSetting: false,
|
|
1096
|
+
numPendingSets: 0,
|
|
1097
|
+
syncCount: 0
|
|
1098
|
+
});
|
|
1099
|
+
isSynced = false;
|
|
1100
|
+
isSubscribed = false;
|
|
1101
|
+
unsubscribe == null ? void 0 : unsubscribe();
|
|
1102
|
+
unsubscribe = void 0;
|
|
1103
|
+
const promise = syncStateValue.resetPersistence();
|
|
1104
|
+
onChangeRemote(() => {
|
|
1105
|
+
var _a;
|
|
1106
|
+
obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
|
|
1107
|
+
});
|
|
1108
|
+
syncState$.isLoaded.set(false);
|
|
1109
|
+
syncStateValue.isPersistEnabled = wasPersistEnabled;
|
|
1110
|
+
syncStateValue.isSyncEnabled = wasSyncEnabled;
|
|
1111
|
+
node.dirtyFn = sync;
|
|
1112
|
+
await promise;
|
|
1113
|
+
};
|
|
868
1114
|
const onAllPersistLoaded = () => {
|
|
869
1115
|
var _a, _b;
|
|
870
1116
|
let parentNode = node;
|
|
@@ -882,77 +1128,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
882
1128
|
}
|
|
883
1129
|
if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
|
|
884
1130
|
obs$.onChange(
|
|
885
|
-
onObsChange.bind(this, obs$, syncState
|
|
1131
|
+
onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
|
|
886
1132
|
);
|
|
887
1133
|
}
|
|
888
1134
|
});
|
|
889
|
-
return syncState
|
|
1135
|
+
return syncState$;
|
|
890
1136
|
}
|
|
891
|
-
var { getProxy, globalState: globalState2,
|
|
1137
|
+
var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = internal;
|
|
892
1138
|
function enableActivateSyncedNode() {
|
|
893
1139
|
globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
|
|
894
1140
|
const obs$ = getProxy(node);
|
|
895
1141
|
if (node.activationState) {
|
|
896
|
-
const {
|
|
897
|
-
|
|
898
|
-
|
|
1142
|
+
const {
|
|
1143
|
+
get: getOrig,
|
|
1144
|
+
initial,
|
|
1145
|
+
set,
|
|
1146
|
+
onChange
|
|
1147
|
+
} = node.activationState;
|
|
899
1148
|
let promiseReturn = void 0;
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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
|
|
915
|
-
};
|
|
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 };
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
};
|
|
955
|
-
}
|
|
1149
|
+
const get = getOrig ? (params) => {
|
|
1150
|
+
return promiseReturn = getOrig(params);
|
|
1151
|
+
} : void 0;
|
|
956
1152
|
const nodeVal = getNodeValue2(node);
|
|
957
1153
|
if (promiseReturn !== void 0) {
|
|
958
1154
|
newValue = promiseReturn;
|
|
@@ -962,13 +1158,13 @@ function enableActivateSyncedNode() {
|
|
|
962
1158
|
newValue = initial;
|
|
963
1159
|
}
|
|
964
1160
|
setNodeValue(node, promiseReturn ? void 0 : newValue);
|
|
965
|
-
|
|
1161
|
+
syncObservable(obs$, { ...node.activationState, get, set });
|
|
966
1162
|
return { update: onChange, value: newValue };
|
|
967
1163
|
} else {
|
|
968
1164
|
let update = void 0;
|
|
969
1165
|
const get = async (params) => {
|
|
970
1166
|
update = params.refresh;
|
|
971
|
-
if (isPromise(newValue)) {
|
|
1167
|
+
if (isPromise$1(newValue)) {
|
|
972
1168
|
try {
|
|
973
1169
|
newValue = await newValue;
|
|
974
1170
|
} catch (e) {
|
|
@@ -999,13 +1195,20 @@ function installPersistActivateNode() {
|
|
|
999
1195
|
didInstall = true;
|
|
1000
1196
|
}
|
|
1001
1197
|
}
|
|
1198
|
+
var { deepMerge: deepMerge2 } = internal;
|
|
1199
|
+
function configureSynced(fnOrOrigOptions, origOptions) {
|
|
1200
|
+
const fn = origOptions ? fnOrOrigOptions : synced;
|
|
1201
|
+
origOptions = origOptions != null ? origOptions : fnOrOrigOptions;
|
|
1202
|
+
return (options) => {
|
|
1203
|
+
const merged = deepMerge2(origOptions, options);
|
|
1204
|
+
return fn(merged);
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1002
1207
|
|
|
1003
1208
|
// sync.ts
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
var internal3 = {
|
|
1008
|
-
observableSyncConfiguration
|
|
1209
|
+
var internal4 = {
|
|
1210
|
+
observableSyncConfiguration,
|
|
1211
|
+
waitForSet
|
|
1009
1212
|
};
|
|
1010
1213
|
|
|
1011
|
-
export { combineTransforms, configureObservableSync, deepEqual, diffObjects,
|
|
1214
|
+
export { combineTransforms, configureObservableSync, configureSynced, deepEqual, diffObjects, internal4 as internal, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
|