@anfenn/zync 0.1.23 → 0.2.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 +17 -16
- package/dist/index.cjs +145 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +145 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -61,9 +61,42 @@ function findApi(stateKey, syncApi) {
|
|
|
61
61
|
}
|
|
62
62
|
return api;
|
|
63
63
|
}
|
|
64
|
+
function findChanges(current, updated) {
|
|
65
|
+
const currentMap = /* @__PURE__ */ new Map();
|
|
66
|
+
for (const item of current) {
|
|
67
|
+
if (item && item._localId) {
|
|
68
|
+
currentMap.set(item._localId, item);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const changesMap = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const item of updated) {
|
|
73
|
+
if (item && item._localId) {
|
|
74
|
+
const curr = currentMap.get(item._localId);
|
|
75
|
+
if (curr) {
|
|
76
|
+
const diff = {};
|
|
77
|
+
for (const key in curr) {
|
|
78
|
+
if (key !== "_localId" && curr[key] !== item[key]) {
|
|
79
|
+
diff[key] = item[key];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (Object.keys(diff).length > 0) {
|
|
83
|
+
changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff });
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [localId, curr] of currentMap) {
|
|
91
|
+
if (!updated.some((u) => u && u._localId === localId)) {
|
|
92
|
+
changesMap.set(localId, { currentItem: curr, updatedItem: null, changes: null });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return changesMap;
|
|
96
|
+
}
|
|
64
97
|
|
|
65
98
|
// src/pull.ts
|
|
66
|
-
async function pull(set, get, stateKey, api, logger) {
|
|
99
|
+
async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy) {
|
|
67
100
|
const lastPulled = get().syncState.lastPulled || {};
|
|
68
101
|
const lastPulledAt = new Date(lastPulled[stateKey] || /* @__PURE__ */ new Date(0));
|
|
69
102
|
logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastPulledAt.toISOString()}`);
|
|
@@ -92,16 +125,53 @@ async function pull(set, get, stateKey, api, logger) {
|
|
|
92
125
|
continue;
|
|
93
126
|
}
|
|
94
127
|
delete remote.deleted;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
if (localItem) {
|
|
129
|
+
const pendingChange = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localItem._localId);
|
|
130
|
+
if (pendingChange) {
|
|
131
|
+
switch (conflictResolutionStrategy) {
|
|
132
|
+
case "local-wins":
|
|
133
|
+
logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);
|
|
134
|
+
break;
|
|
135
|
+
case "remote-wins": {
|
|
136
|
+
const merged = {
|
|
137
|
+
...remote,
|
|
138
|
+
_localId: localItem._localId
|
|
139
|
+
};
|
|
140
|
+
nextItems = nextItems.map((i) => i._localId === localItem._localId ? merged : i);
|
|
141
|
+
logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
// case 'try-shallow-merge':
|
|
145
|
+
// // Try and merge all fields, fail if not possible due to conflicts
|
|
146
|
+
// // throw new ConflictError('Details...');
|
|
147
|
+
// Object.entries(pendingChange.changes || {}).map(([key, value]) => {
|
|
148
|
+
// const localValue = localItem[key];
|
|
149
|
+
// const remoteValue = remote[key];
|
|
150
|
+
// if (localValue !== undefined && localValue !== value) {
|
|
151
|
+
// //throw new ConflictError(`Conflict on ${key}: local=${localValue} remote=${value}`);
|
|
152
|
+
// }
|
|
153
|
+
// });
|
|
154
|
+
// break;
|
|
155
|
+
// case 'custom':
|
|
156
|
+
// // Hook to allow custom userland logic
|
|
157
|
+
// // const error = onConflict(localItem, remote, stateKey, pending);
|
|
158
|
+
// // logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id} error=${error}`);
|
|
159
|
+
// // if (error) throw new ConflictError(error);
|
|
160
|
+
// break;
|
|
161
|
+
default:
|
|
162
|
+
logger.error(`[zync] pull:conflict-strategy:unknown stateKey=${stateKey} id=${remote.id} strategy=${conflictResolutionStrategy}`);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
const merged = {
|
|
167
|
+
...localItem,
|
|
168
|
+
...remote,
|
|
169
|
+
_localId: localItem._localId
|
|
170
|
+
};
|
|
171
|
+
nextItems = nextItems.map((i) => i._localId === localItem._localId ? merged : i);
|
|
172
|
+
logger.debug(`[zync] pull:merge-remote stateKey=${stateKey} id=${remote.id}`);
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
105
175
|
nextItems = [...nextItems, { ...remote, _localId: nextLocalId() }];
|
|
106
176
|
logger.debug(`[zync] pull:add stateKey=${stateKey} id=${remote.id}`);
|
|
107
177
|
}
|
|
@@ -121,7 +191,7 @@ async function pull(set, get, stateKey, api, logger) {
|
|
|
121
191
|
|
|
122
192
|
// src/push.ts
|
|
123
193
|
var SYNC_FIELDS = ["id", "_localId", "updated_at", "deleted"];
|
|
124
|
-
async function pushOne(set, get, change, api, logger,
|
|
194
|
+
async function pushOne(set, get, change, api, logger, setAndQueueToSync, missingStrategy, onMissingRemoteRecordDuringUpdate, onAfterRemoteAdd) {
|
|
125
195
|
logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);
|
|
126
196
|
const { action, stateKey, localId, id, version } = change;
|
|
127
197
|
switch (action) {
|
|
@@ -161,26 +231,27 @@ async function pushOne(set, get, change, api, logger, queueToSync, missingStrate
|
|
|
161
231
|
}
|
|
162
232
|
return;
|
|
163
233
|
} else {
|
|
164
|
-
logger.warn("[zync] push:update:missing-remote", {
|
|
165
|
-
stateKey,
|
|
166
|
-
localId,
|
|
167
|
-
id: item.id
|
|
168
|
-
});
|
|
169
234
|
switch (missingStrategy) {
|
|
170
235
|
case "delete-local-record":
|
|
171
236
|
set((s) => ({
|
|
172
237
|
[stateKey]: (s[stateKey] || []).filter((i) => i._localId !== localId)
|
|
173
238
|
}));
|
|
239
|
+
logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);
|
|
174
240
|
break;
|
|
175
|
-
case "insert-remote-record":
|
|
241
|
+
case "insert-remote-record":
|
|
176
242
|
omittedItem._localId = crypto.randomUUID();
|
|
177
243
|
omittedItem.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
178
|
-
|
|
244
|
+
setAndQueueToSync((s) => ({
|
|
179
245
|
[stateKey]: (s[stateKey] || []).map((i) => i._localId === localId ? omittedItem : i)
|
|
180
246
|
}));
|
|
181
|
-
|
|
247
|
+
logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);
|
|
248
|
+
break;
|
|
249
|
+
case "ignore":
|
|
250
|
+
logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
logger.error(`[zync] push:missing-remote:unknown stateKey=${stateKey} id=${item.id} strategy=${missingStrategy}`);
|
|
182
254
|
break;
|
|
183
|
-
}
|
|
184
255
|
}
|
|
185
256
|
removeFromPendingChanges(set, localId, stateKey);
|
|
186
257
|
onMissingRemoteRecordDuringUpdate?.(missingStrategy, item, omittedItem._localId);
|
|
@@ -200,7 +271,7 @@ async function pushOne(set, get, change, api, logger, queueToSync, missingStrate
|
|
|
200
271
|
if (samePendingVersion(get, stateKey, localId, version)) {
|
|
201
272
|
removeFromPendingChanges(set, localId, stateKey);
|
|
202
273
|
}
|
|
203
|
-
onAfterRemoteAdd?.(set, get,
|
|
274
|
+
onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, {
|
|
204
275
|
...item,
|
|
205
276
|
...result
|
|
206
277
|
});
|
|
@@ -306,6 +377,7 @@ var DEFAULT_SYNC_INTERVAL_MILLIS = 5e3;
|
|
|
306
377
|
var DEFAULT_LOGGER = console;
|
|
307
378
|
var DEFAULT_MIN_LOG_LEVEL = "debug";
|
|
308
379
|
var DEFAULT_MISSING_REMOTE_RECORD_STRATEGY = "ignore";
|
|
380
|
+
var DEFAULT_CONFLICT_RESOLUTION_STRATEGY = "local-wins";
|
|
309
381
|
function createWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}) {
|
|
310
382
|
const store = create(persistWithSync(stateCreator, persistOptions, syncApi, syncOptions));
|
|
311
383
|
return new Promise((resolve) => {
|
|
@@ -317,6 +389,7 @@ function createWithSync(stateCreator, persistOptions, syncApi, syncOptions = {})
|
|
|
317
389
|
function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}) {
|
|
318
390
|
const syncInterval = syncOptions.syncInterval ?? DEFAULT_SYNC_INTERVAL_MILLIS;
|
|
319
391
|
const missingStrategy = syncOptions.missingRemoteRecordDuringUpdateStrategy ?? DEFAULT_MISSING_REMOTE_RECORD_STRATEGY;
|
|
392
|
+
const conflictResolutionStrategy = syncOptions.conflictResolutionStrategy ?? DEFAULT_CONFLICT_RESOLUTION_STRATEGY;
|
|
320
393
|
const logger = newLogger(syncOptions.logger ?? DEFAULT_LOGGER, syncOptions.minLogLevel ?? DEFAULT_MIN_LOG_LEVEL);
|
|
321
394
|
const baseOnRehydrate = persistOptions?.onRehydrateStorage;
|
|
322
395
|
const basePartialize = persistOptions?.partialize;
|
|
@@ -372,15 +445,15 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
372
445
|
for (const stateKey of Object.keys(syncApi)) {
|
|
373
446
|
try {
|
|
374
447
|
const api = findApi(stateKey, syncApi);
|
|
375
|
-
await pull(set, get, stateKey, api, logger);
|
|
448
|
+
await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);
|
|
376
449
|
} catch (err) {
|
|
377
450
|
syncError = syncError ?? err;
|
|
378
451
|
logger.error(`[zync] pull:error stateKey=${stateKey}`, err);
|
|
379
452
|
}
|
|
380
453
|
}
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
for (const change of
|
|
454
|
+
const changesSnapshot = [...get().syncState.pendingChanges || []];
|
|
455
|
+
changesSnapshot.sort((a, b) => orderFor(a.action) - orderFor(b.action));
|
|
456
|
+
for (const change of changesSnapshot) {
|
|
384
457
|
try {
|
|
385
458
|
const api = findApi(change.stateKey, syncApi);
|
|
386
459
|
await pushOne(
|
|
@@ -389,7 +462,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
389
462
|
change,
|
|
390
463
|
api,
|
|
391
464
|
logger,
|
|
392
|
-
|
|
465
|
+
setAndQueueToSync,
|
|
393
466
|
missingStrategy,
|
|
394
467
|
syncOptions.onMissingRemoteRecordDuringUpdate,
|
|
395
468
|
syncOptions.onAfterRemoteAdd
|
|
@@ -473,40 +546,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
473
546
|
}
|
|
474
547
|
}));
|
|
475
548
|
}
|
|
476
|
-
function
|
|
477
|
-
set((state) => {
|
|
478
|
-
const pendingChanges = state.syncState.pendingChanges || [];
|
|
479
|
-
for (const localId of localIds) {
|
|
480
|
-
const item = state[stateKey].find((i) => i._localId === localId);
|
|
481
|
-
if (!item) {
|
|
482
|
-
logger.error(`[zync] queueToSync:no-local-item localId=${localId}`);
|
|
483
|
-
continue;
|
|
484
|
-
}
|
|
485
|
-
const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);
|
|
486
|
-
if (queueItem) {
|
|
487
|
-
queueItem.version += 1;
|
|
488
|
-
if (queueItem.action === "create-or-update" /* CreateOrUpdate */ && action === "remove" /* Remove */ && item.id) {
|
|
489
|
-
queueItem.action = "remove" /* Remove */;
|
|
490
|
-
queueItem.id = item.id;
|
|
491
|
-
logger.debug(`[zync] queueToSync:changed-to-remove action=${action} localId=${localId} v=${queueItem.version}`);
|
|
492
|
-
} else {
|
|
493
|
-
logger.debug(`[zync] queueToSync:re-queued action=${action} localId=${localId} v=${queueItem.version}`);
|
|
494
|
-
}
|
|
495
|
-
} else {
|
|
496
|
-
pendingChanges.push({ action, stateKey, localId, id: item.id, version: 1 });
|
|
497
|
-
logger.debug(`[zync] queueToSync:added action=${action} localId=${localId}`);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return {
|
|
501
|
-
syncState: {
|
|
502
|
-
...state.syncState || {},
|
|
503
|
-
pendingChanges
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
});
|
|
507
|
-
syncOnce();
|
|
508
|
-
}
|
|
509
|
-
function setAndSync(partial) {
|
|
549
|
+
function setAndSyncOnce(partial) {
|
|
510
550
|
if (typeof partial === "function") {
|
|
511
551
|
set((state) => ({ ...partial(state) }));
|
|
512
552
|
} else {
|
|
@@ -514,6 +554,49 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
514
554
|
}
|
|
515
555
|
syncOnce();
|
|
516
556
|
}
|
|
557
|
+
function setAndQueueToSync(partial) {
|
|
558
|
+
if (typeof partial === "function") {
|
|
559
|
+
set((state) => newSyncState(state, partial(state)));
|
|
560
|
+
} else {
|
|
561
|
+
set((state) => newSyncState(state, partial));
|
|
562
|
+
}
|
|
563
|
+
syncOnce();
|
|
564
|
+
}
|
|
565
|
+
function newSyncState(state, partial) {
|
|
566
|
+
const pendingChanges = state.syncState.pendingChanges || [];
|
|
567
|
+
Object.keys(partial).map((stateKey) => {
|
|
568
|
+
const current = state[stateKey];
|
|
569
|
+
const updated = partial[stateKey];
|
|
570
|
+
const changes = findChanges(current, updated);
|
|
571
|
+
addToPendingChanges(pendingChanges, stateKey, changes);
|
|
572
|
+
});
|
|
573
|
+
return {
|
|
574
|
+
...partial,
|
|
575
|
+
syncState: {
|
|
576
|
+
...state.syncState || {},
|
|
577
|
+
pendingChanges
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function addToPendingChanges(pendingChanges, stateKey, changes) {
|
|
582
|
+
for (const [localId, change] of changes) {
|
|
583
|
+
const action = change.updatedItem === null ? "remove" /* Remove */ : "create-or-update" /* CreateOrUpdate */;
|
|
584
|
+
const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);
|
|
585
|
+
if (queueItem) {
|
|
586
|
+
queueItem.version += 1;
|
|
587
|
+
if (queueItem.action === "create-or-update" /* CreateOrUpdate */ && action === "remove" /* Remove */ && change.currentItem.id) {
|
|
588
|
+
queueItem.action = "remove" /* Remove */;
|
|
589
|
+
queueItem.id = change.currentItem.id;
|
|
590
|
+
logger.debug(`[zync] addToPendingChanges:changed-to-remove action=${action} localId=${localId} v=${queueItem.version}`);
|
|
591
|
+
} else {
|
|
592
|
+
logger.debug(`[zync] addToPendingChanges:re-queued action=${action} localId=${localId} v=${queueItem.version}`);
|
|
593
|
+
}
|
|
594
|
+
} else {
|
|
595
|
+
pendingChanges.push({ action, stateKey, localId, id: change.currentItem?.id, version: 1, changes: change.changes });
|
|
596
|
+
logger.debug(`[zync] addToPendingChanges:added action=${action} localId=${localId}`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
517
600
|
function enable(enabled) {
|
|
518
601
|
set((state) => ({
|
|
519
602
|
syncState: {
|
|
@@ -552,7 +635,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
|
|
|
552
635
|
enable,
|
|
553
636
|
startFirstLoad
|
|
554
637
|
};
|
|
555
|
-
const userState = stateCreator(
|
|
638
|
+
const userState = stateCreator(setAndSyncOnce, get, setAndQueueToSync);
|
|
556
639
|
return {
|
|
557
640
|
...userState,
|
|
558
641
|
syncState: {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/helpers.ts","../src/pull.ts","../src/push.ts","../src/indexedDBStorage.ts"],"sourcesContent":["import { create, type StateCreator } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport { newLogger, type Logger, type LogLevel } from './logger';\nimport { orderFor, findApi, nextLocalId } from './helpers';\nimport type { ApiFunctions, SyncOptions, SyncState, SyncedStateCreator, PendingChange, UseStoreWithSync, MissingRemoteRecordStrategy } from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\n\nexport { createIndexedDBStorage } from './indexedDBStorage';\nexport { nextLocalId } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n CreateOrUpdate = 'create-or-update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 5000;\nconst DEFAULT_LOGGER: Logger = console;\nconst DEFAULT_MIN_LOG_LEVEL: LogLevel = 'debug';\nconst DEFAULT_MISSING_REMOTE_RECORD_STRATEGY: MissingRemoteRecordStrategy = 'ignore';\n\nexport function createWithSync<TStore extends object>(\n stateCreator: SyncedStateCreator<TStore>,\n persistOptions: any,\n syncApi: Record<string, ApiFunctions>,\n syncOptions: SyncOptions = {},\n): Promise<UseStoreWithSync<TStore>> {\n const store = create(persistWithSync(stateCreator, persistOptions, syncApi, syncOptions)) as UseStoreWithSync<TStore>;\n\n return new Promise<UseStoreWithSync<TStore>>((resolve) => {\n store.persist.onFinishHydration((_state) => {\n resolve(store);\n });\n });\n}\n\nexport function persistWithSync<TStore extends object>(\n stateCreator: SyncedStateCreator<TStore>,\n persistOptions: any,\n syncApi: Record<string, ApiFunctions>,\n syncOptions: SyncOptions = {},\n) {\n const syncInterval = syncOptions.syncInterval ?? DEFAULT_SYNC_INTERVAL_MILLIS;\n const missingStrategy = syncOptions.missingRemoteRecordDuringUpdateStrategy ?? DEFAULT_MISSING_REMOTE_RECORD_STRATEGY;\n const logger = newLogger(syncOptions.logger ?? DEFAULT_LOGGER, syncOptions.minLogLevel ?? DEFAULT_MIN_LOG_LEVEL);\n\n const baseOnRehydrate = persistOptions?.onRehydrateStorage;\n const basePartialize = persistOptions?.partialize;\n\n const wrappedPersistOptions = {\n ...persistOptions,\n onRehydrateStorage: () => {\n logger.debug('[zync] rehydration:start');\n\n return (state: any, error: any) => {\n if (error) {\n logger.error('[zync] rehydration:failed', error);\n } else {\n baseOnRehydrate?.(state, error);\n logger.debug('[zync] rehydration:complete', state);\n }\n };\n },\n partialize: (s: any) => {\n // Select state to be persisted\n\n const base = basePartialize ? basePartialize(s) : s;\n const { syncState, ...rest } = base || {};\n return {\n ...rest,\n syncState: {\n firstLoadDone: syncState.firstLoadDone,\n pendingChanges: syncState.pendingChanges,\n lastPulled: syncState.lastPulled,\n },\n };\n },\n merge: (persisted: any, current: any) => {\n // Here after hydration.\n // `persisted` is state from storage that's just loaded (possibly asynchronously e.g. IndexedDB)\n // `current` is what the user has defined (they may have added or removed state keys)\n // Zync is designed to not be used until hydration is complete, so we don't expect to have to\n // merge user mutated state (i.e. current) into persisted. So we do the Zustand recommended pattern of\n // shallow copy where persisted keys win:\n const state = { ...current, ...persisted };\n\n return {\n ...state,\n syncState: {\n ...state.syncState,\n status: 'idle', // this confirms 'hydrating' is done\n },\n };\n },\n };\n\n const creator: StateCreator<TStore & SyncState, [], []> = (set: any, get: any, storeApi: any) => {\n let syncIntervalId: any;\n\n async function syncOnce() {\n const state: SyncState = get();\n if (!state.syncState.enabled || state.syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let syncError: Error | undefined;\n\n // 1) PULL for each stateKey\n for (const stateKey of Object.keys(syncApi)) {\n try {\n const api = findApi(stateKey, syncApi);\n await pull(set, get, stateKey, api, logger);\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] pull:error stateKey=${stateKey}`, err);\n }\n }\n\n // 2) PUSH queued changes\n const snapshot: PendingChange[] = [...(get().syncState.pendingChanges || [])];\n\n // Deterministic ordering: Create -> Update -> Remove so dependencies (e.g. id assignment) happen early\n snapshot.sort((a, b) => orderFor(a.action) - orderFor(b.action));\n\n for (const change of snapshot) {\n try {\n const api = findApi(change.stateKey, syncApi);\n await pushOne(\n set,\n get,\n change,\n api,\n logger,\n queueToSync,\n missingStrategy,\n syncOptions.onMissingRemoteRecordDuringUpdate,\n syncOptions.onAfterRemoteAdd,\n );\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] push:error change=${change}`, err);\n }\n }\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'idle',\n error: syncError,\n },\n }));\n\n if (get().syncState.pendingChanges.length > 0 && !syncError) {\n // If there are pending changes and no sync error, we can sync again\n await syncOnce();\n }\n }\n\n async function startFirstLoad() {\n let syncError: Error | undefined;\n\n for (const stateKey of Object.keys(syncApi)) {\n try {\n logger.info(`[zync] firstLoad:start stateKey=${stateKey}`);\n\n const api = findApi(stateKey, syncApi);\n let lastId; // Start as undefined to allow the userland api code to set the initial value+type\n\n // Batch until empty\n while (true) {\n const batch = await api.firstLoad(lastId);\n if (!batch?.length) break;\n\n // Merge batch\n set((state: any) => {\n const local: any[] = state[stateKey] || [];\n const localById = new Map<any, any>(local.filter((l) => l.id).map((l) => [l.id, l]));\n\n let newest = new Date(state.syncState.lastPulled[stateKey] || 0);\n const next = [...local];\n for (const remote of batch) {\n const remoteUpdated = new Date(remote.updated_at || 0);\n if (remoteUpdated > newest) newest = remoteUpdated;\n\n if (remote.deleted) continue;\n\n delete remote.deleted;\n\n const localItem = remote.id ? localById.get(remote.id) : undefined;\n if (localItem) {\n const merged = {\n ...localItem,\n ...remote,\n _localId: localItem._localId,\n };\n const idx = next.findIndex((i) => i._localId === localItem._localId);\n if (idx >= 0) next[idx] = merged;\n } else {\n next.push({\n ...remote,\n _localId: nextLocalId(),\n });\n }\n }\n\n return {\n [stateKey]: next,\n syncState: {\n ...(state.syncState || {}),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n\n lastId = batch[batch.length - 1].id;\n }\n\n logger.info(`[zync] firstLoad:done stateKey=${stateKey}`);\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] firstLoad:error stateKey=${stateKey}`, err);\n }\n }\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n firstLoadDone: true,\n error: syncError,\n },\n }));\n }\n\n // Never call inside Zustand set() due to itself calling set(), so may cause lost state changes\n function queueToSync(action: any, stateKey: string, ...localIds: string[]) {\n set((state: any) => {\n const pendingChanges: any[] = state.syncState.pendingChanges || [];\n\n for (const localId of localIds) {\n const item = state[stateKey].find((i: any) => i._localId === localId);\n if (!item) {\n logger.error(`[zync] queueToSync:no-local-item localId=${localId}`);\n continue;\n }\n\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n if (queueItem) {\n queueItem.version += 1;\n\n if (queueItem.action === SyncAction.CreateOrUpdate && action === SyncAction.Remove && item.id) {\n queueItem.action = SyncAction.Remove;\n queueItem.id = item.id;\n logger.debug(`[zync] queueToSync:changed-to-remove action=${action} localId=${localId} v=${queueItem.version}`);\n } else {\n logger.debug(`[zync] queueToSync:re-queued action=${action} localId=${localId} v=${queueItem.version}`);\n }\n } else {\n pendingChanges.push({ action, stateKey, localId, id: item.id, version: 1 });\n logger.debug(`[zync] queueToSync:added action=${action} localId=${localId}`);\n }\n }\n\n return {\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n },\n };\n });\n syncOnce();\n }\n\n function setAndSync(partial: any) {\n if (typeof partial === 'function') {\n set((state: any) => ({ ...partial(state) }));\n } else {\n set(partial);\n }\n syncOnce();\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n enabled,\n },\n }));\n\n enableSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function enableSyncTimer(enabled: boolean) {\n clearInterval(syncIntervalId);\n syncIntervalId = undefined;\n if (enabled) {\n syncIntervalId = setInterval(syncOnce, syncInterval);\n syncOnce();\n }\n }\n\n function addVisibilityChangeListener(add: boolean) {\n if (add) {\n document.addEventListener('visibilitychange', onVisibilityChange);\n } else {\n document.removeEventListener('visibilitychange', onVisibilityChange);\n }\n }\n\n function onVisibilityChange() {\n if (document.visibilityState === 'visible') {\n logger.debug('[zync] sync:start-in-foreground');\n enableSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n enableSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad,\n };\n\n const userState = stateCreator(setAndSync, get, queueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n enabled: false,\n firstLoadDone: false,\n pendingChanges: [],\n lastPulled: {},\n },\n } as TStore & SyncState;\n };\n\n return persist(creator, wrappedPersistOptions);\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\nexport interface Logger {\n debug: (...args: any[]) => void;\n info: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n error: (...args: any[]) => void;\n}\n\nexport function newLogger(base: Logger, min: LogLevel): Logger {\n const order: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n none: 100,\n };\n const threshold = order[min];\n const enabled = (lvl: LogLevel) => order[lvl] >= threshold;\n return {\n debug: (...a: any[]) => enabled('debug') && base.debug?.(...a),\n info: (...a: any[]) => enabled('info') && base.info?.(...a),\n warn: (...a: any[]) => enabled('warn') && base.warn?.(...a),\n error: (...a: any[]) => enabled('error') && base.error?.(...a),\n };\n}\n","import { SyncAction } from './index';\nimport type { ApiFunctions, PendingChange } from './types';\n\nexport function nextLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.CreateOrUpdate:\n return 1;\n case SyncAction.Remove:\n return 2;\n }\n}\n\nexport function omitSyncFields(item: any, fields: readonly string[]) {\n const result = { ...item };\n for (const k of fields) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const q: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = q.find((p) => p.localId === localId && p.stateKey === stateKey);\n return curChange?.version === version;\n}\n\nexport function removeFromPendingChanges(set: any, localId: string, stateKey: string) {\n set((s: any) => {\n const queue: PendingChange[] = (s.syncState.pendingChanges || []).filter((p: PendingChange) => !(p.localId === localId && p.stateKey === stateKey));\n return {\n syncState: {\n ...(s.syncState || {}),\n pendingChanges: queue,\n },\n };\n });\n}\n\nexport function findApi(stateKey: string, syncApi: Record<string, ApiFunctions>) {\n const api = syncApi[stateKey];\n if (!api || !api.add || !api.update || !api.remove || !api.list || !api.firstLoad) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n return api;\n}\n","import type { ApiFunctions, PendingChange, SyncedRecord } from './types';\nimport { SyncAction } from './index';\nimport { nextLocalId } from './helpers';\n\nexport async function pull(set: any, get: any, stateKey: string, api: ApiFunctions, logger: any) {\n const lastPulled: Record<string, string> = get().syncState.lastPulled || {};\n const lastPulledAt = new Date(lastPulled[stateKey] || new Date(0));\n\n logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastPulledAt.toISOString()}`);\n\n const serverData = (await api.list(lastPulledAt)) as SyncedRecord[];\n if (!serverData?.length) return;\n\n let newest = lastPulledAt;\n set((state: any) => {\n const pendingChanges: PendingChange[] = state.syncState.pendingChanges || [];\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items by pulling them again\n const pendingRemovalById = new Set(pendingChanges.filter((p) => p.stateKey === stateKey && p.action === SyncAction.Remove).map((p) => p.id));\n\n for (const remote of serverData) {\n const remoteUpdated = new Date(remote.updated_at);\n if (remoteUpdated > newest) newest = remoteUpdated;\n\n // If a Remove is pending for this localId, skip merging/adding to avoid flicker\n if (pendingRemovalById.has(remote.id)) {\n logger.debug(`[zync] pull:skip-pending-remove stateKey=${stateKey} id=${remote.id}`);\n continue;\n }\n\n const localItem = localById.get(remote.id);\n if (remote.deleted) {\n if (localItem) {\n nextItems = nextItems.filter((i: any) => i.id !== remote.id);\n logger.debug(`[zync] pull:remove stateKey=${stateKey} id=${remote.id}`);\n }\n continue;\n }\n\n delete remote.deleted;\n\n const pending = localItem && pendingChanges.some((p: any) => p.stateKey === stateKey && p.localId === localItem._localId);\n if (localItem && !pending) {\n const merged = {\n ...localItem,\n ...remote,\n _localId: localItem._localId,\n };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n logger.debug(`[zync] pull:merge stateKey=${stateKey} id=${remote.id}`);\n } else if (!localItem) {\n // Add remote item (no local or pending collisions)\n nextItems = [...nextItems, { ...remote, _localId: nextLocalId() }];\n logger.debug(`[zync] pull:add stateKey=${stateKey} id=${remote.id}`);\n }\n }\n\n return {\n [stateKey]: nextItems,\n syncState: {\n ...(state.syncState || {}),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n}\n","import { removeFromPendingChanges, omitSyncFields, samePendingVersion } from './helpers';\nimport { SyncAction } from './index';\nimport type { Logger } from './logger';\nimport type { AfterRemoteAddCallback, ApiFunctions, MissingRemoteRecordStrategy, MissingRemoteRecordDuringUpdateCallback, PendingChange } from './types';\n\nconst SYNC_FIELDS = ['id', '_localId', 'updated_at', 'deleted'] as const;\n\nexport async function pushOne(\n set: any,\n get: any,\n change: PendingChange,\n api: ApiFunctions,\n logger: Logger,\n queueToSync: any,\n missingStrategy: MissingRemoteRecordStrategy,\n onMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback,\n onAfterRemoteAdd?: AfterRemoteAddCallback,\n) {\n logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);\n\n const { action, stateKey, localId, id, version } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id ${stateKey} ${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success ${stateKey} ${localId} ${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.CreateOrUpdate: {\n const state = get();\n const items: any[] = state[stateKey] || [];\n const item = items.find((i) => i._localId === localId);\n if (!item) {\n logger.warn(`[zync] push:create-or-update:no-local-item`, {\n stateKey,\n localId,\n });\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n const omittedItem = omitSyncFields(item, SYNC_FIELDS);\n if (item.id) {\n // Update\n const changed = await api.update(item.id, omittedItem);\n if (changed) {\n logger.debug('[zync] push:update:success', {\n stateKey,\n localId,\n id: item.id,\n });\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n return;\n } else {\n logger.warn('[zync] push:update:missing-remote', {\n stateKey,\n localId,\n id: item.id,\n });\n\n switch (missingStrategy) {\n case 'delete-local-record':\n set((s: any) => ({\n [stateKey]: (s[stateKey] || []).filter((i: any) => i._localId !== localId),\n }));\n break;\n\n case 'insert-remote-record': {\n omittedItem._localId = crypto.randomUUID();\n omittedItem.updated_at = new Date().toISOString();\n\n // replace old with new copy without id so it becomes a Create\n set((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? omittedItem : i)),\n }));\n\n queueToSync(SyncAction.CreateOrUpdate, stateKey, omittedItem._localId);\n break;\n }\n }\n removeFromPendingChanges(set, localId, stateKey);\n // Call hook so userland can alert the user etc.\n onMissingRemoteRecordDuringUpdate?.(missingStrategy, item, omittedItem._localId);\n }\n return;\n }\n\n // Create\n const result = await api.add(omittedItem);\n if (result) {\n logger.debug('[zync] push:create:success', {\n stateKey,\n localId,\n id: result.id,\n });\n\n // Merge server-assigned fields (id, updated_at, etc) directly into local entity\n set((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? { ...i, ...result } : i)),\n }));\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, queueToSync, stateKey, {\n ...item,\n ...result,\n });\n } else {\n logger.warn('[zync] push:create:no-result', {\n stateKey,\n localId,\n });\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDBStorage(options: { dbName: string; storeName: string }) {\n const dbName = options.dbName;\n const storeName = options.storeName;\n\n // dbPromise is created lazily by initDB() to avoid pulling `idb` into bundles\n let dbPromise: Promise<IDBPDatabase<any>> | null = null;\n\n async function initDB(): Promise<IDBPDatabase<any>> {\n if (dbPromise) return dbPromise;\n try {\n const idb = await import(/* webpackChunkName: \"idb\" */ 'idb');\n dbPromise = idb.openDB(dbName, 1, {\n upgrade(db: IDBPDatabase<any>) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n return dbPromise;\n } catch (_e) {\n throw new Error('Missing optional dependency \"idb\". Install it to use IndexedDB storage: npm install idb');\n }\n }\n\n async function ensureStore(): Promise<void> {\n const db = await initDB();\n if (db.objectStoreNames.contains(storeName)) return;\n const nextVersion = (db.version || 0) + 1;\n try {\n db.close();\n } catch (_e) {\n // ignore\n }\n const idb = await import(/* webpackChunkName: \"idb\" */ 'idb');\n dbPromise = idb.openDB(dbName, nextVersion, {\n upgrade(upg: IDBPDatabase<any>) {\n if (!upg.objectStoreNames.contains(storeName)) upg.createObjectStore(storeName);\n },\n });\n await dbPromise;\n }\n\n async function withRetry<T>(fn: (db: IDBPDatabase<any>) => Promise<T>): Promise<T> {\n try {\n const db = await initDB();\n return await fn(db);\n } catch (err: any) {\n const msg = String(err && err.message ? err.message : err);\n if (err && (err.name === 'NotFoundError' || /objectStore/i.test(msg))) {\n await ensureStore();\n const db2 = await initDB();\n return await fn(db2);\n }\n throw err;\n }\n }\n\n return {\n getItem: async (name: string): Promise<string | null> => {\n return withRetry(async (db) => {\n let v = await db.get(storeName, name);\n v = v ?? null; // Zustand expects null for missing keys\n return v;\n });\n },\n setItem: async (name: string, value: string): Promise<void> => {\n return withRetry(async (db) => {\n await db.put(storeName, value, name);\n });\n },\n removeItem: async (name: string): Promise<void> => {\n return withRetry(async (db) => {\n await db.delete(storeName, name);\n });\n },\n };\n}\n"],"mappings":";AAAA,SAAS,cAAiC;AAC1C,SAAS,eAAe;;;ACQjB,SAAS,UAAU,MAAc,KAAuB;AAC3D,QAAM,QAAkC;AAAA,IACpC,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACV;AACA,QAAM,YAAY,MAAM,GAAG;AAC3B,QAAM,UAAU,CAAC,QAAkB,MAAM,GAAG,KAAK;AACjD,SAAO;AAAA,IACH,OAAO,IAAI,MAAa,QAAQ,OAAO,KAAK,KAAK,QAAQ,GAAG,CAAC;AAAA,IAC7D,MAAM,IAAI,MAAa,QAAQ,MAAM,KAAK,KAAK,OAAO,GAAG,CAAC;AAAA,IAC1D,MAAM,IAAI,MAAa,QAAQ,MAAM,KAAK,KAAK,OAAO,GAAG,CAAC;AAAA,IAC1D,OAAO,IAAI,MAAa,QAAQ,OAAO,KAAK,KAAK,QAAQ,GAAG,CAAC;AAAA,EACjE;AACJ;;;ACtBO,SAAS,cAAsB;AAClC,SAAO,OAAO,WAAW;AAC7B;AAEO,SAAS,SAAS,GAAuB;AAC5C,UAAQ,GAAG;AAAA,IACP;AACI,aAAO;AAAA,IACX;AACI,aAAO;AAAA,EACf;AACJ;AAEO,SAAS,eAAe,MAAW,QAA2B;AACjE,QAAM,SAAS,EAAE,GAAG,KAAK;AACzB,aAAW,KAAK,OAAQ,QAAO,OAAO,CAAC;AACvC,SAAO;AACX;AAEO,SAAS,mBAAmB,KAAU,UAAkB,SAAiB,SAA0B;AACtG,QAAM,IAAqB,IAAI,EAAE,UAAU,kBAAkB,CAAC;AAC9D,QAAM,YAAY,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,aAAa,QAAQ;AAChF,SAAO,WAAW,YAAY;AAClC;AAEO,SAAS,yBAAyB,KAAU,SAAiB,UAAkB;AAClF,MAAI,CAAC,MAAW;AACZ,UAAM,SAA0B,EAAE,UAAU,kBAAkB,CAAC,GAAG,OAAO,CAAC,MAAqB,EAAE,EAAE,YAAY,WAAW,EAAE,aAAa,SAAS;AAClJ,WAAO;AAAA,MACH,WAAW;AAAA,QACP,GAAI,EAAE,aAAa,CAAC;AAAA,QACpB,gBAAgB;AAAA,MACpB;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;AAEO,SAAS,QAAQ,UAAkB,SAAuC;AAC7E,QAAM,MAAM,QAAQ,QAAQ;AAC5B,MAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,QAAQ,CAAC,IAAI,WAAW;AAC/E,UAAM,IAAI,MAAM,0CAA0C,QAAQ,GAAG;AAAA,EACzE;AACA,SAAO;AACX;;;AC1CA,eAAsB,KAAK,KAAU,KAAU,UAAkB,KAAmB,QAAa;AAC7F,QAAM,aAAqC,IAAI,EAAE,UAAU,cAAc,CAAC;AAC1E,QAAM,eAAe,IAAI,KAAK,WAAW,QAAQ,KAAK,oBAAI,KAAK,CAAC,CAAC;AAEjE,SAAO,MAAM,8BAA8B,QAAQ,UAAU,aAAa,YAAY,CAAC,EAAE;AAEzF,QAAM,aAAc,MAAM,IAAI,KAAK,YAAY;AAC/C,MAAI,CAAC,YAAY,OAAQ;AAEzB,MAAI,SAAS;AACb,MAAI,CAAC,UAAe;AAChB,UAAM,iBAAkC,MAAM,UAAU,kBAAkB,CAAC;AAC3E,UAAM,aAAoB,MAAM,QAAQ,KAAK,CAAC;AAC9C,QAAI,YAAY,CAAC,GAAG,UAAU;AAC9B,UAAM,YAAY,IAAI,IAAc,WAAW,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAExF,UAAM,qBAAqB,IAAI,IAAI,eAAe,OAAO,CAAC,MAAM,EAAE,aAAa,YAAY,EAAE,gCAA4B,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAE3I,eAAW,UAAU,YAAY;AAC7B,YAAM,gBAAgB,IAAI,KAAK,OAAO,UAAU;AAChD,UAAI,gBAAgB,OAAQ,UAAS;AAGrC,UAAI,mBAAmB,IAAI,OAAO,EAAE,GAAG;AACnC,eAAO,MAAM,4CAA4C,QAAQ,OAAO,OAAO,EAAE,EAAE;AACnF;AAAA,MACJ;AAEA,YAAM,YAAY,UAAU,IAAI,OAAO,EAAE;AACzC,UAAI,OAAO,SAAS;AAChB,YAAI,WAAW;AACX,sBAAY,UAAU,OAAO,CAAC,MAAW,EAAE,OAAO,OAAO,EAAE;AAC3D,iBAAO,MAAM,+BAA+B,QAAQ,OAAO,OAAO,EAAE,EAAE;AAAA,QAC1E;AACA;AAAA,MACJ;AAEA,aAAO,OAAO;AAEd,YAAM,UAAU,aAAa,eAAe,KAAK,CAAC,MAAW,EAAE,aAAa,YAAY,EAAE,YAAY,UAAU,QAAQ;AACxH,UAAI,aAAa,CAAC,SAAS;AACvB,cAAM,SAAS;AAAA,UACX,GAAG;AAAA,UACH,GAAG;AAAA,UACH,UAAU,UAAU;AAAA,QACxB;AACA,oBAAY,UAAU,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,WAAW,SAAS,CAAE;AACtF,eAAO,MAAM,8BAA8B,QAAQ,OAAO,OAAO,EAAE,EAAE;AAAA,MACzE,WAAW,CAAC,WAAW;AAEnB,oBAAY,CAAC,GAAG,WAAW,EAAE,GAAG,QAAQ,UAAU,YAAY,EAAE,CAAC;AACjE,eAAO,MAAM,4BAA4B,QAAQ,OAAO,OAAO,EAAE,EAAE;AAAA,MACvE;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,CAAC,QAAQ,GAAG;AAAA,MACZ,WAAW;AAAA,QACP,GAAI,MAAM,aAAa,CAAC;AAAA,QACxB,YAAY;AAAA,UACR,GAAI,MAAM,UAAU,cAAc,CAAC;AAAA,UACnC,CAAC,QAAQ,GAAG,OAAO,YAAY;AAAA,QACnC;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;;;ACjEA,IAAM,cAAc,CAAC,MAAM,YAAY,cAAc,SAAS;AAE9D,eAAsB,QAClB,KACA,KACA,QACA,KACA,QACA,aACA,iBACA,mCACA,kBACF;AACE,SAAO,MAAM,8BAA8B,OAAO,MAAM,aAAa,OAAO,QAAQ,YAAY,OAAO,OAAO,EAAE;AAEhH,QAAM,EAAE,QAAQ,UAAU,SAAS,IAAI,QAAQ,IAAI;AAEnD,UAAQ,QAAQ;AAAA,IACZ;AACI,UAAI,CAAC,IAAI;AACL,eAAO,KAAK,4BAA4B,QAAQ,IAAI,OAAO,EAAE;AAC7D,iCAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,MACJ;AAEA,YAAM,IAAI,OAAO,EAAE;AACnB,aAAO,MAAM,8BAA8B,QAAQ,IAAI,OAAO,IAAI,EAAE,EAAE;AACtE,+BAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,IAEJ,8CAAgC;AAC5B,YAAM,QAAQ,IAAI;AAClB,YAAM,QAAe,MAAM,QAAQ,KAAK,CAAC;AACzC,YAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO;AACrD,UAAI,CAAC,MAAM;AACP,eAAO,KAAK,8CAA8C;AAAA,UACtD;AAAA,UACA;AAAA,QACJ,CAAC;AACD,iCAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,MACJ;AAEA,YAAM,cAAc,eAAe,MAAM,WAAW;AACpD,UAAI,KAAK,IAAI;AAET,cAAM,UAAU,MAAM,IAAI,OAAO,KAAK,IAAI,WAAW;AACrD,YAAI,SAAS;AACT,iBAAO,MAAM,8BAA8B;AAAA,YACvC;AAAA,YACA;AAAA,YACA,IAAI,KAAK;AAAA,UACb,CAAC;AACD,cAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,qCAAyB,KAAK,SAAS,QAAQ;AAAA,UACnD;AACA;AAAA,QACJ,OAAO;AACH,iBAAO,KAAK,qCAAqC;AAAA,YAC7C;AAAA,YACA;AAAA,YACA,IAAI,KAAK;AAAA,UACb,CAAC;AAED,kBAAQ,iBAAiB;AAAA,YACrB,KAAK;AACD,kBAAI,CAAC,OAAY;AAAA,gBACb,CAAC,QAAQ,IAAI,EAAE,QAAQ,KAAK,CAAC,GAAG,OAAO,CAAC,MAAW,EAAE,aAAa,OAAO;AAAA,cAC7E,EAAE;AACF;AAAA,YAEJ,KAAK,wBAAwB;AACzB,0BAAY,WAAW,OAAO,WAAW;AACzC,0BAAY,cAAa,oBAAI,KAAK,GAAE,YAAY;AAGhD,kBAAI,CAAC,OAAY;AAAA,gBACb,CAAC,QAAQ,IAAI,EAAE,QAAQ,KAAK,CAAC,GAAG,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,cAAc,CAAE;AAAA,cAC9F,EAAE;AAEF,mEAAuC,UAAU,YAAY,QAAQ;AACrE;AAAA,YACJ;AAAA,UACJ;AACA,mCAAyB,KAAK,SAAS,QAAQ;AAE/C,8CAAoC,iBAAiB,MAAM,YAAY,QAAQ;AAAA,QACnF;AACA;AAAA,MACJ;AAGA,YAAM,SAAS,MAAM,IAAI,IAAI,WAAW;AACxC,UAAI,QAAQ;AACR,eAAO,MAAM,8BAA8B;AAAA,UACvC;AAAA,UACA;AAAA,UACA,IAAI,OAAO;AAAA,QACf,CAAC;AAGD,YAAI,CAAC,OAAY;AAAA,UACb,CAAC,QAAQ,IAAI,EAAE,QAAQ,KAAK,CAAC,GAAG,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,EAAE,GAAG,GAAG,GAAG,OAAO,IAAI,CAAE;AAAA,QACtG,EAAE;AACF,YAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,mCAAyB,KAAK,SAAS,QAAQ;AAAA,QACnD;AAEA,2BAAmB,KAAK,KAAK,aAAa,UAAU;AAAA,UAChD,GAAG;AAAA,UACH,GAAG;AAAA,QACP,CAAC;AAAA,MACL,OAAO;AACH,eAAO,KAAK,gCAAgC;AAAA,UACxC;AAAA,UACA;AAAA,QACJ,CAAC;AACD,YAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,mCAAyB,KAAK,SAAS,QAAQ;AAAA,QACnD;AAAA,MACJ;AACA;AAAA,IACJ;AAAA,EACJ;AACJ;;;AC/HO,SAAS,uBAAuB,SAAgD;AACnF,QAAM,SAAS,QAAQ;AACvB,QAAM,YAAY,QAAQ;AAG1B,MAAI,YAA+C;AAEnD,iBAAe,SAAqC;AAChD,QAAI,UAAW,QAAO;AACtB,QAAI;AACA,YAAM,MAAM,MAAM;AAAA;AAAA,QAAqC;AAAA,MAAK;AAC5D,kBAAY,IAAI,OAAO,QAAQ,GAAG;AAAA,QAC9B,QAAQ,IAAuB;AAC3B,cAAI,CAAC,GAAG,iBAAiB,SAAS,SAAS,GAAG;AAC1C,eAAG,kBAAkB,SAAS;AAAA,UAClC;AAAA,QACJ;AAAA,MACJ,CAAC;AACD,aAAO;AAAA,IACX,SAAS,IAAI;AACT,YAAM,IAAI,MAAM,yFAAyF;AAAA,IAC7G;AAAA,EACJ;AAEA,iBAAe,cAA6B;AACxC,UAAM,KAAK,MAAM,OAAO;AACxB,QAAI,GAAG,iBAAiB,SAAS,SAAS,EAAG;AAC7C,UAAM,eAAe,GAAG,WAAW,KAAK;AACxC,QAAI;AACA,SAAG,MAAM;AAAA,IACb,SAAS,IAAI;AAAA,IAEb;AACA,UAAM,MAAM,MAAM;AAAA;AAAA,MAAqC;AAAA,IAAK;AAC5D,gBAAY,IAAI,OAAO,QAAQ,aAAa;AAAA,MACxC,QAAQ,KAAwB;AAC5B,YAAI,CAAC,IAAI,iBAAiB,SAAS,SAAS,EAAG,KAAI,kBAAkB,SAAS;AAAA,MAClF;AAAA,IACJ,CAAC;AACD,UAAM;AAAA,EACV;AAEA,iBAAe,UAAa,IAAuD;AAC/E,QAAI;AACA,YAAM,KAAK,MAAM,OAAO;AACxB,aAAO,MAAM,GAAG,EAAE;AAAA,IACtB,SAAS,KAAU;AACf,YAAM,MAAM,OAAO,OAAO,IAAI,UAAU,IAAI,UAAU,GAAG;AACzD,UAAI,QAAQ,IAAI,SAAS,mBAAmB,eAAe,KAAK,GAAG,IAAI;AACnE,cAAM,YAAY;AAClB,cAAM,MAAM,MAAM,OAAO;AACzB,eAAO,MAAM,GAAG,GAAG;AAAA,MACvB;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAEA,SAAO;AAAA,IACH,SAAS,OAAO,SAAyC;AACrD,aAAO,UAAU,OAAO,OAAO;AAC3B,YAAI,IAAI,MAAM,GAAG,IAAI,WAAW,IAAI;AACpC,YAAI,KAAK;AACT,eAAO;AAAA,MACX,CAAC;AAAA,IACL;AAAA,IACA,SAAS,OAAO,MAAc,UAAiC;AAC3D,aAAO,UAAU,OAAO,OAAO;AAC3B,cAAM,GAAG,IAAI,WAAW,OAAO,IAAI;AAAA,MACvC,CAAC;AAAA,IACL;AAAA,IACA,YAAY,OAAO,SAAgC;AAC/C,aAAO,UAAU,OAAO,OAAO;AAC3B,cAAM,GAAG,OAAO,WAAW,IAAI;AAAA,MACnC,CAAC;AAAA,IACL;AAAA,EACJ;AACJ;;;ALlEO,IAAK,aAAL,kBAAKA,gBAAL;AACH,EAAAA,YAAA,oBAAiB;AACjB,EAAAA,YAAA,YAAS;AAFD,SAAAA;AAAA,GAAA;AAKZ,IAAM,+BAA+B;AACrC,IAAM,iBAAyB;AAC/B,IAAM,wBAAkC;AACxC,IAAM,yCAAsE;AAErE,SAAS,eACZ,cACA,gBACA,SACA,cAA2B,CAAC,GACK;AACjC,QAAM,QAAQ,OAAO,gBAAgB,cAAc,gBAAgB,SAAS,WAAW,CAAC;AAExF,SAAO,IAAI,QAAkC,CAAC,YAAY;AACtD,UAAM,QAAQ,kBAAkB,CAAC,WAAW;AACxC,cAAQ,KAAK;AAAA,IACjB,CAAC;AAAA,EACL,CAAC;AACL;AAEO,SAAS,gBACZ,cACA,gBACA,SACA,cAA2B,CAAC,GAC9B;AACE,QAAM,eAAe,YAAY,gBAAgB;AACjD,QAAM,kBAAkB,YAAY,2CAA2C;AAC/E,QAAM,SAAS,UAAU,YAAY,UAAU,gBAAgB,YAAY,eAAe,qBAAqB;AAE/G,QAAM,kBAAkB,gBAAgB;AACxC,QAAM,iBAAiB,gBAAgB;AAEvC,QAAM,wBAAwB;AAAA,IAC1B,GAAG;AAAA,IACH,oBAAoB,MAAM;AACtB,aAAO,MAAM,0BAA0B;AAEvC,aAAO,CAAC,OAAY,UAAe;AAC/B,YAAI,OAAO;AACP,iBAAO,MAAM,6BAA6B,KAAK;AAAA,QACnD,OAAO;AACH,4BAAkB,OAAO,KAAK;AAC9B,iBAAO,MAAM,+BAA+B,KAAK;AAAA,QACrD;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,YAAY,CAAC,MAAW;AAGpB,YAAM,OAAO,iBAAiB,eAAe,CAAC,IAAI;AAClD,YAAM,EAAE,WAAW,GAAG,KAAK,IAAI,QAAQ,CAAC;AACxC,aAAO;AAAA,QACH,GAAG;AAAA,QACH,WAAW;AAAA,UACP,eAAe,UAAU;AAAA,UACzB,gBAAgB,UAAU;AAAA,UAC1B,YAAY,UAAU;AAAA,QAC1B;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,OAAO,CAAC,WAAgB,YAAiB;AAOrC,YAAM,QAAQ,EAAE,GAAG,SAAS,GAAG,UAAU;AAEzC,aAAO;AAAA,QACH,GAAG;AAAA,QACH,WAAW;AAAA,UACP,GAAG,MAAM;AAAA,UACT,QAAQ;AAAA;AAAA,QACZ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,UAAoD,CAAC,KAAU,KAAU,aAAkB;AAC7F,QAAI;AAEJ,mBAAe,WAAW;AACtB,YAAM,QAAmB,IAAI;AAC7B,UAAI,CAAC,MAAM,UAAU,WAAW,MAAM,UAAU,WAAW,OAAQ;AAEnE,UAAI,CAACC,YAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAIA,OAAM,aAAa,CAAC;AAAA,UACxB,QAAQ;AAAA,QACZ;AAAA,MACJ,EAAE;AAEF,UAAI;AAGJ,iBAAW,YAAY,OAAO,KAAK,OAAO,GAAG;AACzC,YAAI;AACA,gBAAM,MAAM,QAAQ,UAAU,OAAO;AACrC,gBAAM,KAAK,KAAK,KAAK,UAAU,KAAK,MAAM;AAAA,QAC9C,SAAS,KAAK;AACV,sBAAY,aAAc;AAC1B,iBAAO,MAAM,8BAA8B,QAAQ,IAAI,GAAG;AAAA,QAC9D;AAAA,MACJ;AAGA,YAAM,WAA4B,CAAC,GAAI,IAAI,EAAE,UAAU,kBAAkB,CAAC,CAAE;AAG5E,eAAS,KAAK,CAAC,GAAG,MAAM,SAAS,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,CAAC;AAE/D,iBAAW,UAAU,UAAU;AAC3B,YAAI;AACA,gBAAM,MAAM,QAAQ,OAAO,UAAU,OAAO;AAC5C,gBAAM;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ,YAAY;AAAA,UAChB;AAAA,QACJ,SAAS,KAAK;AACV,sBAAY,aAAc;AAC1B,iBAAO,MAAM,4BAA4B,MAAM,IAAI,GAAG;AAAA,QAC1D;AAAA,MACJ;AAEA,UAAI,CAACA,YAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAIA,OAAM,aAAa,CAAC;AAAA,UACxB,QAAQ;AAAA,UACR,OAAO;AAAA,QACX;AAAA,MACJ,EAAE;AAEF,UAAI,IAAI,EAAE,UAAU,eAAe,SAAS,KAAK,CAAC,WAAW;AAEzD,cAAM,SAAS;AAAA,MACnB;AAAA,IACJ;AAEA,mBAAe,iBAAiB;AAC5B,UAAI;AAEJ,iBAAW,YAAY,OAAO,KAAK,OAAO,GAAG;AACzC,YAAI;AACA,iBAAO,KAAK,mCAAmC,QAAQ,EAAE;AAEzD,gBAAM,MAAM,QAAQ,UAAU,OAAO;AACrC,cAAI;AAGJ,iBAAO,MAAM;AACT,kBAAM,QAAQ,MAAM,IAAI,UAAU,MAAM;AACxC,gBAAI,CAAC,OAAO,OAAQ;AAGpB,gBAAI,CAAC,UAAe;AAChB,oBAAM,QAAe,MAAM,QAAQ,KAAK,CAAC;AACzC,oBAAM,YAAY,IAAI,IAAc,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEnF,kBAAI,SAAS,IAAI,KAAK,MAAM,UAAU,WAAW,QAAQ,KAAK,CAAC;AAC/D,oBAAM,OAAO,CAAC,GAAG,KAAK;AACtB,yBAAW,UAAU,OAAO;AACxB,sBAAM,gBAAgB,IAAI,KAAK,OAAO,cAAc,CAAC;AACrD,oBAAI,gBAAgB,OAAQ,UAAS;AAErC,oBAAI,OAAO,QAAS;AAEpB,uBAAO,OAAO;AAEd,sBAAM,YAAY,OAAO,KAAK,UAAU,IAAI,OAAO,EAAE,IAAI;AACzD,oBAAI,WAAW;AACX,wBAAM,SAAS;AAAA,oBACX,GAAG;AAAA,oBACH,GAAG;AAAA,oBACH,UAAU,UAAU;AAAA,kBACxB;AACA,wBAAM,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,aAAa,UAAU,QAAQ;AACnE,sBAAI,OAAO,EAAG,MAAK,GAAG,IAAI;AAAA,gBAC9B,OAAO;AACH,uBAAK,KAAK;AAAA,oBACN,GAAG;AAAA,oBACH,UAAU,YAAY;AAAA,kBAC1B,CAAC;AAAA,gBACL;AAAA,cACJ;AAEA,qBAAO;AAAA,gBACH,CAAC,QAAQ,GAAG;AAAA,gBACZ,WAAW;AAAA,kBACP,GAAI,MAAM,aAAa,CAAC;AAAA,kBACxB,YAAY;AAAA,oBACR,GAAI,MAAM,UAAU,cAAc,CAAC;AAAA,oBACnC,CAAC,QAAQ,GAAG,OAAO,YAAY;AAAA,kBACnC;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ,CAAC;AAED,qBAAS,MAAM,MAAM,SAAS,CAAC,EAAE;AAAA,UACrC;AAEA,iBAAO,KAAK,kCAAkC,QAAQ,EAAE;AAAA,QAC5D,SAAS,KAAK;AACV,sBAAY,aAAc;AAC1B,iBAAO,MAAM,mCAAmC,QAAQ,IAAI,GAAG;AAAA,QACnE;AAAA,MACJ;AAEA,UAAI,CAAC,WAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB,eAAe;AAAA,UACf,OAAO;AAAA,QACX;AAAA,MACJ,EAAE;AAAA,IACN;AAGA,aAAS,YAAY,QAAa,aAAqB,UAAoB;AACvE,UAAI,CAAC,UAAe;AAChB,cAAM,iBAAwB,MAAM,UAAU,kBAAkB,CAAC;AAEjE,mBAAW,WAAW,UAAU;AAC5B,gBAAM,OAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,MAAW,EAAE,aAAa,OAAO;AACpE,cAAI,CAAC,MAAM;AACP,mBAAO,MAAM,4CAA4C,OAAO,EAAE;AAClE;AAAA,UACJ;AAEA,gBAAM,YAAY,eAAe,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,aAAa,QAAQ;AAC7F,cAAI,WAAW;AACX,sBAAU,WAAW;AAErB,gBAAI,UAAU,WAAW,2CAA6B,WAAW,yBAAqB,KAAK,IAAI;AAC3F,wBAAU,SAAS;AACnB,wBAAU,KAAK,KAAK;AACpB,qBAAO,MAAM,+CAA+C,MAAM,YAAY,OAAO,MAAM,UAAU,OAAO,EAAE;AAAA,YAClH,OAAO;AACH,qBAAO,MAAM,uCAAuC,MAAM,YAAY,OAAO,MAAM,UAAU,OAAO,EAAE;AAAA,YAC1G;AAAA,UACJ,OAAO;AACH,2BAAe,KAAK,EAAE,QAAQ,UAAU,SAAS,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;AAC1E,mBAAO,MAAM,mCAAmC,MAAM,YAAY,OAAO,EAAE;AAAA,UAC/E;AAAA,QACJ;AAEA,eAAO;AAAA,UACH,WAAW;AAAA,YACP,GAAI,MAAM,aAAa,CAAC;AAAA,YACxB;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,CAAC;AACD,eAAS;AAAA,IACb;AAEA,aAAS,WAAW,SAAc;AAC9B,UAAI,OAAO,YAAY,YAAY;AAC/B,YAAI,CAAC,WAAgB,EAAE,GAAG,QAAQ,KAAK,EAAE,EAAE;AAAA,MAC/C,OAAO;AACH,YAAI,OAAO;AAAA,MACf;AACA,eAAS;AAAA,IACb;AAEA,aAAS,OAAO,SAAkB;AAC9B,UAAI,CAAC,WAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB;AAAA,QACJ;AAAA,MACJ,EAAE;AAEF,sBAAgB,OAAO;AACvB,kCAA4B,OAAO;AAAA,IACvC;AAEA,aAAS,gBAAgB,SAAkB;AACvC,oBAAc,cAAc;AAC5B,uBAAiB;AACjB,UAAI,SAAS;AACT,yBAAiB,YAAY,UAAU,YAAY;AACnD,iBAAS;AAAA,MACb;AAAA,IACJ;AAEA,aAAS,4BAA4B,KAAc;AAC/C,UAAI,KAAK;AACL,iBAAS,iBAAiB,oBAAoB,kBAAkB;AAAA,MACpE,OAAO;AACH,iBAAS,oBAAoB,oBAAoB,kBAAkB;AAAA,MACvE;AAAA,IACJ;AAEA,aAAS,qBAAqB;AAC1B,UAAI,SAAS,oBAAoB,WAAW;AACxC,eAAO,MAAM,iCAAiC;AAC9C,wBAAgB,IAAI;AAAA,MACxB,OAAO;AACH,eAAO,MAAM,iCAAiC;AAC9C,wBAAgB,KAAK;AAAA,MACzB;AAAA,IACJ;AAGA,aAAS,OAAO;AAAA,MACZ;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,YAAY,aAAa,YAAY,KAAK,WAAW;AAE3D,WAAO;AAAA,MACH,GAAG;AAAA,MACH,WAAW;AAAA;AAAA,QAEP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,SAAS;AAAA,QACT,eAAe;AAAA,QACf,gBAAgB,CAAC;AAAA,QACjB,YAAY,CAAC;AAAA,MACjB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,QAAQ,SAAS,qBAAqB;AACjD;","names":["SyncAction","state"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/helpers.ts","../src/pull.ts","../src/push.ts","../src/indexedDBStorage.ts"],"sourcesContent":["import { create, type StateCreator } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport { newLogger, type Logger, type LogLevel } from './logger';\nimport { orderFor, findApi, nextLocalId, findChanges, type ChangeRecord } from './helpers';\nimport type {\n ApiFunctions,\n SyncOptions,\n SyncState,\n SyncedStateCreator,\n PendingChange,\n UseStoreWithSync,\n MissingRemoteRecordStrategy,\n ConflictResolutionStrategy,\n} from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\n\nexport { createIndexedDBStorage } from './indexedDBStorage';\nexport { nextLocalId } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n CreateOrUpdate = 'create-or-update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 5000;\nconst DEFAULT_LOGGER: Logger = console;\nconst DEFAULT_MIN_LOG_LEVEL: LogLevel = 'debug';\nconst DEFAULT_MISSING_REMOTE_RECORD_STRATEGY: MissingRemoteRecordStrategy = 'ignore';\nconst DEFAULT_CONFLICT_RESOLUTION_STRATEGY: ConflictResolutionStrategy = 'local-wins';\n\nexport function createWithSync<TStore extends object>(\n stateCreator: SyncedStateCreator<TStore>,\n persistOptions: any,\n syncApi: Record<string, ApiFunctions>,\n syncOptions: SyncOptions = {},\n): Promise<UseStoreWithSync<TStore>> {\n const store = create(persistWithSync(stateCreator, persistOptions, syncApi, syncOptions)) as UseStoreWithSync<TStore>;\n\n return new Promise<UseStoreWithSync<TStore>>((resolve) => {\n store.persist.onFinishHydration((_state) => {\n resolve(store);\n });\n });\n}\n\nexport function persistWithSync<TStore extends object>(\n stateCreator: SyncedStateCreator<TStore>,\n persistOptions: any,\n syncApi: Record<string, ApiFunctions>,\n syncOptions: SyncOptions = {},\n) {\n const syncInterval = syncOptions.syncInterval ?? DEFAULT_SYNC_INTERVAL_MILLIS;\n const missingStrategy = syncOptions.missingRemoteRecordDuringUpdateStrategy ?? DEFAULT_MISSING_REMOTE_RECORD_STRATEGY;\n const conflictResolutionStrategy = syncOptions.conflictResolutionStrategy ?? DEFAULT_CONFLICT_RESOLUTION_STRATEGY;\n const logger = newLogger(syncOptions.logger ?? DEFAULT_LOGGER, syncOptions.minLogLevel ?? DEFAULT_MIN_LOG_LEVEL);\n\n const baseOnRehydrate = persistOptions?.onRehydrateStorage;\n const basePartialize = persistOptions?.partialize;\n\n const wrappedPersistOptions = {\n ...persistOptions,\n onRehydrateStorage: () => {\n logger.debug('[zync] rehydration:start');\n\n return (state: any, error: any) => {\n if (error) {\n logger.error('[zync] rehydration:failed', error);\n } else {\n baseOnRehydrate?.(state, error);\n logger.debug('[zync] rehydration:complete', state);\n }\n };\n },\n partialize: (s: any) => {\n // Select state to be persisted\n\n const base = basePartialize ? basePartialize(s) : s;\n const { syncState, ...rest } = base || {};\n return {\n ...rest,\n syncState: {\n firstLoadDone: syncState.firstLoadDone,\n pendingChanges: syncState.pendingChanges,\n lastPulled: syncState.lastPulled,\n },\n };\n },\n merge: (persisted: any, current: any) => {\n // Here after hydration.\n // `persisted` is state from storage that's just loaded (possibly asynchronously e.g. IndexedDB)\n // `current` is what the user has defined (they may have added or removed state keys)\n // Zync is designed to not be used until hydration is complete, so we don't expect to have to\n // merge user mutated state (i.e. current) into persisted. So we do the Zustand recommended pattern of\n // shallow copy where persisted keys win:\n const state = { ...current, ...persisted };\n\n return {\n ...state,\n syncState: {\n ...state.syncState,\n status: 'idle', // this confirms 'hydrating' is done\n },\n };\n },\n };\n\n const creator: StateCreator<TStore & SyncState, [], []> = (set: any, get: any, storeApi: any) => {\n let syncIntervalId: any;\n\n async function syncOnce() {\n const state: SyncState = get();\n if (!state.syncState.enabled || state.syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let syncError: Error | undefined;\n\n // 1) PULL for each stateKey\n for (const stateKey of Object.keys(syncApi)) {\n try {\n const api = findApi(stateKey, syncApi);\n await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] pull:error stateKey=${stateKey}`, err);\n }\n }\n\n // 2) PUSH queued changes\n const changesSnapshot: PendingChange[] = [...(get().syncState.pendingChanges || [])];\n\n // Deterministic ordering: Create -> Update -> Remove so dependencies (e.g. id assignment) happen first\n changesSnapshot.sort((a, b) => orderFor(a.action) - orderFor(b.action));\n\n for (const change of changesSnapshot) {\n try {\n const api = findApi(change.stateKey, syncApi);\n await pushOne(\n set,\n get,\n change,\n api,\n logger,\n setAndQueueToSync,\n missingStrategy,\n syncOptions.onMissingRemoteRecordDuringUpdate,\n syncOptions.onAfterRemoteAdd,\n );\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] push:error change=${change}`, err);\n }\n }\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'idle',\n error: syncError,\n },\n }));\n\n if (get().syncState.pendingChanges.length > 0 && !syncError) {\n // If there are pending changes and no sync error, we can sync again\n await syncOnce();\n }\n }\n\n async function startFirstLoad() {\n let syncError: Error | undefined;\n\n for (const stateKey of Object.keys(syncApi)) {\n try {\n logger.info(`[zync] firstLoad:start stateKey=${stateKey}`);\n\n const api = findApi(stateKey, syncApi);\n let lastId; // Start as undefined to allow the userland api code to set the initial value+type\n\n // Batch until empty\n while (true) {\n const batch = await api.firstLoad(lastId);\n if (!batch?.length) break;\n\n // Merge batch\n set((state: any) => {\n const local: any[] = state[stateKey] || [];\n const localById = new Map<any, any>(local.filter((l) => l.id).map((l) => [l.id, l]));\n\n let newest = new Date(state.syncState.lastPulled[stateKey] || 0);\n const next = [...local];\n for (const remote of batch) {\n const remoteUpdated = new Date(remote.updated_at || 0);\n if (remoteUpdated > newest) newest = remoteUpdated;\n\n if (remote.deleted) continue;\n\n delete remote.deleted;\n\n const localItem = remote.id ? localById.get(remote.id) : undefined;\n if (localItem) {\n const merged = {\n ...localItem,\n ...remote,\n _localId: localItem._localId,\n };\n const idx = next.findIndex((i) => i._localId === localItem._localId);\n if (idx >= 0) next[idx] = merged;\n } else {\n next.push({\n ...remote,\n _localId: nextLocalId(),\n });\n }\n }\n\n return {\n [stateKey]: next,\n syncState: {\n ...(state.syncState || {}),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n\n lastId = batch[batch.length - 1].id;\n }\n\n logger.info(`[zync] firstLoad:done stateKey=${stateKey}`);\n } catch (err) {\n syncError = syncError ?? (err as Error);\n logger.error(`[zync] firstLoad:error stateKey=${stateKey}`, err);\n }\n }\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n firstLoadDone: true,\n error: syncError,\n },\n }));\n }\n\n function setAndSyncOnce(partial: any) {\n if (typeof partial === 'function') {\n set((state: any) => ({ ...partial(state) }));\n } else {\n set(partial);\n }\n syncOnce();\n }\n\n function setAndQueueToSync(partial: any) {\n if (typeof partial === 'function') {\n set((state: any) => newSyncState(state, partial(state)));\n } else {\n set((state: any) => newSyncState(state, partial));\n }\n syncOnce();\n }\n\n function newSyncState(state: any, partial: any) {\n const pendingChanges: PendingChange[] = state.syncState.pendingChanges || [];\n\n Object.keys(partial).map((stateKey) => {\n const current = state[stateKey];\n const updated = partial[stateKey];\n const changes = findChanges(current, updated); // find additions, deletions & updates\n addToPendingChanges(pendingChanges, stateKey, changes);\n });\n\n return {\n ...partial,\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n },\n };\n }\n\n function addToPendingChanges(pendingChanges: PendingChange[], stateKey: string, changes: Map<string, ChangeRecord>) {\n for (const [localId, change] of changes) {\n const action = change.updatedItem === null ? SyncAction.Remove : SyncAction.CreateOrUpdate;\n\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n if (queueItem) {\n queueItem.version += 1;\n\n if (queueItem.action === SyncAction.CreateOrUpdate && action === SyncAction.Remove && change.currentItem.id) {\n queueItem.action = SyncAction.Remove;\n queueItem.id = change.currentItem.id;\n logger.debug(`[zync] addToPendingChanges:changed-to-remove action=${action} localId=${localId} v=${queueItem.version}`);\n } else {\n logger.debug(`[zync] addToPendingChanges:re-queued action=${action} localId=${localId} v=${queueItem.version}`);\n }\n } else {\n pendingChanges.push({ action, stateKey, localId, id: change.currentItem?.id, version: 1, changes: change.changes });\n logger.debug(`[zync] addToPendingChanges:added action=${action} localId=${localId}`);\n }\n }\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n enabled,\n },\n }));\n\n enableSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function enableSyncTimer(enabled: boolean) {\n clearInterval(syncIntervalId);\n syncIntervalId = undefined;\n if (enabled) {\n syncIntervalId = setInterval(syncOnce, syncInterval);\n syncOnce();\n }\n }\n\n function addVisibilityChangeListener(add: boolean) {\n if (add) {\n document.addEventListener('visibilitychange', onVisibilityChange);\n } else {\n document.removeEventListener('visibilitychange', onVisibilityChange);\n }\n }\n\n function onVisibilityChange() {\n if (document.visibilityState === 'visible') {\n logger.debug('[zync] sync:start-in-foreground');\n enableSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n enableSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad,\n };\n\n const userState = stateCreator(setAndSyncOnce, get, setAndQueueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n enabled: false,\n firstLoadDone: false,\n pendingChanges: [],\n lastPulled: {},\n },\n } as TStore & SyncState;\n };\n\n return persist(creator, wrappedPersistOptions);\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\nexport interface Logger {\n debug: (...args: any[]) => void;\n info: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n error: (...args: any[]) => void;\n}\n\nexport function newLogger(base: Logger, min: LogLevel): Logger {\n const order: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n none: 100,\n };\n const threshold = order[min];\n const enabled = (lvl: LogLevel) => order[lvl] >= threshold;\n return {\n debug: (...a: any[]) => enabled('debug') && base.debug?.(...a),\n info: (...a: any[]) => enabled('info') && base.info?.(...a),\n warn: (...a: any[]) => enabled('warn') && base.warn?.(...a),\n error: (...a: any[]) => enabled('error') && base.error?.(...a),\n };\n}\n","import { SyncAction } from './index';\nimport type { ApiFunctions, PendingChange } from './types';\n\nexport function nextLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.CreateOrUpdate:\n return 1;\n case SyncAction.Remove:\n return 2;\n }\n}\n\nexport function omitSyncFields(item: any, fields: readonly string[]) {\n const result = { ...item };\n for (const k of fields) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const q: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = q.find((p) => p.localId === localId && p.stateKey === stateKey);\n return curChange?.version === version;\n}\n\nexport function removeFromPendingChanges(set: any, localId: string, stateKey: string) {\n set((s: any) => {\n const queue: PendingChange[] = (s.syncState.pendingChanges || []).filter((p: PendingChange) => !(p.localId === localId && p.stateKey === stateKey));\n return {\n syncState: {\n ...(s.syncState || {}),\n pendingChanges: queue,\n },\n };\n });\n}\n\nexport function findApi(stateKey: string, syncApi: Record<string, ApiFunctions>) {\n const api = syncApi[stateKey];\n if (!api || !api.add || !api.update || !api.remove || !api.list || !api.firstLoad) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n return api;\n}\n\nexport type ChangeRecord = {\n currentItem?: any;\n updatedItem?: any;\n changes: any;\n};\n\n/**\n * Compares the top-level keys of items in `current` and `updated` arrays (assumed to have `_localId`).\n * Returns a Map where the key is `_localId` and the value is an object with:\n * - `currentItem`: The item from `current` (or `null` for additions).\n * - `updatedItem`: The item from `updated` (or `null` for deletions).\n * - `changes`: An object with differing top-level keys and their values (or the full item for additions, or `null` for deletions).\n */\nexport function findChanges(current: any[], updated: any[]): Map<string, ChangeRecord> {\n const currentMap = new Map<string, any>();\n for (const item of current) {\n if (item && item._localId) {\n currentMap.set(item._localId, item);\n }\n }\n\n const changesMap = new Map<string, ChangeRecord>();\n\n // Check for changes and additions\n for (const item of updated) {\n if (item && item._localId) {\n const curr = currentMap.get(item._localId);\n if (curr) {\n const diff: any = {};\n for (const key in curr) {\n if (key !== '_localId' && curr[key] !== item[key]) {\n diff[key] = item[key];\n }\n }\n if (Object.keys(diff).length > 0) {\n changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff });\n }\n } else {\n // Addition\n changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item });\n }\n }\n }\n\n // Check for deletions\n for (const [localId, curr] of currentMap) {\n if (!updated.some((u) => u && u._localId === localId)) {\n changesMap.set(localId, { currentItem: curr, updatedItem: null, changes: null });\n }\n }\n\n return changesMap;\n}\n","import type { ApiFunctions, ConflictResolutionStrategy, PendingChange, SyncedRecord } from './types';\nimport { SyncAction } from './index';\nimport { nextLocalId } from './helpers';\nimport type { Logger } from './logger';\n\nexport async function pull(set: any, get: any, stateKey: string, api: ApiFunctions, logger: Logger, conflictResolutionStrategy: ConflictResolutionStrategy) {\n const lastPulled: Record<string, string> = get().syncState.lastPulled || {};\n const lastPulledAt = new Date(lastPulled[stateKey] || new Date(0));\n\n logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastPulledAt.toISOString()}`);\n\n const serverData = (await api.list(lastPulledAt)) as SyncedRecord[];\n if (!serverData?.length) return;\n\n let newest = lastPulledAt;\n set((state: any) => {\n const pendingChanges: PendingChange[] = state.syncState.pendingChanges || [];\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items by pulling them again\n const pendingRemovalById = new Set(pendingChanges.filter((p) => p.stateKey === stateKey && p.action === SyncAction.Remove).map((p) => p.id));\n\n for (const remote of serverData) {\n const remoteUpdated = new Date(remote.updated_at);\n if (remoteUpdated > newest) newest = remoteUpdated;\n\n // If a Remove is pending for this localId, skip merging/adding to avoid briefly resurrecting the item\n if (pendingRemovalById.has(remote.id)) {\n logger.debug(`[zync] pull:skip-pending-remove stateKey=${stateKey} id=${remote.id}`);\n continue;\n }\n\n const localItem = localById.get(remote.id);\n if (remote.deleted) {\n if (localItem) {\n nextItems = nextItems.filter((i: any) => i.id !== remote.id);\n logger.debug(`[zync] pull:remove stateKey=${stateKey} id=${remote.id}`);\n }\n continue;\n }\n\n delete remote.deleted;\n\n if (localItem) {\n const pendingChange = pendingChanges.find((p: any) => p.stateKey === stateKey && p.localId === localItem._localId);\n if (pendingChange) {\n // TODO: Conflict resolution required\n switch (conflictResolutionStrategy) {\n case 'local-wins':\n // Ignore remote changes, keep local\n logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n break;\n\n case 'remote-wins': {\n // Ignore local changes, keep remote\n const merged = {\n ...remote,\n _localId: localItem._localId,\n };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n break;\n }\n\n // case 'try-shallow-merge':\n // // Try and merge all fields, fail if not possible due to conflicts\n // // throw new ConflictError('Details...');\n // Object.entries(pendingChange.changes || {}).map(([key, value]) => {\n // const localValue = localItem[key];\n // const remoteValue = remote[key];\n // if (localValue !== undefined && localValue !== value) {\n // //throw new ConflictError(`Conflict on ${key}: local=${localValue} remote=${value}`);\n // }\n // });\n // break;\n\n // case 'custom':\n // // Hook to allow custom userland logic\n // // const error = onConflict(localItem, remote, stateKey, pending);\n // // logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id} error=${error}`);\n // // if (error) throw new ConflictError(error);\n // break;\n\n default:\n logger.error(`[zync] pull:conflict-strategy:unknown stateKey=${stateKey} id=${remote.id} strategy=${conflictResolutionStrategy}`);\n break;\n }\n } else {\n // No pending changes, merge remote into local\n const merged = {\n ...localItem,\n ...remote,\n _localId: localItem._localId,\n };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n logger.debug(`[zync] pull:merge-remote stateKey=${stateKey} id=${remote.id}`);\n }\n } else {\n // Add remote item (no local item)\n nextItems = [...nextItems, { ...remote, _localId: nextLocalId() }];\n logger.debug(`[zync] pull:add stateKey=${stateKey} id=${remote.id}`);\n }\n }\n\n return {\n [stateKey]: nextItems,\n syncState: {\n ...(state.syncState || {}),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n}\n","import { removeFromPendingChanges, omitSyncFields, samePendingVersion } from './helpers';\nimport { SyncAction } from './index';\nimport type { Logger } from './logger';\nimport type {\n AfterRemoteAddCallback,\n ApiFunctions,\n MissingRemoteRecordStrategy,\n MissingRemoteRecordDuringUpdateCallback,\n PendingChange,\n SetAndSyncCallback,\n} from './types';\n\nconst SYNC_FIELDS = ['id', '_localId', 'updated_at', 'deleted'] as const;\n\nexport async function pushOne(\n set: any,\n get: any,\n change: PendingChange,\n api: ApiFunctions,\n logger: Logger,\n setAndQueueToSync: SetAndSyncCallback,\n missingStrategy: MissingRemoteRecordStrategy,\n onMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback,\n onAfterRemoteAdd?: AfterRemoteAddCallback,\n) {\n logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);\n\n const { action, stateKey, localId, id, version } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id ${stateKey} ${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success ${stateKey} ${localId} ${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.CreateOrUpdate: {\n const state = get();\n const items: any[] = state[stateKey] || [];\n const item = items.find((i) => i._localId === localId);\n if (!item) {\n logger.warn(`[zync] push:create-or-update:no-local-item`, {\n stateKey,\n localId,\n });\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n const omittedItem = omitSyncFields(item, SYNC_FIELDS);\n if (item.id) {\n // Update\n const changed = await api.update(item.id, omittedItem);\n if (changed) {\n logger.debug('[zync] push:update:success', {\n stateKey,\n localId,\n id: item.id,\n });\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n return;\n } else {\n switch (missingStrategy) {\n case 'delete-local-record':\n set((s: any) => ({\n [stateKey]: (s[stateKey] || []).filter((i: any) => i._localId !== localId),\n }));\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'insert-remote-record':\n omittedItem._localId = crypto.randomUUID();\n omittedItem.updated_at = new Date().toISOString();\n\n // replace old with new copy without id so it becomes a Create\n setAndQueueToSync((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? omittedItem : i)),\n }));\n\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'ignore':\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n default:\n logger.error(`[zync] push:missing-remote:unknown stateKey=${stateKey} id=${item.id} strategy=${missingStrategy}`);\n break;\n }\n\n removeFromPendingChanges(set, localId, stateKey);\n // Call hook so userland can alert the user etc.\n onMissingRemoteRecordDuringUpdate?.(missingStrategy, item, omittedItem._localId);\n }\n return;\n }\n\n // Create\n const result = await api.add(omittedItem);\n if (result) {\n logger.debug('[zync] push:create:success', {\n stateKey,\n localId,\n id: result.id,\n });\n\n // Merge server-assigned fields (id, updated_at, etc) directly into local entity\n set((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? { ...i, ...result } : i)),\n }));\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, {\n ...item,\n ...result,\n });\n } else {\n logger.warn('[zync] push:create:no-result', {\n stateKey,\n localId,\n });\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDBStorage(options: { dbName: string; storeName: string }) {\n const dbName = options.dbName;\n const storeName = options.storeName;\n\n // dbPromise is created lazily by initDB() to avoid pulling `idb` into bundles\n let dbPromise: Promise<IDBPDatabase<any>> | null = null;\n\n async function initDB(): Promise<IDBPDatabase<any>> {\n if (dbPromise) return dbPromise;\n try {\n const idb = await import(/* webpackChunkName: \"idb\" */ 'idb');\n dbPromise = idb.openDB(dbName, 1, {\n upgrade(db: IDBPDatabase<any>) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n return dbPromise;\n } catch (_e) {\n throw new Error('Missing optional dependency \"idb\". Install it to use IndexedDB storage: npm install idb');\n }\n }\n\n async function ensureStore(): Promise<void> {\n const db = await initDB();\n if (db.objectStoreNames.contains(storeName)) return;\n const nextVersion = (db.version || 0) + 1;\n try {\n db.close();\n } catch (_e) {\n // ignore\n }\n const idb = await import(/* webpackChunkName: \"idb\" */ 'idb');\n dbPromise = idb.openDB(dbName, nextVersion, {\n upgrade(upg: IDBPDatabase<any>) {\n if (!upg.objectStoreNames.contains(storeName)) upg.createObjectStore(storeName);\n },\n });\n await dbPromise;\n }\n\n async function withRetry<T>(fn: (db: IDBPDatabase<any>) => Promise<T>): Promise<T> {\n try {\n const db = await initDB();\n return await fn(db);\n } catch (err: any) {\n const msg = String(err && err.message ? err.message : err);\n if (err && (err.name === 'NotFoundError' || /objectStore/i.test(msg))) {\n await ensureStore();\n const db2 = await initDB();\n return await fn(db2);\n }\n throw err;\n }\n }\n\n return {\n getItem: async (name: string): Promise<string | null> => {\n return withRetry(async (db) => {\n let v = await db.get(storeName, name);\n v = v ?? null; // Zustand expects null for missing keys\n return v;\n });\n },\n setItem: async (name: string, value: string): Promise<void> => {\n return withRetry(async (db) => {\n await db.put(storeName, value, name);\n });\n },\n removeItem: async (name: string): Promise<void> => {\n return withRetry(async (db) => {\n await db.delete(storeName, name);\n });\n },\n };\n}\n"],"mappings":"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","names":["SyncAction","state"]}
|