@legendapp/state 3.0.0-alpha.15 → 3.0.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.mts +3 -1
- package/index.d.ts +3 -1
- package/index.js +51 -24
- package/index.mjs +51 -24
- package/package.json +1 -1
- package/sync-plugins/crud.js +59 -42
- package/sync-plugins/crud.mjs +60 -43
- package/sync-plugins/keel.js +3 -3
- package/sync-plugins/keel.mjs +3 -3
- package/sync.d.mts +0 -2
- package/sync.d.ts +0 -2
- package/sync.js +15 -33
- package/sync.mjs +16 -34
package/index.d.mts
CHANGED
|
@@ -308,7 +308,7 @@ declare function opaqueObject<T extends object>(value: T): OpaqueObject<T>;
|
|
|
308
308
|
declare function getValueAtPath(obj: Record<string, any>, path: string[]): any;
|
|
309
309
|
declare function setAtPath<T extends object>(obj: T, path: string[], pathTypes: TypeAtPath[], value: any, mode?: 'set' | 'merge', fullObj?: T, restore?: (path: string[], value: any) => void): T;
|
|
310
310
|
declare function setInObservableAtPath(value$: ObservableParam, path: string[], pathTypes: TypeAtPath[], value: any, mode: 'assign' | 'set' | 'merge'): void;
|
|
311
|
-
declare function mergeIntoObservable<T extends ObservableParam<
|
|
311
|
+
declare function mergeIntoObservable<T extends ObservableParam<any>>(target: T, ...sources: any[]): T;
|
|
312
312
|
declare function constructObjectWithPath(path: string[], pathTypes: TypeAtPath[], value: any): object;
|
|
313
313
|
declare function deconstructObjectWithPath(path: string[], pathTypes: TypeAtPath[], value: any): object;
|
|
314
314
|
declare function isObservableValueReady(value: any): boolean;
|
|
@@ -316,6 +316,7 @@ declare function setSilently(value$: ObservableParam, newValue: any): any;
|
|
|
316
316
|
declare function initializePathType(pathType: TypeAtPath): any;
|
|
317
317
|
declare function applyChange<T extends object>(value: T, change: Change, applyPrevious?: boolean): T;
|
|
318
318
|
declare function applyChanges<T extends object>(value: T, changes: Change[], applyPrevious?: boolean): T;
|
|
319
|
+
declare function deepMerge<T extends object>(target: T, ...sources: any[]): T;
|
|
319
320
|
|
|
320
321
|
declare const hasOwnProperty: (v: PropertyKey) => boolean;
|
|
321
322
|
declare function isArray(obj: unknown): obj is Array<any>;
|
|
@@ -375,6 +376,7 @@ declare function runWithRetry<T>(state: {
|
|
|
375
376
|
declare const internal: {
|
|
376
377
|
createPreviousHandler: typeof createPreviousHandler;
|
|
377
378
|
clone: typeof clone;
|
|
379
|
+
deepMerge: typeof deepMerge;
|
|
378
380
|
ensureNodeValue: typeof ensureNodeValue;
|
|
379
381
|
findIDKey: typeof findIDKey;
|
|
380
382
|
get: typeof get;
|
package/index.d.ts
CHANGED
|
@@ -308,7 +308,7 @@ declare function opaqueObject<T extends object>(value: T): OpaqueObject<T>;
|
|
|
308
308
|
declare function getValueAtPath(obj: Record<string, any>, path: string[]): any;
|
|
309
309
|
declare function setAtPath<T extends object>(obj: T, path: string[], pathTypes: TypeAtPath[], value: any, mode?: 'set' | 'merge', fullObj?: T, restore?: (path: string[], value: any) => void): T;
|
|
310
310
|
declare function setInObservableAtPath(value$: ObservableParam, path: string[], pathTypes: TypeAtPath[], value: any, mode: 'assign' | 'set' | 'merge'): void;
|
|
311
|
-
declare function mergeIntoObservable<T extends ObservableParam<
|
|
311
|
+
declare function mergeIntoObservable<T extends ObservableParam<any>>(target: T, ...sources: any[]): T;
|
|
312
312
|
declare function constructObjectWithPath(path: string[], pathTypes: TypeAtPath[], value: any): object;
|
|
313
313
|
declare function deconstructObjectWithPath(path: string[], pathTypes: TypeAtPath[], value: any): object;
|
|
314
314
|
declare function isObservableValueReady(value: any): boolean;
|
|
@@ -316,6 +316,7 @@ declare function setSilently(value$: ObservableParam, newValue: any): any;
|
|
|
316
316
|
declare function initializePathType(pathType: TypeAtPath): any;
|
|
317
317
|
declare function applyChange<T extends object>(value: T, change: Change, applyPrevious?: boolean): T;
|
|
318
318
|
declare function applyChanges<T extends object>(value: T, changes: Change[], applyPrevious?: boolean): T;
|
|
319
|
+
declare function deepMerge<T extends object>(target: T, ...sources: any[]): T;
|
|
319
320
|
|
|
320
321
|
declare const hasOwnProperty: (v: PropertyKey) => boolean;
|
|
321
322
|
declare function isArray(obj: unknown): obj is Array<any>;
|
|
@@ -375,6 +376,7 @@ declare function runWithRetry<T>(state: {
|
|
|
375
376
|
declare const internal: {
|
|
376
377
|
createPreviousHandler: typeof createPreviousHandler;
|
|
377
378
|
clone: typeof clone;
|
|
379
|
+
deepMerge: typeof deepMerge;
|
|
378
380
|
ensureNodeValue: typeof ensureNodeValue;
|
|
379
381
|
findIDKey: typeof findIDKey;
|
|
380
382
|
get: typeof get;
|
package/index.js
CHANGED
|
@@ -33,6 +33,9 @@ function isPromise(obj) {
|
|
|
33
33
|
function isMap(obj) {
|
|
34
34
|
return obj instanceof Map;
|
|
35
35
|
}
|
|
36
|
+
function isSet(obj) {
|
|
37
|
+
return obj instanceof Set;
|
|
38
|
+
}
|
|
36
39
|
function isNumber(obj) {
|
|
37
40
|
const n = obj;
|
|
38
41
|
return n - n < 1;
|
|
@@ -42,6 +45,8 @@ function isEmpty(obj) {
|
|
|
42
45
|
return false;
|
|
43
46
|
if (isArray(obj))
|
|
44
47
|
return obj.length === 0;
|
|
48
|
+
if (isMap(obj) || isSet(obj))
|
|
49
|
+
return obj.size === 0;
|
|
45
50
|
for (const key in obj) {
|
|
46
51
|
if (hasOwnProperty.call(obj, key)) {
|
|
47
52
|
return false;
|
|
@@ -305,13 +310,13 @@ function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
|
|
|
305
310
|
}
|
|
306
311
|
if (p === void 0) {
|
|
307
312
|
if (mode === "merge") {
|
|
308
|
-
obj =
|
|
313
|
+
obj = deepMerge(obj, value, false, 0);
|
|
309
314
|
} else {
|
|
310
315
|
obj = value;
|
|
311
316
|
}
|
|
312
317
|
} else {
|
|
313
318
|
if (mode === "merge") {
|
|
314
|
-
o[p] =
|
|
319
|
+
o[p] = deepMerge(o[p], value, false, 0);
|
|
315
320
|
} else if (isMap(o)) {
|
|
316
321
|
o.set(p, value);
|
|
317
322
|
} else {
|
|
@@ -342,56 +347,58 @@ function setInObservableAtPath(value$, path, pathTypes, value, mode) {
|
|
|
342
347
|
}
|
|
343
348
|
}
|
|
344
349
|
function mergeIntoObservable(target, ...sources) {
|
|
350
|
+
if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
|
|
351
|
+
if (!isObservable(target)) {
|
|
352
|
+
console.error("[legend-state] should only use mergeIntoObservable with observables");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
345
355
|
beginBatch();
|
|
346
356
|
for (let i = 0; i < sources.length; i++) {
|
|
347
|
-
|
|
357
|
+
_mergeIntoObservable(
|
|
348
358
|
target,
|
|
349
359
|
sources[i],
|
|
350
360
|
/*assign*/
|
|
351
|
-
i < sources.length - 1
|
|
361
|
+
i < sources.length - 1,
|
|
362
|
+
0
|
|
352
363
|
);
|
|
353
364
|
}
|
|
354
365
|
endBatch();
|
|
355
366
|
return target;
|
|
356
367
|
}
|
|
357
|
-
function _mergeIntoObservable(target, source, assign2) {
|
|
358
|
-
var _a;
|
|
368
|
+
function _mergeIntoObservable(target, source, assign2, levelsDeep) {
|
|
359
369
|
if (isObservable(source)) {
|
|
360
370
|
source = source.peek();
|
|
361
371
|
}
|
|
362
|
-
const
|
|
363
|
-
const targetValue = needsSet ? target.peek() : target;
|
|
372
|
+
const targetValue = target.peek();
|
|
364
373
|
const isTargetArr = isArray(targetValue);
|
|
365
374
|
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
366
|
-
|
|
367
|
-
|
|
375
|
+
const isSourceMap = isMap(source);
|
|
376
|
+
const isSourceSet = isSet(source);
|
|
377
|
+
if (isSourceSet && isSet(targetValue)) {
|
|
378
|
+
target.set(/* @__PURE__ */ new Set([...source, ...targetValue]));
|
|
379
|
+
} else if (isTargetObj && isObject(source) && !isEmpty(targetValue) || isTargetArr && targetValue.length > 0) {
|
|
380
|
+
const keys = isSourceMap || isSourceSet ? Array.from(source.keys()) : Object.keys(source);
|
|
368
381
|
for (let i = 0; i < keys.length; i++) {
|
|
369
382
|
const key = keys[i];
|
|
370
|
-
const sourceValue = source[key];
|
|
383
|
+
const sourceValue = isSourceSet ? key : isSourceMap ? source.get(key) : source[key];
|
|
371
384
|
if (sourceValue === symbolDelete) {
|
|
372
|
-
|
|
385
|
+
target[key].delete();
|
|
373
386
|
} else {
|
|
374
387
|
const isObj = isObject(sourceValue);
|
|
375
388
|
const isArr = !isObj && isArray(sourceValue);
|
|
376
389
|
const targetChild = target[key];
|
|
377
|
-
if ((isObj || isArr) && targetChild
|
|
378
|
-
if (
|
|
379
|
-
target[key] = assign2 ? isArr ? [...sourceValue] : { ...sourceValue } : sourceValue;
|
|
380
|
-
} else {
|
|
381
|
-
_mergeIntoObservable(targetChild, sourceValue);
|
|
382
|
-
}
|
|
383
|
-
} else {
|
|
384
|
-
if (needsSet) {
|
|
390
|
+
if ((isObj || isArr) && targetChild) {
|
|
391
|
+
if (levelsDeep > 0 && isEmpty(sourceValue)) {
|
|
385
392
|
targetChild.set(sourceValue);
|
|
386
|
-
} else {
|
|
387
|
-
const toSet = isObservable(sourceValue) ? sourceValue : isObject(sourceValue) ? { ...sourceValue } : isArray(sourceValue) ? [...sourceValue] : sourceValue;
|
|
388
|
-
target[key] = toSet;
|
|
389
393
|
}
|
|
394
|
+
_mergeIntoObservable(targetChild, sourceValue, false, levelsDeep + 1);
|
|
395
|
+
} else {
|
|
396
|
+
targetChild.set(sourceValue);
|
|
390
397
|
}
|
|
391
398
|
}
|
|
392
399
|
}
|
|
393
400
|
} else if (source !== void 0) {
|
|
394
|
-
|
|
401
|
+
target.set(source);
|
|
395
402
|
}
|
|
396
403
|
return target;
|
|
397
404
|
}
|
|
@@ -446,6 +453,25 @@ function applyChanges(value, changes, applyPrevious) {
|
|
|
446
453
|
}
|
|
447
454
|
return value;
|
|
448
455
|
}
|
|
456
|
+
function deepMerge(target, ...sources) {
|
|
457
|
+
const result = { ...target };
|
|
458
|
+
for (let i = 0; i < sources.length; i++) {
|
|
459
|
+
const obj2 = sources[i];
|
|
460
|
+
for (const key in obj2) {
|
|
461
|
+
if (hasOwnProperty.call(obj2, key)) {
|
|
462
|
+
if (obj2[key] instanceof Object && !isObservable(obj2[key]) && Object.keys(obj2[key]).length > 0) {
|
|
463
|
+
result[key] = deepMerge(
|
|
464
|
+
result[key] || (isArray(obj2[key]) ? [] : {}),
|
|
465
|
+
obj2[key]
|
|
466
|
+
);
|
|
467
|
+
} else {
|
|
468
|
+
result[key] = obj2[key];
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
449
475
|
|
|
450
476
|
// src/batching.ts
|
|
451
477
|
var timeout;
|
|
@@ -2315,6 +2341,7 @@ function runWithRetry(state, fn) {
|
|
|
2315
2341
|
var internal = {
|
|
2316
2342
|
createPreviousHandler,
|
|
2317
2343
|
clone,
|
|
2344
|
+
deepMerge,
|
|
2318
2345
|
ensureNodeValue,
|
|
2319
2346
|
findIDKey,
|
|
2320
2347
|
get,
|
package/index.mjs
CHANGED
|
@@ -31,6 +31,9 @@ function isPromise(obj) {
|
|
|
31
31
|
function isMap(obj) {
|
|
32
32
|
return obj instanceof Map;
|
|
33
33
|
}
|
|
34
|
+
function isSet(obj) {
|
|
35
|
+
return obj instanceof Set;
|
|
36
|
+
}
|
|
34
37
|
function isNumber(obj) {
|
|
35
38
|
const n = obj;
|
|
36
39
|
return n - n < 1;
|
|
@@ -40,6 +43,8 @@ function isEmpty(obj) {
|
|
|
40
43
|
return false;
|
|
41
44
|
if (isArray(obj))
|
|
42
45
|
return obj.length === 0;
|
|
46
|
+
if (isMap(obj) || isSet(obj))
|
|
47
|
+
return obj.size === 0;
|
|
43
48
|
for (const key in obj) {
|
|
44
49
|
if (hasOwnProperty.call(obj, key)) {
|
|
45
50
|
return false;
|
|
@@ -303,13 +308,13 @@ function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
|
|
|
303
308
|
}
|
|
304
309
|
if (p === void 0) {
|
|
305
310
|
if (mode === "merge") {
|
|
306
|
-
obj =
|
|
311
|
+
obj = deepMerge(obj, value, false, 0);
|
|
307
312
|
} else {
|
|
308
313
|
obj = value;
|
|
309
314
|
}
|
|
310
315
|
} else {
|
|
311
316
|
if (mode === "merge") {
|
|
312
|
-
o[p] =
|
|
317
|
+
o[p] = deepMerge(o[p], value, false, 0);
|
|
313
318
|
} else if (isMap(o)) {
|
|
314
319
|
o.set(p, value);
|
|
315
320
|
} else {
|
|
@@ -340,56 +345,58 @@ function setInObservableAtPath(value$, path, pathTypes, value, mode) {
|
|
|
340
345
|
}
|
|
341
346
|
}
|
|
342
347
|
function mergeIntoObservable(target, ...sources) {
|
|
348
|
+
if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
|
|
349
|
+
if (!isObservable(target)) {
|
|
350
|
+
console.error("[legend-state] should only use mergeIntoObservable with observables");
|
|
351
|
+
}
|
|
352
|
+
}
|
|
343
353
|
beginBatch();
|
|
344
354
|
for (let i = 0; i < sources.length; i++) {
|
|
345
|
-
|
|
355
|
+
_mergeIntoObservable(
|
|
346
356
|
target,
|
|
347
357
|
sources[i],
|
|
348
358
|
/*assign*/
|
|
349
|
-
i < sources.length - 1
|
|
359
|
+
i < sources.length - 1,
|
|
360
|
+
0
|
|
350
361
|
);
|
|
351
362
|
}
|
|
352
363
|
endBatch();
|
|
353
364
|
return target;
|
|
354
365
|
}
|
|
355
|
-
function _mergeIntoObservable(target, source, assign2) {
|
|
356
|
-
var _a;
|
|
366
|
+
function _mergeIntoObservable(target, source, assign2, levelsDeep) {
|
|
357
367
|
if (isObservable(source)) {
|
|
358
368
|
source = source.peek();
|
|
359
369
|
}
|
|
360
|
-
const
|
|
361
|
-
const targetValue = needsSet ? target.peek() : target;
|
|
370
|
+
const targetValue = target.peek();
|
|
362
371
|
const isTargetArr = isArray(targetValue);
|
|
363
372
|
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
364
|
-
|
|
365
|
-
|
|
373
|
+
const isSourceMap = isMap(source);
|
|
374
|
+
const isSourceSet = isSet(source);
|
|
375
|
+
if (isSourceSet && isSet(targetValue)) {
|
|
376
|
+
target.set(/* @__PURE__ */ new Set([...source, ...targetValue]));
|
|
377
|
+
} else if (isTargetObj && isObject(source) && !isEmpty(targetValue) || isTargetArr && targetValue.length > 0) {
|
|
378
|
+
const keys = isSourceMap || isSourceSet ? Array.from(source.keys()) : Object.keys(source);
|
|
366
379
|
for (let i = 0; i < keys.length; i++) {
|
|
367
380
|
const key = keys[i];
|
|
368
|
-
const sourceValue = source[key];
|
|
381
|
+
const sourceValue = isSourceSet ? key : isSourceMap ? source.get(key) : source[key];
|
|
369
382
|
if (sourceValue === symbolDelete) {
|
|
370
|
-
|
|
383
|
+
target[key].delete();
|
|
371
384
|
} else {
|
|
372
385
|
const isObj = isObject(sourceValue);
|
|
373
386
|
const isArr = !isObj && isArray(sourceValue);
|
|
374
387
|
const targetChild = target[key];
|
|
375
|
-
if ((isObj || isArr) && targetChild
|
|
376
|
-
if (
|
|
377
|
-
target[key] = assign2 ? isArr ? [...sourceValue] : { ...sourceValue } : sourceValue;
|
|
378
|
-
} else {
|
|
379
|
-
_mergeIntoObservable(targetChild, sourceValue);
|
|
380
|
-
}
|
|
381
|
-
} else {
|
|
382
|
-
if (needsSet) {
|
|
388
|
+
if ((isObj || isArr) && targetChild) {
|
|
389
|
+
if (levelsDeep > 0 && isEmpty(sourceValue)) {
|
|
383
390
|
targetChild.set(sourceValue);
|
|
384
|
-
} else {
|
|
385
|
-
const toSet = isObservable(sourceValue) ? sourceValue : isObject(sourceValue) ? { ...sourceValue } : isArray(sourceValue) ? [...sourceValue] : sourceValue;
|
|
386
|
-
target[key] = toSet;
|
|
387
391
|
}
|
|
392
|
+
_mergeIntoObservable(targetChild, sourceValue, false, levelsDeep + 1);
|
|
393
|
+
} else {
|
|
394
|
+
targetChild.set(sourceValue);
|
|
388
395
|
}
|
|
389
396
|
}
|
|
390
397
|
}
|
|
391
398
|
} else if (source !== void 0) {
|
|
392
|
-
|
|
399
|
+
target.set(source);
|
|
393
400
|
}
|
|
394
401
|
return target;
|
|
395
402
|
}
|
|
@@ -444,6 +451,25 @@ function applyChanges(value, changes, applyPrevious) {
|
|
|
444
451
|
}
|
|
445
452
|
return value;
|
|
446
453
|
}
|
|
454
|
+
function deepMerge(target, ...sources) {
|
|
455
|
+
const result = { ...target };
|
|
456
|
+
for (let i = 0; i < sources.length; i++) {
|
|
457
|
+
const obj2 = sources[i];
|
|
458
|
+
for (const key in obj2) {
|
|
459
|
+
if (hasOwnProperty.call(obj2, key)) {
|
|
460
|
+
if (obj2[key] instanceof Object && !isObservable(obj2[key]) && Object.keys(obj2[key]).length > 0) {
|
|
461
|
+
result[key] = deepMerge(
|
|
462
|
+
result[key] || (isArray(obj2[key]) ? [] : {}),
|
|
463
|
+
obj2[key]
|
|
464
|
+
);
|
|
465
|
+
} else {
|
|
466
|
+
result[key] = obj2[key];
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return result;
|
|
472
|
+
}
|
|
447
473
|
|
|
448
474
|
// src/batching.ts
|
|
449
475
|
var timeout;
|
|
@@ -2313,6 +2339,7 @@ function runWithRetry(state, fn) {
|
|
|
2313
2339
|
var internal = {
|
|
2314
2340
|
createPreviousHandler,
|
|
2315
2341
|
clone,
|
|
2342
|
+
deepMerge,
|
|
2316
2343
|
ensureNodeValue,
|
|
2317
2344
|
findIDKey,
|
|
2318
2345
|
get,
|
package/package.json
CHANGED
package/sync-plugins/crud.js
CHANGED
|
@@ -123,11 +123,18 @@ function syncedCrud(props) {
|
|
|
123
123
|
}
|
|
124
124
|
} : void 0;
|
|
125
125
|
const set = createFn || updateFn || deleteFn ? async (params) => {
|
|
126
|
-
const { value, changes, update, retryAsCreate,
|
|
126
|
+
const { value, changes, update, retryAsCreate, node } = params;
|
|
127
127
|
const creates = /* @__PURE__ */ new Map();
|
|
128
128
|
const updates = /* @__PURE__ */ new Map();
|
|
129
129
|
const deletes = /* @__PURE__ */ new Set();
|
|
130
|
-
|
|
130
|
+
const getUpdateValue = (itemValue, prev) => {
|
|
131
|
+
return updatePartial ? Object.assign(
|
|
132
|
+
sync.diffObjects(prev, itemValue),
|
|
133
|
+
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
134
|
+
) : itemValue;
|
|
135
|
+
};
|
|
136
|
+
changes.forEach((change) => {
|
|
137
|
+
const { path, prevAtPath, valueAtPath, pathTypes } = change;
|
|
131
138
|
if (asType === "value") {
|
|
132
139
|
if (value) {
|
|
133
140
|
let id = value == null ? void 0 : value[fieldId];
|
|
@@ -140,12 +147,18 @@ function syncedCrud(props) {
|
|
|
140
147
|
creates.set(id, value);
|
|
141
148
|
} else if (path.length === 0) {
|
|
142
149
|
if (valueAtPath) {
|
|
143
|
-
updates.set(id, valueAtPath);
|
|
150
|
+
updates.set(id, getUpdateValue(valueAtPath, prevAtPath));
|
|
144
151
|
} else if (prevAtPath) {
|
|
145
152
|
deletes.add(prevAtPath == null ? void 0 : prevAtPath.id);
|
|
146
153
|
}
|
|
147
|
-
} else {
|
|
148
|
-
|
|
154
|
+
} else if (!updates.has(id)) {
|
|
155
|
+
const previous = state.applyChanges(
|
|
156
|
+
clone(value),
|
|
157
|
+
changes,
|
|
158
|
+
/*applyPrevious*/
|
|
159
|
+
true
|
|
160
|
+
);
|
|
161
|
+
updates.set(id, getUpdateValue(value, previous));
|
|
149
162
|
}
|
|
150
163
|
} else {
|
|
151
164
|
console.error("[legend-state]: added synced item without an id");
|
|
@@ -154,13 +167,22 @@ function syncedCrud(props) {
|
|
|
154
167
|
deletes.add(prevAtPath);
|
|
155
168
|
}
|
|
156
169
|
} else {
|
|
157
|
-
let itemsChanged =
|
|
170
|
+
let itemsChanged = [];
|
|
158
171
|
if (path.length === 0) {
|
|
159
|
-
|
|
172
|
+
const changed = asMap ? Array.from(valueAtPath.entries()) : Object.entries(valueAtPath);
|
|
173
|
+
for (let i = 0; i < changed.length; i++) {
|
|
174
|
+
const [key, value2] = changed[i];
|
|
160
175
|
const prev = asMap ? prevAtPath.get(key) : prevAtPath[key];
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
176
|
+
if (state.isNullOrUndefined(value2) && !state.isNullOrUndefined(prev)) {
|
|
177
|
+
deletes.add(prev);
|
|
178
|
+
return false;
|
|
179
|
+
} else {
|
|
180
|
+
const isDiff = !prevAtPath || !sync.deepEqual(value2, prev);
|
|
181
|
+
if (isDiff) {
|
|
182
|
+
itemsChanged.push([getUpdateValue(value2, prev), prev]);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
164
186
|
} else {
|
|
165
187
|
const itemKey = path[0];
|
|
166
188
|
const itemValue = asMap ? value.get(itemKey) : value[itemKey];
|
|
@@ -169,36 +191,34 @@ function syncedCrud(props) {
|
|
|
169
191
|
deletes.add(prevAtPath);
|
|
170
192
|
}
|
|
171
193
|
} else {
|
|
172
|
-
|
|
194
|
+
const previous = state.setAtPath(
|
|
195
|
+
clone(itemValue),
|
|
196
|
+
path.slice(1),
|
|
197
|
+
pathTypes.slice(1),
|
|
198
|
+
prevAtPath
|
|
199
|
+
);
|
|
200
|
+
itemsChanged = [[getUpdateValue(itemValue, previous), previous]];
|
|
173
201
|
}
|
|
174
202
|
}
|
|
175
|
-
itemsChanged == null ? void 0 : itemsChanged.forEach(([
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
203
|
+
itemsChanged == null ? void 0 : itemsChanged.forEach(([item, prev]) => {
|
|
204
|
+
const isCreate = fieldCreatedAt ? !item[fieldCreatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : fieldUpdatedAt ? !item[fieldUpdatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : state.isNullOrUndefined(prev);
|
|
205
|
+
if (isCreate) {
|
|
206
|
+
if (generateId) {
|
|
207
|
+
ensureId(item, fieldId, generateId);
|
|
208
|
+
}
|
|
209
|
+
if (!item.id) {
|
|
210
|
+
console.error("[legend-state]: added item without an id");
|
|
211
|
+
}
|
|
212
|
+
if (createFn) {
|
|
213
|
+
creates.set(item.id, item);
|
|
214
|
+
} else {
|
|
215
|
+
console.log("[legend-state] missing create function");
|
|
180
216
|
}
|
|
181
217
|
} else {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (isCreate) {
|
|
185
|
-
if (generateId) {
|
|
186
|
-
ensureId(item, fieldId, generateId);
|
|
187
|
-
}
|
|
188
|
-
if (!item.id) {
|
|
189
|
-
console.error("[legend-state]: added item without an id");
|
|
190
|
-
}
|
|
191
|
-
if (createFn) {
|
|
192
|
-
creates.set(item.id, item);
|
|
193
|
-
} else {
|
|
194
|
-
console.log("[legend-state] missing create function");
|
|
195
|
-
}
|
|
218
|
+
if (updateFn) {
|
|
219
|
+
updates.set(item.id, item);
|
|
196
220
|
} else {
|
|
197
|
-
|
|
198
|
-
updates.set(item.id, item);
|
|
199
|
-
} else {
|
|
200
|
-
console.log("[legend-state] missing update function");
|
|
201
|
-
}
|
|
221
|
+
console.log("[legend-state] missing update function");
|
|
202
222
|
}
|
|
203
223
|
}
|
|
204
224
|
});
|
|
@@ -256,10 +276,7 @@ function syncedCrud(props) {
|
|
|
256
276
|
);
|
|
257
277
|
}),
|
|
258
278
|
...Array.from(updates).map(async ([itemKey, itemValue]) => {
|
|
259
|
-
const toSave =
|
|
260
|
-
sync.diffObjects(asType === "value" ? valuePrevious : valuePrevious[itemKey], itemValue),
|
|
261
|
-
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
262
|
-
) : itemValue;
|
|
279
|
+
const toSave = itemValue;
|
|
263
280
|
const changed = await transformOut(toSave, transform == null ? void 0 : transform.save);
|
|
264
281
|
if (Object.keys(changed).length > 0) {
|
|
265
282
|
return updateFn(changed, params).then(
|
|
@@ -267,11 +284,11 @@ function syncedCrud(props) {
|
|
|
267
284
|
);
|
|
268
285
|
}
|
|
269
286
|
}),
|
|
270
|
-
...Array.from(deletes).map((
|
|
287
|
+
...Array.from(deletes).map((valuePrevious) => {
|
|
271
288
|
if (deleteFn) {
|
|
272
|
-
deleteFn(
|
|
289
|
+
deleteFn(valuePrevious, params);
|
|
273
290
|
} else if (fieldDeleted && updateFn) {
|
|
274
|
-
const valueId =
|
|
291
|
+
const valueId = valuePrevious[fieldId];
|
|
275
292
|
updateFn(
|
|
276
293
|
{ ...valueId ? { [fieldId]: valueId } : {}, [fieldDeleted]: true },
|
|
277
294
|
params
|
package/sync-plugins/crud.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPromise, isNullOrUndefined,
|
|
1
|
+
import { isPromise, applyChanges, isNullOrUndefined, setAtPath, isArray, internal, isObservable, getNodeValue } from '@legendapp/state';
|
|
2
2
|
import { synced, deepEqual, diffObjects } from '@legendapp/state/sync';
|
|
3
3
|
|
|
4
4
|
// src/sync-plugins/crud.ts
|
|
@@ -121,11 +121,18 @@ function syncedCrud(props) {
|
|
|
121
121
|
}
|
|
122
122
|
} : void 0;
|
|
123
123
|
const set = createFn || updateFn || deleteFn ? async (params) => {
|
|
124
|
-
const { value, changes, update, retryAsCreate,
|
|
124
|
+
const { value, changes, update, retryAsCreate, node } = params;
|
|
125
125
|
const creates = /* @__PURE__ */ new Map();
|
|
126
126
|
const updates = /* @__PURE__ */ new Map();
|
|
127
127
|
const deletes = /* @__PURE__ */ new Set();
|
|
128
|
-
|
|
128
|
+
const getUpdateValue = (itemValue, prev) => {
|
|
129
|
+
return updatePartial ? Object.assign(
|
|
130
|
+
diffObjects(prev, itemValue),
|
|
131
|
+
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
132
|
+
) : itemValue;
|
|
133
|
+
};
|
|
134
|
+
changes.forEach((change) => {
|
|
135
|
+
const { path, prevAtPath, valueAtPath, pathTypes } = change;
|
|
129
136
|
if (asType === "value") {
|
|
130
137
|
if (value) {
|
|
131
138
|
let id = value == null ? void 0 : value[fieldId];
|
|
@@ -138,12 +145,18 @@ function syncedCrud(props) {
|
|
|
138
145
|
creates.set(id, value);
|
|
139
146
|
} else if (path.length === 0) {
|
|
140
147
|
if (valueAtPath) {
|
|
141
|
-
updates.set(id, valueAtPath);
|
|
148
|
+
updates.set(id, getUpdateValue(valueAtPath, prevAtPath));
|
|
142
149
|
} else if (prevAtPath) {
|
|
143
150
|
deletes.add(prevAtPath == null ? void 0 : prevAtPath.id);
|
|
144
151
|
}
|
|
145
|
-
} else {
|
|
146
|
-
|
|
152
|
+
} else if (!updates.has(id)) {
|
|
153
|
+
const previous = applyChanges(
|
|
154
|
+
clone(value),
|
|
155
|
+
changes,
|
|
156
|
+
/*applyPrevious*/
|
|
157
|
+
true
|
|
158
|
+
);
|
|
159
|
+
updates.set(id, getUpdateValue(value, previous));
|
|
147
160
|
}
|
|
148
161
|
} else {
|
|
149
162
|
console.error("[legend-state]: added synced item without an id");
|
|
@@ -152,13 +165,22 @@ function syncedCrud(props) {
|
|
|
152
165
|
deletes.add(prevAtPath);
|
|
153
166
|
}
|
|
154
167
|
} else {
|
|
155
|
-
let itemsChanged =
|
|
168
|
+
let itemsChanged = [];
|
|
156
169
|
if (path.length === 0) {
|
|
157
|
-
|
|
170
|
+
const changed = asMap ? Array.from(valueAtPath.entries()) : Object.entries(valueAtPath);
|
|
171
|
+
for (let i = 0; i < changed.length; i++) {
|
|
172
|
+
const [key, value2] = changed[i];
|
|
158
173
|
const prev = asMap ? prevAtPath.get(key) : prevAtPath[key];
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
174
|
+
if (isNullOrUndefined(value2) && !isNullOrUndefined(prev)) {
|
|
175
|
+
deletes.add(prev);
|
|
176
|
+
return false;
|
|
177
|
+
} else {
|
|
178
|
+
const isDiff = !prevAtPath || !deepEqual(value2, prev);
|
|
179
|
+
if (isDiff) {
|
|
180
|
+
itemsChanged.push([getUpdateValue(value2, prev), prev]);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
162
184
|
} else {
|
|
163
185
|
const itemKey = path[0];
|
|
164
186
|
const itemValue = asMap ? value.get(itemKey) : value[itemKey];
|
|
@@ -167,36 +189,34 @@ function syncedCrud(props) {
|
|
|
167
189
|
deletes.add(prevAtPath);
|
|
168
190
|
}
|
|
169
191
|
} else {
|
|
170
|
-
|
|
192
|
+
const previous = setAtPath(
|
|
193
|
+
clone(itemValue),
|
|
194
|
+
path.slice(1),
|
|
195
|
+
pathTypes.slice(1),
|
|
196
|
+
prevAtPath
|
|
197
|
+
);
|
|
198
|
+
itemsChanged = [[getUpdateValue(itemValue, previous), previous]];
|
|
171
199
|
}
|
|
172
200
|
}
|
|
173
|
-
itemsChanged == null ? void 0 : itemsChanged.forEach(([
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
|
|
201
|
+
itemsChanged == null ? void 0 : itemsChanged.forEach(([item, prev]) => {
|
|
202
|
+
const isCreate = fieldCreatedAt ? !item[fieldCreatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : fieldUpdatedAt ? !item[fieldUpdatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : isNullOrUndefined(prev);
|
|
203
|
+
if (isCreate) {
|
|
204
|
+
if (generateId) {
|
|
205
|
+
ensureId(item, fieldId, generateId);
|
|
206
|
+
}
|
|
207
|
+
if (!item.id) {
|
|
208
|
+
console.error("[legend-state]: added item without an id");
|
|
209
|
+
}
|
|
210
|
+
if (createFn) {
|
|
211
|
+
creates.set(item.id, item);
|
|
212
|
+
} else {
|
|
213
|
+
console.log("[legend-state] missing create function");
|
|
178
214
|
}
|
|
179
215
|
} else {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (isCreate) {
|
|
183
|
-
if (generateId) {
|
|
184
|
-
ensureId(item, fieldId, generateId);
|
|
185
|
-
}
|
|
186
|
-
if (!item.id) {
|
|
187
|
-
console.error("[legend-state]: added item without an id");
|
|
188
|
-
}
|
|
189
|
-
if (createFn) {
|
|
190
|
-
creates.set(item.id, item);
|
|
191
|
-
} else {
|
|
192
|
-
console.log("[legend-state] missing create function");
|
|
193
|
-
}
|
|
216
|
+
if (updateFn) {
|
|
217
|
+
updates.set(item.id, item);
|
|
194
218
|
} else {
|
|
195
|
-
|
|
196
|
-
updates.set(item.id, item);
|
|
197
|
-
} else {
|
|
198
|
-
console.log("[legend-state] missing update function");
|
|
199
|
-
}
|
|
219
|
+
console.log("[legend-state] missing update function");
|
|
200
220
|
}
|
|
201
221
|
}
|
|
202
222
|
});
|
|
@@ -254,10 +274,7 @@ function syncedCrud(props) {
|
|
|
254
274
|
);
|
|
255
275
|
}),
|
|
256
276
|
...Array.from(updates).map(async ([itemKey, itemValue]) => {
|
|
257
|
-
const toSave =
|
|
258
|
-
diffObjects(asType === "value" ? valuePrevious : valuePrevious[itemKey], itemValue),
|
|
259
|
-
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
260
|
-
) : itemValue;
|
|
277
|
+
const toSave = itemValue;
|
|
261
278
|
const changed = await transformOut(toSave, transform == null ? void 0 : transform.save);
|
|
262
279
|
if (Object.keys(changed).length > 0) {
|
|
263
280
|
return updateFn(changed, params).then(
|
|
@@ -265,11 +282,11 @@ function syncedCrud(props) {
|
|
|
265
282
|
);
|
|
266
283
|
}
|
|
267
284
|
}),
|
|
268
|
-
...Array.from(deletes).map((
|
|
285
|
+
...Array.from(deletes).map((valuePrevious) => {
|
|
269
286
|
if (deleteFn) {
|
|
270
|
-
deleteFn(
|
|
287
|
+
deleteFn(valuePrevious, params);
|
|
271
288
|
} else if (fieldDeleted && updateFn) {
|
|
272
|
-
const valueId =
|
|
289
|
+
const valueId = valuePrevious[fieldId];
|
|
273
290
|
updateFn(
|
|
274
291
|
{ ...valueId ? { [fieldId]: valueId } : {}, [fieldDeleted]: true },
|
|
275
292
|
params
|
package/sync-plugins/keel.js
CHANGED
|
@@ -216,7 +216,7 @@ function syncedKeel(props) {
|
|
|
216
216
|
const create = createParam ? async (input, params) => {
|
|
217
217
|
const { data, error } = await createParam(convertObjectToCreate(input));
|
|
218
218
|
if (error) {
|
|
219
|
-
handleSetError(error, params, "create");
|
|
219
|
+
await handleSetError(error, params, "create");
|
|
220
220
|
}
|
|
221
221
|
return data;
|
|
222
222
|
} : void 0;
|
|
@@ -229,7 +229,7 @@ function syncedKeel(props) {
|
|
|
229
229
|
if (!state.isEmpty(values)) {
|
|
230
230
|
const { data, error } = await updateParam({ where: { id }, values });
|
|
231
231
|
if (error) {
|
|
232
|
-
handleSetError(error, params, "update");
|
|
232
|
+
await handleSetError(error, params, "update");
|
|
233
233
|
}
|
|
234
234
|
return data;
|
|
235
235
|
}
|
|
@@ -237,7 +237,7 @@ function syncedKeel(props) {
|
|
|
237
237
|
const deleteFn = deleteParam ? async (value, params) => {
|
|
238
238
|
const { data, error } = await deleteParam({ id: value.id });
|
|
239
239
|
if (error) {
|
|
240
|
-
handleSetError(error, params, "delete");
|
|
240
|
+
await handleSetError(error, params, "delete");
|
|
241
241
|
}
|
|
242
242
|
return data;
|
|
243
243
|
} : void 0;
|
package/sync-plugins/keel.mjs
CHANGED
|
@@ -210,7 +210,7 @@ function syncedKeel(props) {
|
|
|
210
210
|
const create = createParam ? async (input, params) => {
|
|
211
211
|
const { data, error } = await createParam(convertObjectToCreate(input));
|
|
212
212
|
if (error) {
|
|
213
|
-
handleSetError(error, params, "create");
|
|
213
|
+
await handleSetError(error, params, "create");
|
|
214
214
|
}
|
|
215
215
|
return data;
|
|
216
216
|
} : void 0;
|
|
@@ -223,7 +223,7 @@ function syncedKeel(props) {
|
|
|
223
223
|
if (!isEmpty(values)) {
|
|
224
224
|
const { data, error } = await updateParam({ where: { id }, values });
|
|
225
225
|
if (error) {
|
|
226
|
-
handleSetError(error, params, "update");
|
|
226
|
+
await handleSetError(error, params, "update");
|
|
227
227
|
}
|
|
228
228
|
return data;
|
|
229
229
|
}
|
|
@@ -231,7 +231,7 @@ function syncedKeel(props) {
|
|
|
231
231
|
const deleteFn = deleteParam ? async (value, params) => {
|
|
232
232
|
const { data, error } = await deleteParam({ id: value.id });
|
|
233
233
|
if (error) {
|
|
234
|
-
handleSetError(error, params, "delete");
|
|
234
|
+
await handleSetError(error, params, "delete");
|
|
235
235
|
}
|
|
236
236
|
return data;
|
|
237
237
|
} : void 0;
|
package/sync.d.mts
CHANGED
|
@@ -32,7 +32,6 @@ interface SyncedGetParams<T> extends SyncedGetSetSubscribeBaseParams<T> {
|
|
|
32
32
|
options: SyncedOptions;
|
|
33
33
|
}
|
|
34
34
|
interface SyncedSetParams<T> extends Pick<SetParams<T>, 'changes' | 'value'>, SyncedGetSetSubscribeBaseParams<T> {
|
|
35
|
-
valuePrevious: T;
|
|
36
35
|
update: UpdateFn<T>;
|
|
37
36
|
cancelRetry: () => void;
|
|
38
37
|
retryNum: number;
|
|
@@ -108,7 +107,6 @@ interface ObservableSyncSetParams<T> {
|
|
|
108
107
|
options: SyncedOptions<T>;
|
|
109
108
|
changes: Change[];
|
|
110
109
|
value: T;
|
|
111
|
-
valuePrevious: T;
|
|
112
110
|
}
|
|
113
111
|
interface ObservableSyncFunctions<T = any> {
|
|
114
112
|
get?(params: SyncedGetParams<T>): T | Promise<T>;
|
package/sync.d.ts
CHANGED
|
@@ -32,7 +32,6 @@ interface SyncedGetParams<T> extends SyncedGetSetSubscribeBaseParams<T> {
|
|
|
32
32
|
options: SyncedOptions;
|
|
33
33
|
}
|
|
34
34
|
interface SyncedSetParams<T> extends Pick<SetParams<T>, 'changes' | 'value'>, SyncedGetSetSubscribeBaseParams<T> {
|
|
35
|
-
valuePrevious: T;
|
|
36
35
|
update: UpdateFn<T>;
|
|
37
36
|
cancelRetry: () => void;
|
|
38
37
|
retryNum: number;
|
|
@@ -108,7 +107,6 @@ interface ObservableSyncSetParams<T> {
|
|
|
108
107
|
options: SyncedOptions<T>;
|
|
109
108
|
changes: Change[];
|
|
110
109
|
value: T;
|
|
111
|
-
valuePrevious: T;
|
|
112
110
|
}
|
|
113
111
|
interface ObservableSyncFunctions<T = any> {
|
|
114
112
|
get?(params: SyncedGetParams<T>): T | Promise<T>;
|
package/sync.js
CHANGED
|
@@ -137,7 +137,17 @@ function transformStringifyDates(...args) {
|
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
|
-
var {
|
|
140
|
+
var {
|
|
141
|
+
clone,
|
|
142
|
+
deepMerge,
|
|
143
|
+
getNode,
|
|
144
|
+
getNodeValue,
|
|
145
|
+
getValueAtPath,
|
|
146
|
+
globalState,
|
|
147
|
+
runWithRetry,
|
|
148
|
+
symbolLinked,
|
|
149
|
+
createPreviousHandler
|
|
150
|
+
} = state.internal;
|
|
141
151
|
var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
|
|
142
152
|
var allSyncStates = /* @__PURE__ */ new Map();
|
|
143
153
|
var metadatas = /* @__PURE__ */ new WeakMap();
|
|
@@ -247,7 +257,6 @@ function mergeQueuedChanges(allChanges) {
|
|
|
247
257
|
if (!previousByOptions.has(syncOptions)) {
|
|
248
258
|
previousByOptions.set(syncOptions, getPrevious());
|
|
249
259
|
}
|
|
250
|
-
value.valuePrevious = previousByOptions.get(syncOptions);
|
|
251
260
|
targetMap.set(syncOptions, value);
|
|
252
261
|
}
|
|
253
262
|
return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
|
|
@@ -360,8 +369,7 @@ async function prepChangeRemote(queuedChange) {
|
|
|
360
369
|
localState,
|
|
361
370
|
syncOptions,
|
|
362
371
|
inRemoteChange,
|
|
363
|
-
isApplyingPending
|
|
364
|
-
valuePrevious
|
|
372
|
+
isApplyingPending
|
|
365
373
|
} = queuedChange;
|
|
366
374
|
const persist = syncOptions.persist;
|
|
367
375
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
@@ -437,8 +445,7 @@ async function prepChangeRemote(queuedChange) {
|
|
|
437
445
|
pathTypes,
|
|
438
446
|
prevAtPath,
|
|
439
447
|
valueAtPath: valueTransformed,
|
|
440
|
-
pathStr
|
|
441
|
-
valuePrevious
|
|
448
|
+
pathStr
|
|
442
449
|
});
|
|
443
450
|
})
|
|
444
451
|
);
|
|
@@ -485,7 +492,7 @@ async function doChangeRemote(changeInfo) {
|
|
|
485
492
|
if (!changeInfo)
|
|
486
493
|
return;
|
|
487
494
|
const { queuedChange, changesRemote } = changeInfo;
|
|
488
|
-
const { value$: obs$, syncState: syncState2, localState, syncOptions
|
|
495
|
+
const { value$: obs$, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
489
496
|
const { pluginPersist } = localState;
|
|
490
497
|
const node = getNode(obs$);
|
|
491
498
|
const state$ = node.state;
|
|
@@ -505,11 +512,6 @@ async function doChangeRemote(changeInfo) {
|
|
|
505
512
|
if (!state.isNullOrUndefined(pendingAtPath)) {
|
|
506
513
|
const { p } = pendingAtPath;
|
|
507
514
|
change.prevAtPath = p;
|
|
508
|
-
if (key) {
|
|
509
|
-
state.setAtPath(change.valuePrevious, change.path, change.pathTypes, p, "set");
|
|
510
|
-
} else {
|
|
511
|
-
change.valuePrevious = p;
|
|
512
|
-
}
|
|
513
515
|
}
|
|
514
516
|
});
|
|
515
517
|
}
|
|
@@ -539,14 +541,13 @@ async function doChangeRemote(changeInfo) {
|
|
|
539
541
|
value$: obs$,
|
|
540
542
|
changes: changesRemote,
|
|
541
543
|
value,
|
|
542
|
-
valuePrevious: previous,
|
|
543
544
|
onError,
|
|
544
545
|
update: (params) => {
|
|
545
546
|
if (updateResult) {
|
|
546
547
|
const { value: value2, lastSync, mode } = params;
|
|
547
548
|
updateResult = {
|
|
548
549
|
lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
|
|
549
|
-
value:
|
|
550
|
+
value: deepMerge(updateResult.value, value2),
|
|
550
551
|
mode
|
|
551
552
|
};
|
|
552
553
|
} else {
|
|
@@ -703,25 +704,6 @@ async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
|
703
704
|
}
|
|
704
705
|
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
705
706
|
}
|
|
706
|
-
function deepMerge(target, ...sources) {
|
|
707
|
-
const result = { ...target };
|
|
708
|
-
for (let i = 0; i < sources.length; i++) {
|
|
709
|
-
const obj2 = sources[i];
|
|
710
|
-
for (const key in obj2) {
|
|
711
|
-
if (state.hasOwnProperty.call(obj2, key)) {
|
|
712
|
-
if (obj2[key] instanceof Object && !state.isObservable(obj2[key]) && Object.keys(obj2[key]).length > 0) {
|
|
713
|
-
result[key] = deepMerge(
|
|
714
|
-
result[key] || (state.isArray(obj2[key]) ? [] : {}),
|
|
715
|
-
obj2[key]
|
|
716
|
-
);
|
|
717
|
-
} else {
|
|
718
|
-
result[key] = obj2[key];
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
return result;
|
|
724
|
-
}
|
|
725
707
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
726
708
|
let syncOptions = syncOptionsOrSynced;
|
|
727
709
|
if (state.isFunction(syncOptions)) {
|
package/sync.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction, syncState, when, linked, internal, observable, isPromise, mergeIntoObservable,
|
|
1
|
+
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction, syncState, when, linked, internal, observable, isPromise, mergeIntoObservable, isEmpty, whenReady, shouldIgnoreUnobserved, constructObjectWithPath, setAtPath, isArray } from '@legendapp/state';
|
|
2
2
|
|
|
3
3
|
// src/sync/configureObservableSync.ts
|
|
4
4
|
var observableSyncConfiguration = {};
|
|
@@ -135,7 +135,17 @@ function transformStringifyDates(...args) {
|
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
|
-
var {
|
|
138
|
+
var {
|
|
139
|
+
clone,
|
|
140
|
+
deepMerge,
|
|
141
|
+
getNode,
|
|
142
|
+
getNodeValue,
|
|
143
|
+
getValueAtPath,
|
|
144
|
+
globalState,
|
|
145
|
+
runWithRetry,
|
|
146
|
+
symbolLinked,
|
|
147
|
+
createPreviousHandler
|
|
148
|
+
} = internal;
|
|
139
149
|
var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
|
|
140
150
|
var allSyncStates = /* @__PURE__ */ new Map();
|
|
141
151
|
var metadatas = /* @__PURE__ */ new WeakMap();
|
|
@@ -245,7 +255,6 @@ function mergeQueuedChanges(allChanges) {
|
|
|
245
255
|
if (!previousByOptions.has(syncOptions)) {
|
|
246
256
|
previousByOptions.set(syncOptions, getPrevious());
|
|
247
257
|
}
|
|
248
|
-
value.valuePrevious = previousByOptions.get(syncOptions);
|
|
249
258
|
targetMap.set(syncOptions, value);
|
|
250
259
|
}
|
|
251
260
|
return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
|
|
@@ -358,8 +367,7 @@ async function prepChangeRemote(queuedChange) {
|
|
|
358
367
|
localState,
|
|
359
368
|
syncOptions,
|
|
360
369
|
inRemoteChange,
|
|
361
|
-
isApplyingPending
|
|
362
|
-
valuePrevious
|
|
370
|
+
isApplyingPending
|
|
363
371
|
} = queuedChange;
|
|
364
372
|
const persist = syncOptions.persist;
|
|
365
373
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
@@ -435,8 +443,7 @@ async function prepChangeRemote(queuedChange) {
|
|
|
435
443
|
pathTypes,
|
|
436
444
|
prevAtPath,
|
|
437
445
|
valueAtPath: valueTransformed,
|
|
438
|
-
pathStr
|
|
439
|
-
valuePrevious
|
|
446
|
+
pathStr
|
|
440
447
|
});
|
|
441
448
|
})
|
|
442
449
|
);
|
|
@@ -483,7 +490,7 @@ async function doChangeRemote(changeInfo) {
|
|
|
483
490
|
if (!changeInfo)
|
|
484
491
|
return;
|
|
485
492
|
const { queuedChange, changesRemote } = changeInfo;
|
|
486
|
-
const { value$: obs$, syncState: syncState2, localState, syncOptions
|
|
493
|
+
const { value$: obs$, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
487
494
|
const { pluginPersist } = localState;
|
|
488
495
|
const node = getNode(obs$);
|
|
489
496
|
const state$ = node.state;
|
|
@@ -503,11 +510,6 @@ async function doChangeRemote(changeInfo) {
|
|
|
503
510
|
if (!isNullOrUndefined(pendingAtPath)) {
|
|
504
511
|
const { p } = pendingAtPath;
|
|
505
512
|
change.prevAtPath = p;
|
|
506
|
-
if (key) {
|
|
507
|
-
setAtPath(change.valuePrevious, change.path, change.pathTypes, p, "set");
|
|
508
|
-
} else {
|
|
509
|
-
change.valuePrevious = p;
|
|
510
|
-
}
|
|
511
513
|
}
|
|
512
514
|
});
|
|
513
515
|
}
|
|
@@ -537,14 +539,13 @@ async function doChangeRemote(changeInfo) {
|
|
|
537
539
|
value$: obs$,
|
|
538
540
|
changes: changesRemote,
|
|
539
541
|
value,
|
|
540
|
-
valuePrevious: previous,
|
|
541
542
|
onError,
|
|
542
543
|
update: (params) => {
|
|
543
544
|
if (updateResult) {
|
|
544
545
|
const { value: value2, lastSync, mode } = params;
|
|
545
546
|
updateResult = {
|
|
546
547
|
lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
|
|
547
|
-
value:
|
|
548
|
+
value: deepMerge(updateResult.value, value2),
|
|
548
549
|
mode
|
|
549
550
|
};
|
|
550
551
|
} else {
|
|
@@ -701,25 +702,6 @@ async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
|
701
702
|
}
|
|
702
703
|
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
703
704
|
}
|
|
704
|
-
function deepMerge(target, ...sources) {
|
|
705
|
-
const result = { ...target };
|
|
706
|
-
for (let i = 0; i < sources.length; i++) {
|
|
707
|
-
const obj2 = sources[i];
|
|
708
|
-
for (const key in obj2) {
|
|
709
|
-
if (hasOwnProperty.call(obj2, key)) {
|
|
710
|
-
if (obj2[key] instanceof Object && !isObservable(obj2[key]) && Object.keys(obj2[key]).length > 0) {
|
|
711
|
-
result[key] = deepMerge(
|
|
712
|
-
result[key] || (isArray(obj2[key]) ? [] : {}),
|
|
713
|
-
obj2[key]
|
|
714
|
-
);
|
|
715
|
-
} else {
|
|
716
|
-
result[key] = obj2[key];
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
return result;
|
|
722
|
-
}
|
|
723
705
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
724
706
|
let syncOptions = syncOptionsOrSynced;
|
|
725
707
|
if (isFunction(syncOptions)) {
|