@anfenn/zync 0.3.4 → 0.4.1
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/README.md +25 -20
- package/dist/index.cjs +189 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -6
- package/dist/index.d.ts +19 -6
- package/dist/index.js +186 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,9 +23,40 @@ function newLogger(base, min) {
|
|
|
23
23
|
|
|
24
24
|
// src/helpers.ts
|
|
25
25
|
var SYNC_FIELDS = ["_localId", "updated_at", "deleted"];
|
|
26
|
-
function
|
|
26
|
+
function createLocalId() {
|
|
27
27
|
return crypto.randomUUID();
|
|
28
28
|
}
|
|
29
|
+
function sleep(ms) {
|
|
30
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
}
|
|
32
|
+
function changeKeysTo(input, toIdKey, toUpdatedAtKey, toDeletedKey) {
|
|
33
|
+
if (!input) return input;
|
|
34
|
+
const isArray = Array.isArray(input);
|
|
35
|
+
const result = (isArray ? input : [input]).map((item) => {
|
|
36
|
+
const { id, updated_at, deleted, ...rest } = item;
|
|
37
|
+
return {
|
|
38
|
+
[toIdKey]: id,
|
|
39
|
+
[toUpdatedAtKey]: updated_at,
|
|
40
|
+
[toDeletedKey]: deleted,
|
|
41
|
+
...rest
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
return isArray ? result : result[0];
|
|
45
|
+
}
|
|
46
|
+
function changeKeysFrom(input, fromIdKey, fromUpdatedAtKey, fromDeletedKey) {
|
|
47
|
+
if (!input) return input;
|
|
48
|
+
const isArray = Array.isArray(input);
|
|
49
|
+
const result = (isArray ? input : [input]).map((item) => {
|
|
50
|
+
const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
updated_at,
|
|
54
|
+
deleted,
|
|
55
|
+
...rest
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
return isArray ? result : result[0];
|
|
59
|
+
}
|
|
29
60
|
function orderFor(a) {
|
|
30
61
|
switch (a) {
|
|
31
62
|
case "create" /* Create */:
|
|
@@ -42,8 +73,8 @@ function omitSyncFields(item) {
|
|
|
42
73
|
return result;
|
|
43
74
|
}
|
|
44
75
|
function samePendingVersion(get, stateKey, localId, version) {
|
|
45
|
-
const
|
|
46
|
-
const curChange =
|
|
76
|
+
const pending = get().syncState.pendingChanges || [];
|
|
77
|
+
const curChange = pending.find((p) => p.localId === localId && p.stateKey === stateKey);
|
|
47
78
|
return curChange?.version === version;
|
|
48
79
|
}
|
|
49
80
|
function removeFromPendingChanges(set, localId, stateKey) {
|
|
@@ -77,7 +108,7 @@ function tryAddToPendingChanges(pendingChanges, stateKey, changes) {
|
|
|
77
108
|
queueItem.changes = { ...queueItem.changes, ...omittedItem };
|
|
78
109
|
}
|
|
79
110
|
} else if (action === "remove" /* Remove */ || hasChanges) {
|
|
80
|
-
pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem });
|
|
111
|
+
pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem, before: omitSyncFields(change.currentItem) });
|
|
81
112
|
}
|
|
82
113
|
}
|
|
83
114
|
}
|
|
@@ -89,6 +120,30 @@ function setPendingChangeToUpdate(get, stateKey, localId, id) {
|
|
|
89
120
|
if (id) change.id = id;
|
|
90
121
|
}
|
|
91
122
|
}
|
|
123
|
+
function setPendingChangeBefore(get, stateKey, localId, before) {
|
|
124
|
+
const pendingChanges = get().syncState.pendingChanges || [];
|
|
125
|
+
const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);
|
|
126
|
+
if (change) {
|
|
127
|
+
change.before = { ...change.before, ...before };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function tryUpdateConflicts(pendingChanges, conflicts) {
|
|
131
|
+
if (!conflicts) return conflicts;
|
|
132
|
+
const newConflicts = { ...conflicts };
|
|
133
|
+
for (const change of pendingChanges) {
|
|
134
|
+
const conflict = newConflicts[change.localId];
|
|
135
|
+
if (conflict && change.changes) {
|
|
136
|
+
const newFields = conflict.fields.map((f) => {
|
|
137
|
+
if (f.key in change.changes) {
|
|
138
|
+
return { ...f, localValue: change.changes[f.key] };
|
|
139
|
+
}
|
|
140
|
+
return f;
|
|
141
|
+
});
|
|
142
|
+
newConflicts[change.localId] = { stateKey: conflict.stateKey, fields: newFields };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return newConflicts;
|
|
146
|
+
}
|
|
92
147
|
function findApi(stateKey, syncApi) {
|
|
93
148
|
const api = syncApi[stateKey];
|
|
94
149
|
if (!api || !api.add || !api.update || !api.remove || !api.list || !api.firstLoad) {
|
|
@@ -130,6 +185,50 @@ function findChanges(current, updated) {
|
|
|
130
185
|
}
|
|
131
186
|
return changesMap;
|
|
132
187
|
}
|
|
188
|
+
function hasKeysOrUndefined(obj) {
|
|
189
|
+
return Object.keys(obj).length === 0 ? void 0 : obj;
|
|
190
|
+
}
|
|
191
|
+
function hasConflicts(get, localId) {
|
|
192
|
+
const state = get();
|
|
193
|
+
if (state.syncState.conflicts) {
|
|
194
|
+
return !!state.syncState.conflicts[localId];
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
function resolveConflict(set, localId, keepLocalFields) {
|
|
199
|
+
set((state) => {
|
|
200
|
+
const syncState = state.syncState || {};
|
|
201
|
+
const conflicts = syncState.conflicts || {};
|
|
202
|
+
const conflict = conflicts[localId];
|
|
203
|
+
if (conflict) {
|
|
204
|
+
const items = state[conflict.stateKey];
|
|
205
|
+
const item = items.find((i) => i._localId === localId);
|
|
206
|
+
if (!item) {
|
|
207
|
+
return state;
|
|
208
|
+
}
|
|
209
|
+
const resolved = { ...item };
|
|
210
|
+
let pendingChanges = [...syncState.pendingChanges];
|
|
211
|
+
if (!keepLocalFields) {
|
|
212
|
+
for (const field of conflict.fields) {
|
|
213
|
+
resolved[field.key] = field.remoteValue;
|
|
214
|
+
}
|
|
215
|
+
pendingChanges = pendingChanges.filter((p) => !(p.stateKey === conflict.stateKey && p.localId === localId));
|
|
216
|
+
}
|
|
217
|
+
const nextItems = items.map((i) => i._localId === localId ? resolved : i);
|
|
218
|
+
const nextConflicts = { ...conflicts };
|
|
219
|
+
delete nextConflicts[localId];
|
|
220
|
+
return {
|
|
221
|
+
[conflict.stateKey]: nextItems,
|
|
222
|
+
syncState: {
|
|
223
|
+
...syncState,
|
|
224
|
+
pendingChanges,
|
|
225
|
+
conflicts: hasKeysOrUndefined(nextConflicts)
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return state;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
133
232
|
|
|
134
233
|
// src/pull.ts
|
|
135
234
|
async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy) {
|
|
@@ -140,7 +239,8 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
|
|
|
140
239
|
if (!serverData?.length) return;
|
|
141
240
|
let newest = lastPulledAt;
|
|
142
241
|
set((state) => {
|
|
143
|
-
|
|
242
|
+
let pendingChanges = [...state.syncState.pendingChanges];
|
|
243
|
+
const conflicts = { ...state.syncState.conflicts };
|
|
144
244
|
const localItems = state[stateKey] || [];
|
|
145
245
|
let nextItems = [...localItems];
|
|
146
246
|
const localById = new Map(localItems.filter((l) => l.id).map((l) => [l.id, l]));
|
|
@@ -164,43 +264,43 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
|
|
|
164
264
|
if (localItem) {
|
|
165
265
|
const pendingChange = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localItem._localId);
|
|
166
266
|
if (pendingChange) {
|
|
267
|
+
logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);
|
|
167
268
|
switch (conflictResolutionStrategy) {
|
|
168
|
-
case "
|
|
169
|
-
logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);
|
|
269
|
+
case "client-wins":
|
|
170
270
|
break;
|
|
171
|
-
case "
|
|
172
|
-
const merged = {
|
|
173
|
-
...remote,
|
|
174
|
-
_localId: localItem._localId
|
|
175
|
-
};
|
|
271
|
+
case "server-wins": {
|
|
272
|
+
const merged = { ...remote, _localId: localItem._localId };
|
|
176
273
|
nextItems = nextItems.map((i) => i._localId === localItem._localId ? merged : i);
|
|
177
|
-
|
|
274
|
+
pendingChanges = pendingChanges.filter((p) => !(p.stateKey === stateKey && p.localId === localItem._localId));
|
|
178
275
|
break;
|
|
179
276
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
277
|
+
case "try-shallow-merge": {
|
|
278
|
+
const changes = pendingChange.changes || {};
|
|
279
|
+
const before = pendingChange.before || {};
|
|
280
|
+
const fields = Object.entries(changes).filter(([k, localValue]) => k in before && k in remote && before[k] !== remote[k] && localValue !== remote[k]).map(([key, localValue]) => ({ key, localValue, remoteValue: remote[key] }));
|
|
281
|
+
if (fields.length > 0) {
|
|
282
|
+
logger.warn(`[zync] pull:${conflictResolutionStrategy}:conflicts-found`, JSON.stringify(fields, null, 4));
|
|
283
|
+
conflicts[localItem._localId] = { stateKey, fields };
|
|
284
|
+
} else {
|
|
285
|
+
const localChangedKeys = Object.keys(changes);
|
|
286
|
+
const preservedLocal = { _localId: localItem._localId };
|
|
287
|
+
for (const k of localChangedKeys) {
|
|
288
|
+
if (k in localItem) preservedLocal[k] = localItem[k];
|
|
289
|
+
}
|
|
290
|
+
const merged = { ...remote, ...preservedLocal };
|
|
291
|
+
nextItems = nextItems.map((i) => i._localId === localItem._localId ? merged : i);
|
|
292
|
+
delete conflicts[localItem._localId];
|
|
293
|
+
}
|
|
192
294
|
break;
|
|
295
|
+
}
|
|
193
296
|
}
|
|
194
297
|
} else {
|
|
195
|
-
const merged = {
|
|
196
|
-
...localItem,
|
|
197
|
-
...remote
|
|
198
|
-
};
|
|
298
|
+
const merged = { ...localItem, ...remote };
|
|
199
299
|
nextItems = nextItems.map((i) => i._localId === localItem._localId ? merged : i);
|
|
200
300
|
logger.debug(`[zync] pull:merge-remote stateKey=${stateKey} id=${remote.id}`);
|
|
201
301
|
}
|
|
202
302
|
} else {
|
|
203
|
-
nextItems = [...nextItems, { ...remote, _localId:
|
|
303
|
+
nextItems = [...nextItems, { ...remote, _localId: createLocalId() }];
|
|
204
304
|
logger.debug(`[zync] pull:add stateKey=${stateKey} id=${remote.id}`);
|
|
205
305
|
}
|
|
206
306
|
}
|
|
@@ -208,6 +308,8 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
|
|
|
208
308
|
[stateKey]: nextItems,
|
|
209
309
|
syncState: {
|
|
210
310
|
...state.syncState || {},
|
|
311
|
+
pendingChanges,
|
|
312
|
+
conflicts: hasKeysOrUndefined(conflicts),
|
|
211
313
|
lastPulled: {
|
|
212
314
|
...state.syncState.lastPulled || {},
|
|
213
315
|
[stateKey]: newest.toISOString()
|
|
@@ -221,7 +323,6 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
|
|
|
221
323
|
async function pushOne(set, get, change, api, logger, setAndQueueToSync, missingStrategy, onMissingRemoteRecordDuringUpdate, onAfterRemoteAdd) {
|
|
222
324
|
logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);
|
|
223
325
|
const { action, stateKey, localId, id, version, changes } = change;
|
|
224
|
-
const changesClone = { ...changes };
|
|
225
326
|
switch (action) {
|
|
226
327
|
case "remove" /* Remove */:
|
|
227
328
|
if (!id) {
|
|
@@ -234,11 +335,17 @@ async function pushOne(set, get, change, api, logger, setAndQueueToSync, missing
|
|
|
234
335
|
removeFromPendingChanges(set, localId, stateKey);
|
|
235
336
|
break;
|
|
236
337
|
case "update" /* Update */: {
|
|
237
|
-
|
|
338
|
+
if (hasConflicts(get, change.localId)) {
|
|
339
|
+
logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const exists = await api.update(id, changes);
|
|
238
343
|
if (exists) {
|
|
239
344
|
logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);
|
|
240
345
|
if (samePendingVersion(get, stateKey, localId, version)) {
|
|
241
346
|
removeFromPendingChanges(set, localId, stateKey);
|
|
347
|
+
} else {
|
|
348
|
+
setPendingChangeBefore(get, stateKey, localId, changes);
|
|
242
349
|
}
|
|
243
350
|
return;
|
|
244
351
|
} else {
|
|
@@ -260,7 +367,7 @@ async function pushOne(set, get, change, api, logger, setAndQueueToSync, missing
|
|
|
260
367
|
case "insert-remote-record": {
|
|
261
368
|
const newItem = {
|
|
262
369
|
...item,
|
|
263
|
-
_localId:
|
|
370
|
+
_localId: createLocalId(),
|
|
264
371
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
265
372
|
};
|
|
266
373
|
setAndQueueToSync((s) => ({
|
|
@@ -282,7 +389,7 @@ async function pushOne(set, get, change, api, logger, setAndQueueToSync, missing
|
|
|
282
389
|
break;
|
|
283
390
|
}
|
|
284
391
|
case "create" /* Create */: {
|
|
285
|
-
const result = await api.add(
|
|
392
|
+
const result = await api.add(changes);
|
|
286
393
|
if (result) {
|
|
287
394
|
logger.debug(`[zync] push:create:success stateKey=${stateKey} localId=${localId} id=${id}`);
|
|
288
395
|
set((s) => ({
|
|
@@ -339,7 +446,7 @@ async function startFirstLoad(set, syncApi, logger) {
|
|
|
339
446
|
} else {
|
|
340
447
|
next.push({
|
|
341
448
|
...remote,
|
|
342
|
-
_localId:
|
|
449
|
+
_localId: createLocalId()
|
|
343
450
|
});
|
|
344
451
|
}
|
|
345
452
|
}
|
|
@@ -453,17 +560,17 @@ function createIndexedDBStorage(options) {
|
|
|
453
560
|
}
|
|
454
561
|
|
|
455
562
|
// src/index.ts
|
|
456
|
-
var SyncAction = /* @__PURE__ */ ((
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
return
|
|
563
|
+
var SyncAction = /* @__PURE__ */ ((SyncAction3) => {
|
|
564
|
+
SyncAction3["Create"] = "create";
|
|
565
|
+
SyncAction3["Update"] = "update";
|
|
566
|
+
SyncAction3["Remove"] = "remove";
|
|
567
|
+
return SyncAction3;
|
|
461
568
|
})(SyncAction || {});
|
|
462
|
-
var DEFAULT_SYNC_INTERVAL_MILLIS =
|
|
569
|
+
var DEFAULT_SYNC_INTERVAL_MILLIS = 2e3;
|
|
463
570
|
var DEFAULT_LOGGER = console;
|
|
464
571
|
var DEFAULT_MIN_LOG_LEVEL = "debug";
|
|
465
572
|
var DEFAULT_MISSING_REMOTE_RECORD_STRATEGY = "ignore";
|
|
466
|
-
var DEFAULT_CONFLICT_RESOLUTION_STRATEGY = "
|
|
573
|
+
var DEFAULT_CONFLICT_RESOLUTION_STRATEGY = "client-wins";
|
|
467
574
|
function createWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}) {
|
|
468
575
|
const store = create(persistWithSync(stateCreator, persistOptions, syncApi, syncOptions));
|
|
469
576
|
return new Promise((resolve) => {
|
|
@@ -500,7 +607,8 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
500
607
|
syncState: {
|
|
501
608
|
firstLoadDone: syncState.firstLoadDone,
|
|
502
609
|
pendingChanges: syncState.pendingChanges,
|
|
503
|
-
lastPulled: syncState.lastPulled
|
|
610
|
+
lastPulled: syncState.lastPulled,
|
|
611
|
+
conflicts: syncState.conflicts
|
|
504
612
|
}
|
|
505
613
|
};
|
|
506
614
|
},
|
|
@@ -509,7 +617,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
509
617
|
return {
|
|
510
618
|
...state,
|
|
511
619
|
syncState: {
|
|
512
|
-
...state.syncState,
|
|
620
|
+
...state.syncState || {},
|
|
513
621
|
status: "idle"
|
|
514
622
|
// this confirms 'hydrating' is done
|
|
515
623
|
}
|
|
@@ -517,13 +625,12 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
517
625
|
}
|
|
518
626
|
};
|
|
519
627
|
const creator = (set, get, storeApi) => {
|
|
520
|
-
let
|
|
628
|
+
let syncTimerStarted = false;
|
|
521
629
|
async function syncOnce() {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
set((state2) => ({
|
|
630
|
+
if (get().syncState.status !== "idle") return;
|
|
631
|
+
set((state) => ({
|
|
525
632
|
syncState: {
|
|
526
|
-
...
|
|
633
|
+
...state.syncState || {},
|
|
527
634
|
status: "syncing"
|
|
528
635
|
}
|
|
529
636
|
}));
|
|
@@ -558,24 +665,13 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
558
665
|
logger.error(`[zync] push:error change=${change}`, err);
|
|
559
666
|
}
|
|
560
667
|
}
|
|
561
|
-
set((
|
|
668
|
+
set((state) => ({
|
|
562
669
|
syncState: {
|
|
563
|
-
...
|
|
670
|
+
...state.syncState || {},
|
|
564
671
|
status: "idle",
|
|
565
672
|
error: firstSyncError
|
|
566
673
|
}
|
|
567
674
|
}));
|
|
568
|
-
if (get().syncState.pendingChanges.length > 0 && !firstSyncError) {
|
|
569
|
-
await syncOnce();
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
function setAndSyncOnce(partial) {
|
|
573
|
-
if (typeof partial === "function") {
|
|
574
|
-
set((state) => ({ ...partial(state) }));
|
|
575
|
-
} else {
|
|
576
|
-
set(partial);
|
|
577
|
-
}
|
|
578
|
-
syncOnce();
|
|
579
675
|
}
|
|
580
676
|
function setAndQueueToSync(partial) {
|
|
581
677
|
if (typeof partial === "function") {
|
|
@@ -583,7 +679,6 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
583
679
|
} else {
|
|
584
680
|
set((state) => newSyncState(state, partial));
|
|
585
681
|
}
|
|
586
|
-
syncOnce();
|
|
587
682
|
}
|
|
588
683
|
function newSyncState(state, partial) {
|
|
589
684
|
const pendingChanges = state.syncState.pendingChanges || [];
|
|
@@ -593,11 +688,13 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
593
688
|
const changes = findChanges(current, updated);
|
|
594
689
|
tryAddToPendingChanges(pendingChanges, stateKey, changes);
|
|
595
690
|
});
|
|
691
|
+
const conflicts = tryUpdateConflicts(pendingChanges, state.syncState.conflicts);
|
|
596
692
|
return {
|
|
597
693
|
...partial,
|
|
598
694
|
syncState: {
|
|
599
695
|
...state.syncState || {},
|
|
600
|
-
pendingChanges
|
|
696
|
+
pendingChanges,
|
|
697
|
+
conflicts
|
|
601
698
|
}
|
|
602
699
|
};
|
|
603
700
|
}
|
|
@@ -605,18 +702,26 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
605
702
|
set((state) => ({
|
|
606
703
|
syncState: {
|
|
607
704
|
...state.syncState || {},
|
|
608
|
-
enabled
|
|
705
|
+
status: enabled ? "idle" : "disabled"
|
|
609
706
|
}
|
|
610
707
|
}));
|
|
611
|
-
|
|
708
|
+
startSyncTimer(enabled);
|
|
612
709
|
addVisibilityChangeListener(enabled);
|
|
613
710
|
}
|
|
614
|
-
function
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
711
|
+
function startSyncTimer(start) {
|
|
712
|
+
if (start) {
|
|
713
|
+
tryStart();
|
|
714
|
+
} else {
|
|
715
|
+
syncTimerStarted = false;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
async function tryStart() {
|
|
719
|
+
if (syncTimerStarted) return;
|
|
720
|
+
syncTimerStarted = true;
|
|
721
|
+
while (true) {
|
|
722
|
+
if (!syncTimerStarted) break;
|
|
723
|
+
await syncOnce();
|
|
724
|
+
await sleep(syncInterval);
|
|
620
725
|
}
|
|
621
726
|
}
|
|
622
727
|
function addVisibilityChangeListener(add) {
|
|
@@ -629,24 +734,25 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
629
734
|
function onVisibilityChange() {
|
|
630
735
|
if (document.visibilityState === "visible") {
|
|
631
736
|
logger.debug("[zync] sync:start-in-foreground");
|
|
632
|
-
|
|
737
|
+
startSyncTimer(true);
|
|
633
738
|
} else {
|
|
634
739
|
logger.debug("[zync] sync:pause-in-background");
|
|
635
|
-
|
|
740
|
+
startSyncTimer(false);
|
|
636
741
|
}
|
|
637
742
|
}
|
|
638
743
|
storeApi.sync = {
|
|
639
744
|
enable,
|
|
640
|
-
startFirstLoad: () => startFirstLoad(set, syncApi, logger)
|
|
745
|
+
startFirstLoad: () => startFirstLoad(set, syncApi, logger),
|
|
746
|
+
resolveConflict: (localId, keepLocal) => resolveConflict(set, localId, keepLocal)
|
|
641
747
|
};
|
|
642
|
-
const userState = stateCreator(
|
|
748
|
+
const userState = stateCreator(set, get, setAndQueueToSync);
|
|
643
749
|
return {
|
|
644
750
|
...userState,
|
|
645
751
|
syncState: {
|
|
646
752
|
// set defaults
|
|
647
753
|
status: "hydrating",
|
|
648
754
|
error: void 0,
|
|
649
|
-
|
|
755
|
+
conflicts: void 0,
|
|
650
756
|
firstLoadDone: false,
|
|
651
757
|
pendingChanges: [],
|
|
652
758
|
lastPulled: {}
|
|
@@ -657,9 +763,11 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
657
763
|
}
|
|
658
764
|
export {
|
|
659
765
|
SyncAction,
|
|
766
|
+
changeKeysFrom,
|
|
767
|
+
changeKeysTo,
|
|
660
768
|
createIndexedDBStorage,
|
|
769
|
+
createLocalId,
|
|
661
770
|
createWithSync,
|
|
662
|
-
nextLocalId,
|
|
663
771
|
persistWithSync
|
|
664
772
|
};
|
|
665
773
|
//# sourceMappingURL=index.js.map
|