@anfenn/zync 0.4.8 → 0.5.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 CHANGED
@@ -11,7 +11,7 @@ sqlite or the complexity of DB schemas and relationships, and it keeps your comp
11
11
 
12
12
  The tradeoff however is although Zustand can use IndexedDB, it will store all state in one key, and so load it all into the JS VM.
13
13
 
14
- When you need sqlite, or you know the client will need large amounts of data, [WatermelondDB](https://github.com/nozbe/WatermelonDB) is what you want. This will however require a backend that provides the PUSH/PULL endpoints for synchronising or perhaps modifying the frontend to redirect those requests to and from specific endpoints.
14
+ When you need sqlite, or you know the client will need large amounts of data, [Dync](https://github.com/anfen/dync) is what you want.
15
15
 
16
16
  ## Benefits
17
17
 
@@ -108,7 +108,7 @@ export const useStore = create<any>()(
108
108
  // State-to-API map to enable syncing. Must implement the full CRUD API:
109
109
  //
110
110
  // add: (item: any) => Promise<any | undefined>
111
- // update: (id: any, changes: any) => Promise<boolean>
111
+ // update: (id: any, changes: any, item: any) => Promise<boolean>
112
112
  // remove: (id: any) => Promise<void>
113
113
  // list: (lastUpdatedAt: Date) => Promise<any[]>
114
114
  // firstLoad: (lastId: any) => Promise<any[]> (Optional)
@@ -116,9 +116,17 @@ export const useStore = create<any>()(
116
116
  facts: factApi,
117
117
  },
118
118
  {
119
+ // Default: 2000 (ms)
120
+ syncInterval: 2000,
121
+
122
+ // Default: undefined (ms)
123
+ // Override syncInterval above for just pull requests, per api (Push requests are still controlled by syncInterval)
124
+ // Has no effect if less than syncInterval
125
+ apiConfig: { facts: { pullInterval: 10000 } },
126
+
119
127
  // Options: 'ignore' | 'delete-local-record' | 'insert-remote-record'
120
128
  // Default: 'ignore'
121
- // Triggered by the api.update() returning true or false confirming the existence of the remote record after an update
129
+ // Triggered by api.update() returning false confirming the absence of the remote record
122
130
  missingRemoteRecordDuringUpdateStrategy: 'ignore',
123
131
 
124
132
  // Options: 'local-wins' | 'remote-wins' | 'try-shallow-merge'
@@ -160,6 +168,7 @@ function App() {
160
168
  // syncState.conflicts
161
169
  // syncState.firstLoadDone
162
170
  // syncState.pendingChanges
171
+ // syncState.lastUpdatedAt
163
172
  // syncState.lastPulled
164
173
 
165
174
  useEffect(() => {
@@ -220,7 +229,7 @@ async function add(item: any): Promise<any | undefined> {
220
229
  }
221
230
  }
222
231
 
223
- async function update(id: number, changes: any): Promise<boolean> {
232
+ async function update(id: number, changes: any, item: any): Promise<boolean> {
224
233
  const { status, statusText, data } = await supabase.from('fact').update(changes).eq('id', id).select();
225
234
 
226
235
  if (status !== 200) {
package/dist/index.cjs CHANGED
@@ -380,12 +380,14 @@ function removeFromPendingChanges(set, localId, stateKey) {
380
380
  }
381
381
  function tryAddToPendingChanges(pendingChanges, stateKey, changes) {
382
382
  for (const [localId, change] of changes) {
383
- let omittedItem = omitSyncFields(change.changes);
383
+ let omittedChanges = omitSyncFields(change.changes);
384
+ const omittedCurrentItem = omitSyncFields(change.currentItem);
385
+ const omittedUpdatedItem = omitSyncFields(change.updatedItem);
384
386
  const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);
385
- const hasChanges = Object.keys(omittedItem).length > 0;
387
+ const hasChanges = Object.keys(omittedChanges).length > 0;
386
388
  const action = change.updatedItem === null ? "remove" /* Remove */ : change.currentItem === null ? "create" /* Create */ : "update" /* Update */;
387
389
  if (action === "update" /* Update */ && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {
388
- omittedItem = omitSyncFields(change.updatedItem);
390
+ omittedChanges = omittedUpdatedItem;
389
391
  }
390
392
  if (queueItem) {
391
393
  if (queueItem.action === "remove" /* Remove */) {
@@ -395,10 +397,20 @@ function tryAddToPendingChanges(pendingChanges, stateKey, changes) {
395
397
  if (action === "remove" /* Remove */) {
396
398
  queueItem.action = "remove" /* Remove */;
397
399
  } else if (hasChanges) {
398
- queueItem.changes = { ...queueItem.changes, ...omittedItem };
400
+ queueItem.changes = { ...queueItem.changes, ...omittedChanges };
401
+ queueItem.after = { ...queueItem.after, ...omittedUpdatedItem };
399
402
  }
400
403
  } else if (action === "remove" /* Remove */ || hasChanges) {
401
- pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem, before: omitSyncFields(change.currentItem) });
404
+ pendingChanges.push({
405
+ action,
406
+ stateKey,
407
+ localId,
408
+ id: change.id,
409
+ version: 1,
410
+ changes: omittedChanges,
411
+ before: omittedCurrentItem,
412
+ after: omittedUpdatedItem
413
+ });
402
414
  }
403
415
  }
404
416
  }
@@ -441,6 +453,14 @@ function findApi(stateKey, syncApi) {
441
453
  }
442
454
  return api;
443
455
  }
456
+ function isPullIntervalNow(stateKey, apiConfig, lastPulled) {
457
+ const config = apiConfig[stateKey];
458
+ if (!config || !config.pullInterval) {
459
+ return true;
460
+ }
461
+ const lastPulledTime = new Date(lastPulled[stateKey] ?? 0).getTime();
462
+ return Date.now() > lastPulledTime + config.pullInterval;
463
+ }
444
464
  function findChanges(current, updated) {
445
465
  const currentMap = /* @__PURE__ */ new Map();
446
466
  for (const item of current) {
@@ -522,12 +542,11 @@ function resolveConflict(set, localId, keepLocalFields) {
522
542
 
523
543
  // src/pull.ts
524
544
  async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy) {
525
- const lastPulled = get().syncState.lastPulled || {};
526
- const lastPulledAt = new Date(lastPulled[stateKey] || /* @__PURE__ */ new Date(0));
527
- logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastPulledAt.toISOString()}`);
528
- const serverData = await api.list(lastPulledAt);
545
+ const lastUpdatedAt = get().syncState.lastUpdatedAt || {};
546
+ let lastUpdatedAtDate = new Date(lastUpdatedAt[stateKey] || /* @__PURE__ */ new Date(0));
547
+ logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastUpdatedAtDate.toISOString()}`);
548
+ const serverData = await api.list(lastUpdatedAtDate);
529
549
  if (!serverData?.length) return;
530
- let newest = lastPulledAt;
531
550
  set((state) => {
532
551
  let pendingChanges = [...state.syncState.pendingChanges];
533
552
  const conflicts = { ...state.syncState.conflicts };
@@ -537,7 +556,7 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
537
556
  const pendingRemovalById = new Set(pendingChanges.filter((p) => p.stateKey === stateKey && p.action === "remove" /* Remove */).map((p) => p.id));
538
557
  for (const remote of serverData) {
539
558
  const remoteUpdated = new Date(remote.updated_at);
540
- if (remoteUpdated > newest) newest = remoteUpdated;
559
+ if (remoteUpdated > lastUpdatedAtDate) lastUpdatedAtDate = remoteUpdated;
541
560
  if (pendingRemovalById.has(remote.id)) {
542
561
  logger.debug(`[zync] pull:skip-pending-remove stateKey=${stateKey} id=${remote.id}`);
543
562
  continue;
@@ -600,9 +619,9 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
600
619
  ...state.syncState || {},
601
620
  pendingChanges,
602
621
  conflicts: hasKeysOrUndefined(conflicts),
603
- lastPulled: {
604
- ...state.syncState.lastPulled || {},
605
- [stateKey]: newest.toISOString()
622
+ lastUpdatedAt: {
623
+ ...state.syncState.lastUpdatedAt || {},
624
+ [stateKey]: lastUpdatedAtDate.toISOString()
606
625
  }
607
626
  }
608
627
  };
@@ -612,7 +631,7 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
612
631
  // src/push.ts
613
632
  async function pushOne(set, get, change, api, logger, setAndQueueToSync, missingStrategy, onMissingRemoteRecordDuringUpdate, onAfterRemoteAdd) {
614
633
  logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);
615
- const { action, stateKey, localId, id, version, changes } = change;
634
+ const { action, stateKey, localId, id, version, changes, after } = change;
616
635
  switch (action) {
617
636
  case "remove" /* Remove */:
618
637
  if (!id) {
@@ -629,7 +648,7 @@ async function pushOne(set, get, change, api, logger, setAndQueueToSync, missing
629
648
  logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);
630
649
  return;
631
650
  }
632
- const exists = await api.update(id, changes);
651
+ const exists = await api.update(id, changes, after);
633
652
  if (exists) {
634
653
  logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);
635
654
  if (samePendingVersion(get, stateKey, localId, version)) {
@@ -721,7 +740,7 @@ async function startFirstLoad(set, syncApi, logger) {
721
740
  set((state) => {
722
741
  const local = state[stateKey] || [];
723
742
  const localById = new Map(local.filter((l) => l.id).map((l) => [l.id, l]));
724
- let newest = new Date(state.syncState.lastPulled[stateKey] || 0);
743
+ let newest = new Date(state.syncState.lastUpdatedAt[stateKey] || 0);
725
744
  const next = [...local];
726
745
  for (const remote of batch) {
727
746
  const remoteUpdated = new Date(remote.updated_at || 0);
@@ -748,8 +767,8 @@ async function startFirstLoad(set, syncApi, logger) {
748
767
  [stateKey]: next,
749
768
  syncState: {
750
769
  ...state.syncState || {},
751
- lastPulled: {
752
- ...state.syncState.lastPulled || {},
770
+ lastUpdatedAt: {
771
+ ...state.syncState.lastUpdatedAt || {},
753
772
  [stateKey]: newest.toISOString()
754
773
  }
755
774
  }
@@ -867,6 +886,7 @@ function createWithSync(stateCreator, persistOptions, syncApi, syncOptions = {})
867
886
  }
868
887
  function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}) {
869
888
  const syncInterval = syncOptions.syncInterval ?? DEFAULT_SYNC_INTERVAL_MILLIS;
889
+ const apiConfig = syncOptions.apiConfig ?? {};
870
890
  const missingStrategy = syncOptions.missingRemoteRecordDuringUpdateStrategy ?? DEFAULT_MISSING_REMOTE_RECORD_STRATEGY;
871
891
  const conflictResolutionStrategy = syncOptions.conflictResolutionStrategy ?? DEFAULT_CONFLICT_RESOLUTION_STRATEGY;
872
892
  const logger = newLogger(syncOptions.logger ?? DEFAULT_LOGGER, syncOptions.minLogLevel ?? DEFAULT_MIN_LOG_LEVEL);
@@ -893,6 +913,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
893
913
  syncState: {
894
914
  firstLoadDone: syncState.firstLoadDone,
895
915
  pendingChanges: syncState.pendingChanges,
916
+ lastUpdatedAt: syncState.lastUpdatedAt,
896
917
  lastPulled: syncState.lastPulled,
897
918
  conflicts: syncState.conflicts
898
919
  }
@@ -921,10 +942,13 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
921
942
  }
922
943
  }));
923
944
  let firstSyncError;
945
+ const lastPulled = { ...get().syncState.lastPulled };
924
946
  for (const stateKey of Object.keys(syncApi)) {
925
947
  try {
948
+ if (!isPullIntervalNow(stateKey, apiConfig, lastPulled)) continue;
926
949
  const api = findApi(stateKey, syncApi);
927
950
  await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);
951
+ lastPulled[stateKey] = (/* @__PURE__ */ new Date()).toISOString();
928
952
  } catch (err) {
929
953
  firstSyncError = firstSyncError ?? err;
930
954
  logger.error(`[zync] pull:error stateKey=${stateKey}`, err);
@@ -955,7 +979,8 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
955
979
  syncState: {
956
980
  ...state.syncState || {},
957
981
  status: "idle",
958
- error: firstSyncError
982
+ error: firstSyncError,
983
+ lastPulled
959
984
  }
960
985
  }));
961
986
  }
@@ -1041,6 +1066,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
1041
1066
  conflicts: void 0,
1042
1067
  firstLoadDone: false,
1043
1068
  pendingChanges: [],
1069
+ lastUpdatedAt: {},
1044
1070
  lastPulled: {}
1045
1071
  }
1046
1072
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/.pnpm/idb@8.0.3/node_modules/idb/build/index.js","../src/index.ts","../src/logger.ts","../src/helpers.ts","../src/pull.ts","../src/push.ts","../src/firstLoad.ts","../src/indexedDBStorage.ts"],"sourcesContent":["const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(this.request);\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n get(target, prop) {\n if (!advanceMethodProps.includes(prop))\n return target[prop];\n let cachedFunc = methodMap[prop];\n if (!cachedFunc) {\n cachedFunc = methodMap[prop] = function (...args) {\n advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n };\n }\n return cachedFunc;\n },\n};\nasync function* iterate(...args) {\n // tslint:disable-next-line:no-this-assignment\n let cursor = this;\n if (!(cursor instanceof IDBCursor)) {\n cursor = await cursor.openCursor(...args);\n }\n if (!cursor)\n return;\n cursor = cursor;\n const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n // Map this double-proxy back to the original, so other cursor methods work.\n reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n while (cursor) {\n yield proxiedCursor;\n // If one of the advancing methods was not called, call continue().\n cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n advanceResults.delete(proxiedCursor);\n }\n}\nfunction isIteratorProp(target, prop) {\n return ((prop === Symbol.asyncIterator &&\n instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get(target, prop, receiver) {\n if (isIteratorProp(target, prop))\n return iterate;\n return oldTraps.get(target, prop, receiver);\n },\n has(target, prop) {\n return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n","import { create, type StateCreator } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport { newLogger, type Logger, type LogLevel } from './logger';\nimport { orderFor, findApi, findChanges, tryAddToPendingChanges, tryUpdateConflicts, resolveConflict, sleep } from './helpers';\nimport {\n type ApiFunctions,\n type SyncOptions,\n type SyncState,\n type SyncedStateCreator,\n type PendingChange,\n type UseStoreWithSync,\n type MissingRemoteRecordStrategy,\n type ConflictResolutionStrategy,\n} from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\nimport { startFirstLoad } from './firstLoad';\n\nexport { createIndexedDB } from './indexedDBStorage';\nexport { createLocalId, changeKeysTo, changeKeysFrom } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n Create = 'create',\n Update = 'update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 2000;\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 = 'try-shallow-merge';\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 conflicts: syncState.conflicts,\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 syncTimerStarted = false;\n\n async function syncOnce() {\n if (get().syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let firstSyncError: 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 firstSyncError = firstSyncError ?? (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 firstSyncError = firstSyncError ?? (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: firstSyncError,\n } as SyncState['syncState'],\n }));\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 }\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 tryAddToPendingChanges(pendingChanges, stateKey, changes);\n });\n\n // Prevent stale conflicts reporting old values to user\n const conflicts = tryUpdateConflicts(pendingChanges, state.syncState.conflicts);\n\n return {\n ...partial,\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n conflicts,\n } as SyncState['syncState'],\n };\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: enabled ? 'idle' : 'disabled',\n },\n }));\n\n startSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function startSyncTimer(start: boolean) {\n if (start) {\n tryStart(); // Unawaited async\n } else {\n syncTimerStarted = false;\n }\n }\n\n async function tryStart() {\n if (syncTimerStarted) return;\n syncTimerStarted = true;\n\n while (true) {\n if (!syncTimerStarted) break;\n await syncOnce();\n await sleep(syncInterval);\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 startSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n startSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad: () => startFirstLoad(set, syncApi, logger),\n resolveConflict: (localId: string, keepLocal: boolean) => resolveConflict(set, localId, keepLocal),\n };\n\n const userState = stateCreator(set, get, setAndQueueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n conflicts: undefined,\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, Conflict, FieldConflict, PendingChange, SyncState } from './types';\n\nconst SYNC_FIELDS = ['_localId', 'updated_at', 'deleted'] as const;\n\nexport function createLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function changeKeysTo(input: any | any[], toIdKey: string, toUpdatedAtKey: string, toDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { id, updated_at, deleted, ...rest } = item;\n return {\n [toIdKey]: id,\n [toUpdatedAtKey]: updated_at,\n [toDeletedKey]: deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function changeKeysFrom(input: any | any[], fromIdKey: string, fromUpdatedAtKey: string, fromDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;\n return {\n id,\n updated_at,\n deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.Create:\n return 1;\n case SyncAction.Update:\n return 2;\n case SyncAction.Remove:\n return 3;\n }\n}\n\nexport function omitSyncFields(item: any) {\n const result = { ...item };\n for (const k of SYNC_FIELDS) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const pending: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = pending.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 tryAddToPendingChanges(pendingChanges: PendingChange[], stateKey: string, changes: Map<string, ChangeRecord>) {\n for (const [localId, change] of changes) {\n let omittedItem = omitSyncFields(change.changes);\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n const hasChanges = Object.keys(omittedItem).length > 0;\n const action = change.updatedItem === null ? SyncAction.Remove : change.currentItem === null ? SyncAction.Create : SyncAction.Update;\n\n if (action === SyncAction.Update && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {\n // Here when insert-remote-record swaps local remotely deleted item with a fresh copy to push up\n omittedItem = omitSyncFields(change.updatedItem);\n }\n\n if (queueItem) {\n if (queueItem.action === SyncAction.Remove) {\n // Once a Remove is queued, it stays a Remove\n continue;\n }\n\n queueItem.version += 1;\n\n if (action === SyncAction.Remove) {\n queueItem.action = SyncAction.Remove;\n } else if (hasChanges) {\n // Never change the action here, it stays Create or Update and is removed when synced\n queueItem.changes = { ...queueItem.changes, ...omittedItem };\n }\n } else if (action === SyncAction.Remove || hasChanges) {\n pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem, before: omitSyncFields(change.currentItem) });\n }\n }\n}\n\nexport function setPendingChangeToUpdate(get: any, stateKey: string, localId: string, id?: any) {\n // id is optional as the user may client assign the id, but not return it from the api\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.action = SyncAction.Update;\n if (id) change.id = id;\n }\n}\n\nexport function setPendingChangeBefore(get: any, stateKey: string, localId: string, before: any) {\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.before = { ...change.before, ...before };\n }\n}\n\nexport function tryUpdateConflicts(pendingChanges: PendingChange[], conflicts?: Record<string, Conflict>): Record<string, Conflict> | undefined {\n if (!conflicts) return conflicts;\n\n const newConflicts = { ...conflicts };\n\n for (const change of pendingChanges) {\n const conflict = newConflicts[change.localId];\n if (conflict && change.changes) {\n // Loop changed fields and update their old possibly stale value to the current local value\n const newFields = conflict.fields.map((f) => {\n if (f.key in change.changes) {\n return { ...f, localValue: change.changes[f.key] } as FieldConflict;\n }\n return f;\n });\n\n newConflicts[change.localId] = { stateKey: conflict.stateKey, fields: newFields };\n }\n }\n\n return newConflicts;\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) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n return api;\n}\n\ntype ChangeRecord = {\n currentItem?: any;\n updatedItem?: any;\n changes: any;\n id?: 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 update of updated) {\n const item = { ...update };\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 // Changes\n changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff, id: curr.id ?? item.id });\n }\n } else {\n // Addition\n changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item, id: item.id });\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, id: curr.id });\n }\n }\n\n return changesMap;\n}\n\nexport function hasKeysOrUndefined(obj: any): any {\n return Object.keys(obj).length === 0 ? undefined : obj;\n}\n\nexport function hasConflicts(get: any, localId: string): boolean {\n const state = get() as SyncState;\n if (state.syncState.conflicts) {\n return !!state.syncState.conflicts[localId];\n }\n return false;\n}\n\nexport function resolveConflict(set: any, localId: string, keepLocalFields: boolean) {\n set((state: any) => {\n const syncState: SyncState['syncState'] = state.syncState || {};\n const conflicts: Record<string, Conflict> = syncState.conflicts || {};\n const conflict = conflicts[localId];\n if (conflict) {\n const items = state[conflict.stateKey];\n const item = items.find((i: any) => i._localId === localId);\n if (!item) {\n return state;\n }\n\n const resolved: any = { ...item };\n let pendingChanges = [...syncState.pendingChanges];\n\n if (!keepLocalFields) {\n // Use remote value(s)\n for (const field of conflict.fields) {\n resolved[field.key] = field.remoteValue;\n }\n\n // Remove resolved pending change\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === conflict.stateKey && p.localId === localId));\n }\n\n // Replace with resolved item\n const nextItems = items.map((i: any) => (i._localId === localId ? resolved : i));\n const nextConflicts = { ...conflicts };\n delete nextConflicts[localId];\n\n return {\n [conflict.stateKey]: nextItems,\n syncState: {\n ...syncState,\n pendingChanges,\n conflicts: hasKeysOrUndefined(nextConflicts),\n },\n };\n }\n return state;\n });\n}\n","import { type ApiFunctions, type FieldConflict, type ConflictResolutionStrategy, type SyncedRecord, type PendingChange } from './types';\nimport { SyncAction } from './index';\nimport { createLocalId, hasKeysOrUndefined } 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\n set((state: any) => {\n let pendingChanges = [...(state.syncState.pendingChanges as PendingChange[])];\n const conflicts = { ...state.syncState.conflicts };\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items when 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 logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n\n switch (conflictResolutionStrategy) {\n case 'local-wins':\n // Ignore remote changes, keep local\n break;\n\n case 'remote-wins': {\n // Ignore local changes, keep remote\n const merged = { ...remote, _localId: localItem._localId };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Remove pending change so it isn't pushed after pull\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === stateKey && p.localId === localItem._localId));\n break;\n }\n\n case 'try-shallow-merge': {\n // List fields that local and remote have changed\n const changes = pendingChange.changes || {};\n const before = pendingChange.before || {};\n const fields: FieldConflict[] = Object.entries(changes)\n .filter(([k, localValue]) => k in before && k in remote && before[k] !== remote[k] && localValue !== remote[k])\n .map(([key, localValue]) => ({ key, localValue, remoteValue: remote[key] }));\n\n if (fields.length > 0) {\n logger.warn(`[zync] pull:${conflictResolutionStrategy}:conflicts-found`, JSON.stringify(fields, null, 4));\n conflicts[localItem._localId] = { stateKey, fields };\n } else {\n // No conflicts, merge remote into local but only preserve fields that were\n // actually changed locally\n const localChangedKeys = Object.keys(changes);\n const preservedLocal: any = { _localId: localItem._localId };\n for (const k of localChangedKeys) {\n if (k in localItem) preservedLocal[k] = localItem[k];\n }\n\n const merged = { ...remote, ...preservedLocal };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Merge now resolved, drop pending and conflict\n delete conflicts[localItem._localId];\n }\n break;\n }\n }\n } else {\n // No pending changes, merge remote into local\n const merged = { ...localItem, ...remote };\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: createLocalId() }];\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 pendingChanges,\n conflicts: hasKeysOrUndefined(conflicts),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n}\n","import { hasConflicts, removeFromPendingChanges, samePendingVersion, setPendingChangeBefore, setPendingChangeToUpdate } from './helpers';\nimport { createLocalId, 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\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, changes } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success stateKey=${stateKey} localId=${localId} id=${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.Update: {\n if (hasConflicts(get, change.localId)) {\n logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);\n return;\n }\n\n const exists = await api.update(id, changes);\n if (exists) {\n logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure pending.before is not stale for conflict resolution\n setPendingChangeBefore(get, stateKey, localId, changes);\n }\n return;\n } else {\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:missing-remote:no-local-item stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\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 logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'insert-remote-record': {\n const newItem = {\n ...item,\n _localId: createLocalId(),\n updated_at: new Date().toISOString(),\n };\n\n // replace old with modified and queue Create\n setAndQueueToSync((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? newItem : i)),\n }));\n\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${newItem.id}`);\n break;\n }\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-strategy 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);\n }\n break;\n }\n\n case SyncAction.Create: {\n const result = await api.add(changes);\n if (result) {\n logger.debug(`[zync] push:create:success stateKey=${stateKey} localId=${localId} id=${id}`);\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\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure any pendingChanges entry has id and is now an Update\n setPendingChangeToUpdate(get, stateKey, localId, result.id);\n }\n\n const finalItem = { ...changes, ...result, _localId: localId };\n\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, finalItem);\n } else {\n logger.warn(`[zync] push:create:no-result stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import { createLocalId } from './helpers';\nimport type { Logger } from './logger';\nimport type { ApiFunctions } from './types';\n\nexport async function startFirstLoad(set: any, syncApi: Record<string, ApiFunctions>, logger: Logger) {\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 = syncApi[stateKey];\n if (!api?.firstLoad) {\n logger.error(`[zync] firstLoad:no-api-function stateKey=${stateKey}`);\n continue;\n }\n\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: createLocalId(),\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 if (lastId !== undefined && lastId === batch[batch.length - 1].id) {\n throw new Error(`Duplicate records downloaded, stopping to prevent infinite loop`);\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","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDB(dbName: string, storeName: string) {\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":["target","SyncAction"]}
1
+ {"version":3,"sources":["../node_modules/.pnpm/idb@8.0.3/node_modules/idb/build/index.js","../src/index.ts","../src/logger.ts","../src/helpers.ts","../src/pull.ts","../src/push.ts","../src/firstLoad.ts","../src/indexedDBStorage.ts"],"sourcesContent":["const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(this.request);\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n get(target, prop) {\n if (!advanceMethodProps.includes(prop))\n return target[prop];\n let cachedFunc = methodMap[prop];\n if (!cachedFunc) {\n cachedFunc = methodMap[prop] = function (...args) {\n advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n };\n }\n return cachedFunc;\n },\n};\nasync function* iterate(...args) {\n // tslint:disable-next-line:no-this-assignment\n let cursor = this;\n if (!(cursor instanceof IDBCursor)) {\n cursor = await cursor.openCursor(...args);\n }\n if (!cursor)\n return;\n cursor = cursor;\n const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n // Map this double-proxy back to the original, so other cursor methods work.\n reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n while (cursor) {\n yield proxiedCursor;\n // If one of the advancing methods was not called, call continue().\n cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n advanceResults.delete(proxiedCursor);\n }\n}\nfunction isIteratorProp(target, prop) {\n return ((prop === Symbol.asyncIterator &&\n instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get(target, prop, receiver) {\n if (isIteratorProp(target, prop))\n return iterate;\n return oldTraps.get(target, prop, receiver);\n },\n has(target, prop) {\n return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n","import { create, type StateCreator } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport { newLogger, type Logger, type LogLevel } from './logger';\nimport { orderFor, findApi, findChanges, tryAddToPendingChanges, tryUpdateConflicts, resolveConflict, sleep, isPullIntervalNow } from './helpers';\nimport {\n type ApiFunctions,\n type SyncOptions,\n type SyncState,\n type SyncedStateCreator,\n type PendingChange,\n type UseStoreWithSync,\n type MissingRemoteRecordStrategy,\n type ConflictResolutionStrategy,\n} from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\nimport { startFirstLoad } from './firstLoad';\n\nexport { createIndexedDB } from './indexedDBStorage';\nexport { createLocalId, changeKeysTo, changeKeysFrom } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n Create = 'create',\n Update = 'update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 2000;\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 = 'try-shallow-merge';\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 apiConfig = syncOptions.apiConfig ?? {};\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 lastUpdatedAt: syncState.lastUpdatedAt,\n lastPulled: syncState.lastPulled,\n conflicts: syncState.conflicts,\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 syncTimerStarted = false;\n\n async function syncOnce() {\n if (get().syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let firstSyncError: Error | undefined;\n const lastPulled: SyncState['syncState']['lastPulled'] = { ...get().syncState.lastPulled };\n\n // 1) PULL for each stateKey\n for (const stateKey of Object.keys(syncApi)) {\n try {\n if (!isPullIntervalNow(stateKey, apiConfig, lastPulled)) continue;\n\n const api = findApi(stateKey, syncApi);\n await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);\n lastPulled[stateKey] = new Date().toISOString();\n } catch (err) {\n firstSyncError = firstSyncError ?? (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 firstSyncError = firstSyncError ?? (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: firstSyncError,\n lastPulled,\n } as SyncState['syncState'],\n }));\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 }\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 tryAddToPendingChanges(pendingChanges, stateKey, changes);\n });\n\n // Prevent stale conflicts reporting old values to user\n const conflicts = tryUpdateConflicts(pendingChanges, state.syncState.conflicts);\n\n return {\n ...partial,\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n conflicts,\n } as SyncState['syncState'],\n };\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: enabled ? 'idle' : 'disabled',\n },\n }));\n\n startSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function startSyncTimer(start: boolean) {\n if (start) {\n tryStart(); // Unawaited async\n } else {\n syncTimerStarted = false;\n }\n }\n\n async function tryStart() {\n if (syncTimerStarted) return;\n syncTimerStarted = true;\n\n while (true) {\n if (!syncTimerStarted) break;\n await syncOnce();\n await sleep(syncInterval);\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 startSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n startSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad: () => startFirstLoad(set, syncApi, logger),\n resolveConflict: (localId: string, keepLocal: boolean) => resolveConflict(set, localId, keepLocal),\n };\n\n const userState = stateCreator(set, get, setAndQueueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n conflicts: undefined,\n firstLoadDone: false,\n pendingChanges: [],\n lastUpdatedAt: {},\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 { ApiConfig, ApiFunctions, Conflict, FieldConflict, PendingChange, SyncState } from './types';\n\nconst SYNC_FIELDS = ['_localId', 'updated_at', 'deleted'] as const;\n\nexport function createLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function changeKeysTo(input: any | any[], toIdKey: string, toUpdatedAtKey: string, toDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { id, updated_at, deleted, ...rest } = item;\n return {\n [toIdKey]: id,\n [toUpdatedAtKey]: updated_at,\n [toDeletedKey]: deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function changeKeysFrom(input: any | any[], fromIdKey: string, fromUpdatedAtKey: string, fromDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;\n return {\n id,\n updated_at,\n deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.Create:\n return 1;\n case SyncAction.Update:\n return 2;\n case SyncAction.Remove:\n return 3;\n }\n}\n\nexport function omitSyncFields(item: any) {\n const result = { ...item };\n for (const k of SYNC_FIELDS) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const pending: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = pending.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 tryAddToPendingChanges(pendingChanges: PendingChange[], stateKey: string, changes: Map<string, ChangeRecord>) {\n for (const [localId, change] of changes) {\n let omittedChanges = omitSyncFields(change.changes);\n const omittedCurrentItem = omitSyncFields(change.currentItem);\n const omittedUpdatedItem = omitSyncFields(change.updatedItem);\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n const hasChanges = Object.keys(omittedChanges).length > 0;\n const action = change.updatedItem === null ? SyncAction.Remove : change.currentItem === null ? SyncAction.Create : SyncAction.Update;\n\n if (action === SyncAction.Update && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {\n // Here when insert-remote-record swaps local remotely deleted item with a fresh copy to push up\n omittedChanges = omittedUpdatedItem;\n }\n\n if (queueItem) {\n if (queueItem.action === SyncAction.Remove) {\n // Once a Remove is queued, it stays a Remove\n continue;\n }\n\n queueItem.version += 1;\n\n if (action === SyncAction.Remove) {\n queueItem.action = SyncAction.Remove;\n } else if (hasChanges) {\n // Never change the action here, it stays Create or Update and is removed when synced\n queueItem.changes = { ...queueItem.changes, ...omittedChanges };\n queueItem.after = { ...queueItem.after, ...omittedUpdatedItem };\n }\n } else if (action === SyncAction.Remove || hasChanges) {\n pendingChanges.push({\n action,\n stateKey,\n localId,\n id: change.id,\n version: 1,\n changes: omittedChanges,\n before: omittedCurrentItem,\n after: omittedUpdatedItem,\n });\n }\n }\n}\n\nexport function setPendingChangeToUpdate(get: any, stateKey: string, localId: string, id?: any) {\n // id is optional as the user may client assign the id, but not return it from the api\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.action = SyncAction.Update;\n if (id) change.id = id;\n }\n}\n\nexport function setPendingChangeBefore(get: any, stateKey: string, localId: string, before: any) {\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.before = { ...change.before, ...before };\n }\n}\n\nexport function tryUpdateConflicts(pendingChanges: PendingChange[], conflicts?: Record<string, Conflict>): Record<string, Conflict> | undefined {\n if (!conflicts) return conflicts;\n\n const newConflicts = { ...conflicts };\n\n for (const change of pendingChanges) {\n const conflict = newConflicts[change.localId];\n if (conflict && change.changes) {\n // Loop changed fields and update their old possibly stale value to the current local value\n const newFields = conflict.fields.map((f) => {\n if (f.key in change.changes) {\n return { ...f, localValue: change.changes[f.key] } as FieldConflict;\n }\n return f;\n });\n\n newConflicts[change.localId] = { stateKey: conflict.stateKey, fields: newFields };\n }\n }\n\n return newConflicts;\n}\n\nexport function findApi(stateKey: string, syncApi: Record<string, ApiFunctions>): ApiFunctions {\n const api = syncApi[stateKey];\n if (!api || !api.add || !api.update || !api.remove || !api.list) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n\n return api;\n}\n\nexport function isPullIntervalNow(stateKey: string, apiConfig: Record<string, ApiConfig>, lastPulled: SyncState['syncState']['lastPulled']): boolean {\n const config = apiConfig[stateKey];\n if (!config || !config.pullInterval) {\n return true;\n }\n\n const lastPulledTime = new Date(lastPulled[stateKey] ?? 0).getTime();\n return Date.now() > lastPulledTime + config.pullInterval;\n}\n\ntype ChangeRecord = {\n currentItem?: any;\n updatedItem?: any;\n changes: any;\n id?: 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 update of updated) {\n const item = { ...update };\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 // Changes\n changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff, id: curr.id ?? item.id });\n }\n } else {\n // Addition\n changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item, id: item.id });\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, id: curr.id });\n }\n }\n\n return changesMap;\n}\n\nexport function hasKeysOrUndefined(obj: any): any {\n return Object.keys(obj).length === 0 ? undefined : obj;\n}\n\nexport function hasConflicts(get: any, localId: string): boolean {\n const state = get() as SyncState;\n if (state.syncState.conflicts) {\n return !!state.syncState.conflicts[localId];\n }\n return false;\n}\n\nexport function resolveConflict(set: any, localId: string, keepLocalFields: boolean) {\n set((state: any) => {\n const syncState: SyncState['syncState'] = state.syncState || {};\n const conflicts: Record<string, Conflict> = syncState.conflicts || {};\n const conflict = conflicts[localId];\n if (conflict) {\n const items = state[conflict.stateKey];\n const item = items.find((i: any) => i._localId === localId);\n if (!item) {\n return state;\n }\n\n const resolved: any = { ...item };\n let pendingChanges = [...syncState.pendingChanges];\n\n if (!keepLocalFields) {\n // Use remote value(s)\n for (const field of conflict.fields) {\n resolved[field.key] = field.remoteValue;\n }\n\n // Remove resolved pending change\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === conflict.stateKey && p.localId === localId));\n }\n\n // Replace with resolved item\n const nextItems = items.map((i: any) => (i._localId === localId ? resolved : i));\n const nextConflicts = { ...conflicts };\n delete nextConflicts[localId];\n\n return {\n [conflict.stateKey]: nextItems,\n syncState: {\n ...syncState,\n pendingChanges,\n conflicts: hasKeysOrUndefined(nextConflicts),\n },\n };\n }\n return state;\n });\n}\n","import { type ApiFunctions, type FieldConflict, type ConflictResolutionStrategy, type SyncedRecord, type PendingChange, type SyncState } from './types';\nimport { SyncAction } from './index';\nimport { createLocalId, hasKeysOrUndefined } 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 lastUpdatedAt: SyncState['syncState']['lastUpdatedAt'] = get().syncState.lastUpdatedAt || {};\n let lastUpdatedAtDate = new Date(lastUpdatedAt[stateKey] || new Date(0));\n\n logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastUpdatedAtDate.toISOString()}`);\n\n const serverData = (await api.list(lastUpdatedAtDate)) as SyncedRecord[];\n if (!serverData?.length) return;\n\n set((state: any) => {\n let pendingChanges = [...(state.syncState.pendingChanges as PendingChange[])];\n const conflicts = { ...state.syncState.conflicts };\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items when 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 > lastUpdatedAtDate) lastUpdatedAtDate = 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 logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n\n switch (conflictResolutionStrategy) {\n case 'local-wins':\n // Ignore remote changes, keep local\n break;\n\n case 'remote-wins': {\n // Ignore local changes, keep remote\n const merged = { ...remote, _localId: localItem._localId };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Remove pending change so it isn't pushed after pull\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === stateKey && p.localId === localItem._localId));\n break;\n }\n\n case 'try-shallow-merge': {\n // List fields that local and remote have changed\n const changes = pendingChange.changes || {};\n const before = pendingChange.before || {};\n const fields: FieldConflict[] = Object.entries(changes)\n .filter(([k, localValue]) => k in before && k in remote && before[k] !== remote[k] && localValue !== remote[k])\n .map(([key, localValue]) => ({ key, localValue, remoteValue: remote[key] }));\n\n if (fields.length > 0) {\n logger.warn(`[zync] pull:${conflictResolutionStrategy}:conflicts-found`, JSON.stringify(fields, null, 4));\n conflicts[localItem._localId] = { stateKey, fields };\n } else {\n // No conflicts, merge remote into local but only preserve fields that were\n // actually changed locally\n const localChangedKeys = Object.keys(changes);\n const preservedLocal: any = { _localId: localItem._localId };\n for (const k of localChangedKeys) {\n if (k in localItem) preservedLocal[k] = localItem[k];\n }\n\n const merged = { ...remote, ...preservedLocal };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Merge now resolved, drop pending and conflict\n delete conflicts[localItem._localId];\n }\n break;\n }\n }\n } else {\n // No pending changes, merge remote into local\n const merged = { ...localItem, ...remote };\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: createLocalId() }];\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 pendingChanges,\n conflicts: hasKeysOrUndefined(conflicts),\n lastUpdatedAt: {\n ...(state.syncState.lastUpdatedAt || {}),\n [stateKey]: lastUpdatedAtDate.toISOString(),\n },\n },\n };\n });\n}\n","import { hasConflicts, removeFromPendingChanges, samePendingVersion, setPendingChangeBefore, setPendingChangeToUpdate } from './helpers';\nimport { createLocalId, 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\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, changes, after } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success stateKey=${stateKey} localId=${localId} id=${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.Update: {\n if (hasConflicts(get, change.localId)) {\n logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);\n return;\n }\n\n const exists = await api.update(id, changes, after);\n if (exists) {\n logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure pending.before is not stale for conflict resolution\n setPendingChangeBefore(get, stateKey, localId, changes);\n }\n return;\n } else {\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:missing-remote:no-local-item stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\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 logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'insert-remote-record': {\n const newItem = {\n ...item,\n _localId: createLocalId(),\n updated_at: new Date().toISOString(),\n };\n\n // replace old with modified and queue Create\n setAndQueueToSync((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? newItem : i)),\n }));\n\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${newItem.id}`);\n break;\n }\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-strategy 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);\n }\n break;\n }\n\n case SyncAction.Create: {\n const result = await api.add(changes);\n if (result) {\n logger.debug(`[zync] push:create:success stateKey=${stateKey} localId=${localId} id=${id}`);\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\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure any pendingChanges entry has id and is now an Update\n setPendingChangeToUpdate(get, stateKey, localId, result.id);\n }\n\n const finalItem = { ...changes, ...result, _localId: localId };\n\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, finalItem);\n } else {\n logger.warn(`[zync] push:create:no-result stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import { createLocalId } from './helpers';\nimport type { Logger } from './logger';\nimport type { ApiFunctions } from './types';\n\nexport async function startFirstLoad(set: any, syncApi: Record<string, ApiFunctions>, logger: Logger) {\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 = syncApi[stateKey];\n if (!api?.firstLoad) {\n logger.error(`[zync] firstLoad:no-api-function stateKey=${stateKey}`);\n continue;\n }\n\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.lastUpdatedAt[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: createLocalId(),\n });\n }\n }\n\n return {\n [stateKey]: next,\n syncState: {\n ...(state.syncState || {}),\n lastUpdatedAt: {\n ...(state.syncState.lastUpdatedAt || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n\n if (lastId !== undefined && lastId === batch[batch.length - 1].id) {\n throw new Error(`Duplicate records downloaded, stopping to prevent infinite loop`);\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","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDB(dbName: string, storeName: string) {\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":["target","SyncAction"]}
package/dist/index.d.cts CHANGED
@@ -12,17 +12,22 @@ type SyncedRecord = {
12
12
  };
13
13
  interface ApiFunctions {
14
14
  add: (item: any) => Promise<any | undefined>;
15
- update: (id: any, changes: any) => Promise<boolean>;
15
+ update: (id: any, changes: any, item: any) => Promise<boolean>;
16
16
  remove: (id: any) => Promise<void>;
17
17
  list: (lastUpdatedAt: Date) => Promise<any[]>;
18
18
  firstLoad?: (lastId: any) => Promise<any[]>;
19
19
  }
20
20
  type MissingRemoteRecordStrategy = 'ignore' | 'delete-local-record' | 'insert-remote-record';
21
21
  type ConflictResolutionStrategy = 'local-wins' | 'remote-wins' | 'try-shallow-merge';
22
+ type SetAndSyncCallback = (state: any) => void;
22
23
  type AfterRemoteAddCallback = (set: any, get: any, setAndSync: SetAndSyncCallback, stateKey: string, item: SyncedRecord) => void;
23
24
  type MissingRemoteRecordDuringUpdateCallback = (strategy: MissingRemoteRecordStrategy, item: SyncedRecord) => void;
25
+ type ApiName = string;
26
+ type LocalId = string;
27
+ type ISODateString = string;
24
28
  interface SyncOptions {
25
29
  syncInterval?: number;
30
+ apiConfig?: Record<ApiName, ApiConfig>;
26
31
  logger?: any;
27
32
  minLogLevel?: LogLevel;
28
33
  onAfterRemoteAdd?: AfterRemoteAddCallback;
@@ -30,17 +35,20 @@ interface SyncOptions {
30
35
  onMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
31
36
  conflictResolutionStrategy?: ConflictResolutionStrategy;
32
37
  }
38
+ type ApiConfig = {
39
+ pullInterval?: number;
40
+ };
33
41
  type SyncState = {
34
42
  syncState: {
35
43
  status: 'disabled' | 'hydrating' | 'syncing' | 'idle';
36
44
  firstLoadDone: boolean;
37
45
  pendingChanges: PendingChange[];
38
- lastPulled: Record<string, string>;
46
+ lastUpdatedAt: Record<ApiName, ISODateString>;
47
+ lastPulled: Record<ApiName, ISODateString>;
39
48
  error?: Error;
40
- conflicts?: Record<string, Conflict>;
49
+ conflicts?: Record<LocalId, Conflict>;
41
50
  };
42
51
  };
43
- type SetAndSyncCallback = (state: any) => void;
44
52
  type SyncedStateCreator<TStore> = (set: any, get: any, setAndSyncOnce: SetAndSyncCallback) => TStore;
45
53
  interface PendingChange {
46
54
  action: SyncAction;
@@ -50,6 +58,7 @@ interface PendingChange {
50
58
  version: number;
51
59
  changes?: any;
52
60
  before?: any;
61
+ after?: any;
53
62
  }
54
63
  type UseStoreWithSync<T> = UseBoundStore<StoreApi<T & SyncState> & {
55
64
  sync: {
package/dist/index.d.ts CHANGED
@@ -12,17 +12,22 @@ type SyncedRecord = {
12
12
  };
13
13
  interface ApiFunctions {
14
14
  add: (item: any) => Promise<any | undefined>;
15
- update: (id: any, changes: any) => Promise<boolean>;
15
+ update: (id: any, changes: any, item: any) => Promise<boolean>;
16
16
  remove: (id: any) => Promise<void>;
17
17
  list: (lastUpdatedAt: Date) => Promise<any[]>;
18
18
  firstLoad?: (lastId: any) => Promise<any[]>;
19
19
  }
20
20
  type MissingRemoteRecordStrategy = 'ignore' | 'delete-local-record' | 'insert-remote-record';
21
21
  type ConflictResolutionStrategy = 'local-wins' | 'remote-wins' | 'try-shallow-merge';
22
+ type SetAndSyncCallback = (state: any) => void;
22
23
  type AfterRemoteAddCallback = (set: any, get: any, setAndSync: SetAndSyncCallback, stateKey: string, item: SyncedRecord) => void;
23
24
  type MissingRemoteRecordDuringUpdateCallback = (strategy: MissingRemoteRecordStrategy, item: SyncedRecord) => void;
25
+ type ApiName = string;
26
+ type LocalId = string;
27
+ type ISODateString = string;
24
28
  interface SyncOptions {
25
29
  syncInterval?: number;
30
+ apiConfig?: Record<ApiName, ApiConfig>;
26
31
  logger?: any;
27
32
  minLogLevel?: LogLevel;
28
33
  onAfterRemoteAdd?: AfterRemoteAddCallback;
@@ -30,17 +35,20 @@ interface SyncOptions {
30
35
  onMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
31
36
  conflictResolutionStrategy?: ConflictResolutionStrategy;
32
37
  }
38
+ type ApiConfig = {
39
+ pullInterval?: number;
40
+ };
33
41
  type SyncState = {
34
42
  syncState: {
35
43
  status: 'disabled' | 'hydrating' | 'syncing' | 'idle';
36
44
  firstLoadDone: boolean;
37
45
  pendingChanges: PendingChange[];
38
- lastPulled: Record<string, string>;
46
+ lastUpdatedAt: Record<ApiName, ISODateString>;
47
+ lastPulled: Record<ApiName, ISODateString>;
39
48
  error?: Error;
40
- conflicts?: Record<string, Conflict>;
49
+ conflicts?: Record<LocalId, Conflict>;
41
50
  };
42
51
  };
43
- type SetAndSyncCallback = (state: any) => void;
44
52
  type SyncedStateCreator<TStore> = (set: any, get: any, setAndSyncOnce: SetAndSyncCallback) => TStore;
45
53
  interface PendingChange {
46
54
  action: SyncAction;
@@ -50,6 +58,7 @@ interface PendingChange {
50
58
  version: number;
51
59
  changes?: any;
52
60
  before?: any;
61
+ after?: any;
53
62
  }
54
63
  type UseStoreWithSync<T> = UseBoundStore<StoreApi<T & SyncState> & {
55
64
  sync: {
package/dist/index.js CHANGED
@@ -90,12 +90,14 @@ function removeFromPendingChanges(set, localId, stateKey) {
90
90
  }
91
91
  function tryAddToPendingChanges(pendingChanges, stateKey, changes) {
92
92
  for (const [localId, change] of changes) {
93
- let omittedItem = omitSyncFields(change.changes);
93
+ let omittedChanges = omitSyncFields(change.changes);
94
+ const omittedCurrentItem = omitSyncFields(change.currentItem);
95
+ const omittedUpdatedItem = omitSyncFields(change.updatedItem);
94
96
  const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);
95
- const hasChanges = Object.keys(omittedItem).length > 0;
97
+ const hasChanges = Object.keys(omittedChanges).length > 0;
96
98
  const action = change.updatedItem === null ? "remove" /* Remove */ : change.currentItem === null ? "create" /* Create */ : "update" /* Update */;
97
99
  if (action === "update" /* Update */ && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {
98
- omittedItem = omitSyncFields(change.updatedItem);
100
+ omittedChanges = omittedUpdatedItem;
99
101
  }
100
102
  if (queueItem) {
101
103
  if (queueItem.action === "remove" /* Remove */) {
@@ -105,10 +107,20 @@ function tryAddToPendingChanges(pendingChanges, stateKey, changes) {
105
107
  if (action === "remove" /* Remove */) {
106
108
  queueItem.action = "remove" /* Remove */;
107
109
  } else if (hasChanges) {
108
- queueItem.changes = { ...queueItem.changes, ...omittedItem };
110
+ queueItem.changes = { ...queueItem.changes, ...omittedChanges };
111
+ queueItem.after = { ...queueItem.after, ...omittedUpdatedItem };
109
112
  }
110
113
  } else if (action === "remove" /* Remove */ || hasChanges) {
111
- pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem, before: omitSyncFields(change.currentItem) });
114
+ pendingChanges.push({
115
+ action,
116
+ stateKey,
117
+ localId,
118
+ id: change.id,
119
+ version: 1,
120
+ changes: omittedChanges,
121
+ before: omittedCurrentItem,
122
+ after: omittedUpdatedItem
123
+ });
112
124
  }
113
125
  }
114
126
  }
@@ -151,6 +163,14 @@ function findApi(stateKey, syncApi) {
151
163
  }
152
164
  return api;
153
165
  }
166
+ function isPullIntervalNow(stateKey, apiConfig, lastPulled) {
167
+ const config = apiConfig[stateKey];
168
+ if (!config || !config.pullInterval) {
169
+ return true;
170
+ }
171
+ const lastPulledTime = new Date(lastPulled[stateKey] ?? 0).getTime();
172
+ return Date.now() > lastPulledTime + config.pullInterval;
173
+ }
154
174
  function findChanges(current, updated) {
155
175
  const currentMap = /* @__PURE__ */ new Map();
156
176
  for (const item of current) {
@@ -232,12 +252,11 @@ function resolveConflict(set, localId, keepLocalFields) {
232
252
 
233
253
  // src/pull.ts
234
254
  async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy) {
235
- const lastPulled = get().syncState.lastPulled || {};
236
- const lastPulledAt = new Date(lastPulled[stateKey] || /* @__PURE__ */ new Date(0));
237
- logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastPulledAt.toISOString()}`);
238
- const serverData = await api.list(lastPulledAt);
255
+ const lastUpdatedAt = get().syncState.lastUpdatedAt || {};
256
+ let lastUpdatedAtDate = new Date(lastUpdatedAt[stateKey] || /* @__PURE__ */ new Date(0));
257
+ logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastUpdatedAtDate.toISOString()}`);
258
+ const serverData = await api.list(lastUpdatedAtDate);
239
259
  if (!serverData?.length) return;
240
- let newest = lastPulledAt;
241
260
  set((state) => {
242
261
  let pendingChanges = [...state.syncState.pendingChanges];
243
262
  const conflicts = { ...state.syncState.conflicts };
@@ -247,7 +266,7 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
247
266
  const pendingRemovalById = new Set(pendingChanges.filter((p) => p.stateKey === stateKey && p.action === "remove" /* Remove */).map((p) => p.id));
248
267
  for (const remote of serverData) {
249
268
  const remoteUpdated = new Date(remote.updated_at);
250
- if (remoteUpdated > newest) newest = remoteUpdated;
269
+ if (remoteUpdated > lastUpdatedAtDate) lastUpdatedAtDate = remoteUpdated;
251
270
  if (pendingRemovalById.has(remote.id)) {
252
271
  logger.debug(`[zync] pull:skip-pending-remove stateKey=${stateKey} id=${remote.id}`);
253
272
  continue;
@@ -310,9 +329,9 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
310
329
  ...state.syncState || {},
311
330
  pendingChanges,
312
331
  conflicts: hasKeysOrUndefined(conflicts),
313
- lastPulled: {
314
- ...state.syncState.lastPulled || {},
315
- [stateKey]: newest.toISOString()
332
+ lastUpdatedAt: {
333
+ ...state.syncState.lastUpdatedAt || {},
334
+ [stateKey]: lastUpdatedAtDate.toISOString()
316
335
  }
317
336
  }
318
337
  };
@@ -322,7 +341,7 @@ async function pull(set, get, stateKey, api, logger, conflictResolutionStrategy)
322
341
  // src/push.ts
323
342
  async function pushOne(set, get, change, api, logger, setAndQueueToSync, missingStrategy, onMissingRemoteRecordDuringUpdate, onAfterRemoteAdd) {
324
343
  logger.debug(`[zync] push:attempt action=${change.action} stateKey=${change.stateKey} localId=${change.localId}`);
325
- const { action, stateKey, localId, id, version, changes } = change;
344
+ const { action, stateKey, localId, id, version, changes, after } = change;
326
345
  switch (action) {
327
346
  case "remove" /* Remove */:
328
347
  if (!id) {
@@ -339,7 +358,7 @@ async function pushOne(set, get, change, api, logger, setAndQueueToSync, missing
339
358
  logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);
340
359
  return;
341
360
  }
342
- const exists = await api.update(id, changes);
361
+ const exists = await api.update(id, changes, after);
343
362
  if (exists) {
344
363
  logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);
345
364
  if (samePendingVersion(get, stateKey, localId, version)) {
@@ -431,7 +450,7 @@ async function startFirstLoad(set, syncApi, logger) {
431
450
  set((state) => {
432
451
  const local = state[stateKey] || [];
433
452
  const localById = new Map(local.filter((l) => l.id).map((l) => [l.id, l]));
434
- let newest = new Date(state.syncState.lastPulled[stateKey] || 0);
453
+ let newest = new Date(state.syncState.lastUpdatedAt[stateKey] || 0);
435
454
  const next = [...local];
436
455
  for (const remote of batch) {
437
456
  const remoteUpdated = new Date(remote.updated_at || 0);
@@ -458,8 +477,8 @@ async function startFirstLoad(set, syncApi, logger) {
458
477
  [stateKey]: next,
459
478
  syncState: {
460
479
  ...state.syncState || {},
461
- lastPulled: {
462
- ...state.syncState.lastPulled || {},
480
+ lastUpdatedAt: {
481
+ ...state.syncState.lastUpdatedAt || {},
463
482
  [stateKey]: newest.toISOString()
464
483
  }
465
484
  }
@@ -583,6 +602,7 @@ function createWithSync(stateCreator, persistOptions, syncApi, syncOptions = {})
583
602
  }
584
603
  function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}) {
585
604
  const syncInterval = syncOptions.syncInterval ?? DEFAULT_SYNC_INTERVAL_MILLIS;
605
+ const apiConfig = syncOptions.apiConfig ?? {};
586
606
  const missingStrategy = syncOptions.missingRemoteRecordDuringUpdateStrategy ?? DEFAULT_MISSING_REMOTE_RECORD_STRATEGY;
587
607
  const conflictResolutionStrategy = syncOptions.conflictResolutionStrategy ?? DEFAULT_CONFLICT_RESOLUTION_STRATEGY;
588
608
  const logger = newLogger(syncOptions.logger ?? DEFAULT_LOGGER, syncOptions.minLogLevel ?? DEFAULT_MIN_LOG_LEVEL);
@@ -609,6 +629,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
609
629
  syncState: {
610
630
  firstLoadDone: syncState.firstLoadDone,
611
631
  pendingChanges: syncState.pendingChanges,
632
+ lastUpdatedAt: syncState.lastUpdatedAt,
612
633
  lastPulled: syncState.lastPulled,
613
634
  conflicts: syncState.conflicts
614
635
  }
@@ -637,10 +658,13 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
637
658
  }
638
659
  }));
639
660
  let firstSyncError;
661
+ const lastPulled = { ...get().syncState.lastPulled };
640
662
  for (const stateKey of Object.keys(syncApi)) {
641
663
  try {
664
+ if (!isPullIntervalNow(stateKey, apiConfig, lastPulled)) continue;
642
665
  const api = findApi(stateKey, syncApi);
643
666
  await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);
667
+ lastPulled[stateKey] = (/* @__PURE__ */ new Date()).toISOString();
644
668
  } catch (err) {
645
669
  firstSyncError = firstSyncError ?? err;
646
670
  logger.error(`[zync] pull:error stateKey=${stateKey}`, err);
@@ -671,7 +695,8 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
671
695
  syncState: {
672
696
  ...state.syncState || {},
673
697
  status: "idle",
674
- error: firstSyncError
698
+ error: firstSyncError,
699
+ lastPulled
675
700
  }
676
701
  }));
677
702
  }
@@ -757,6 +782,7 @@ function persistWithSync(stateCreator, persistOptions, syncApi, syncOptions = {}
757
782
  conflicts: void 0,
758
783
  firstLoadDone: false,
759
784
  pendingChanges: [],
785
+ lastUpdatedAt: {},
760
786
  lastPulled: {}
761
787
  }
762
788
  };
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/firstLoad.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, findChanges, tryAddToPendingChanges, tryUpdateConflicts, resolveConflict, sleep } from './helpers';\nimport {\n type ApiFunctions,\n type SyncOptions,\n type SyncState,\n type SyncedStateCreator,\n type PendingChange,\n type UseStoreWithSync,\n type MissingRemoteRecordStrategy,\n type ConflictResolutionStrategy,\n} from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\nimport { startFirstLoad } from './firstLoad';\n\nexport { createIndexedDB } from './indexedDBStorage';\nexport { createLocalId, changeKeysTo, changeKeysFrom } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n Create = 'create',\n Update = 'update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 2000;\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 = 'try-shallow-merge';\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 conflicts: syncState.conflicts,\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 syncTimerStarted = false;\n\n async function syncOnce() {\n if (get().syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let firstSyncError: 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 firstSyncError = firstSyncError ?? (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 firstSyncError = firstSyncError ?? (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: firstSyncError,\n } as SyncState['syncState'],\n }));\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 }\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 tryAddToPendingChanges(pendingChanges, stateKey, changes);\n });\n\n // Prevent stale conflicts reporting old values to user\n const conflicts = tryUpdateConflicts(pendingChanges, state.syncState.conflicts);\n\n return {\n ...partial,\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n conflicts,\n } as SyncState['syncState'],\n };\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: enabled ? 'idle' : 'disabled',\n },\n }));\n\n startSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function startSyncTimer(start: boolean) {\n if (start) {\n tryStart(); // Unawaited async\n } else {\n syncTimerStarted = false;\n }\n }\n\n async function tryStart() {\n if (syncTimerStarted) return;\n syncTimerStarted = true;\n\n while (true) {\n if (!syncTimerStarted) break;\n await syncOnce();\n await sleep(syncInterval);\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 startSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n startSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad: () => startFirstLoad(set, syncApi, logger),\n resolveConflict: (localId: string, keepLocal: boolean) => resolveConflict(set, localId, keepLocal),\n };\n\n const userState = stateCreator(set, get, setAndQueueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n conflicts: undefined,\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, Conflict, FieldConflict, PendingChange, SyncState } from './types';\n\nconst SYNC_FIELDS = ['_localId', 'updated_at', 'deleted'] as const;\n\nexport function createLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function changeKeysTo(input: any | any[], toIdKey: string, toUpdatedAtKey: string, toDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { id, updated_at, deleted, ...rest } = item;\n return {\n [toIdKey]: id,\n [toUpdatedAtKey]: updated_at,\n [toDeletedKey]: deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function changeKeysFrom(input: any | any[], fromIdKey: string, fromUpdatedAtKey: string, fromDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;\n return {\n id,\n updated_at,\n deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.Create:\n return 1;\n case SyncAction.Update:\n return 2;\n case SyncAction.Remove:\n return 3;\n }\n}\n\nexport function omitSyncFields(item: any) {\n const result = { ...item };\n for (const k of SYNC_FIELDS) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const pending: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = pending.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 tryAddToPendingChanges(pendingChanges: PendingChange[], stateKey: string, changes: Map<string, ChangeRecord>) {\n for (const [localId, change] of changes) {\n let omittedItem = omitSyncFields(change.changes);\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n const hasChanges = Object.keys(omittedItem).length > 0;\n const action = change.updatedItem === null ? SyncAction.Remove : change.currentItem === null ? SyncAction.Create : SyncAction.Update;\n\n if (action === SyncAction.Update && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {\n // Here when insert-remote-record swaps local remotely deleted item with a fresh copy to push up\n omittedItem = omitSyncFields(change.updatedItem);\n }\n\n if (queueItem) {\n if (queueItem.action === SyncAction.Remove) {\n // Once a Remove is queued, it stays a Remove\n continue;\n }\n\n queueItem.version += 1;\n\n if (action === SyncAction.Remove) {\n queueItem.action = SyncAction.Remove;\n } else if (hasChanges) {\n // Never change the action here, it stays Create or Update and is removed when synced\n queueItem.changes = { ...queueItem.changes, ...omittedItem };\n }\n } else if (action === SyncAction.Remove || hasChanges) {\n pendingChanges.push({ action, stateKey, localId, id: change.id, version: 1, changes: omittedItem, before: omitSyncFields(change.currentItem) });\n }\n }\n}\n\nexport function setPendingChangeToUpdate(get: any, stateKey: string, localId: string, id?: any) {\n // id is optional as the user may client assign the id, but not return it from the api\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.action = SyncAction.Update;\n if (id) change.id = id;\n }\n}\n\nexport function setPendingChangeBefore(get: any, stateKey: string, localId: string, before: any) {\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.before = { ...change.before, ...before };\n }\n}\n\nexport function tryUpdateConflicts(pendingChanges: PendingChange[], conflicts?: Record<string, Conflict>): Record<string, Conflict> | undefined {\n if (!conflicts) return conflicts;\n\n const newConflicts = { ...conflicts };\n\n for (const change of pendingChanges) {\n const conflict = newConflicts[change.localId];\n if (conflict && change.changes) {\n // Loop changed fields and update their old possibly stale value to the current local value\n const newFields = conflict.fields.map((f) => {\n if (f.key in change.changes) {\n return { ...f, localValue: change.changes[f.key] } as FieldConflict;\n }\n return f;\n });\n\n newConflicts[change.localId] = { stateKey: conflict.stateKey, fields: newFields };\n }\n }\n\n return newConflicts;\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) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n return api;\n}\n\ntype ChangeRecord = {\n currentItem?: any;\n updatedItem?: any;\n changes: any;\n id?: 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 update of updated) {\n const item = { ...update };\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 // Changes\n changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff, id: curr.id ?? item.id });\n }\n } else {\n // Addition\n changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item, id: item.id });\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, id: curr.id });\n }\n }\n\n return changesMap;\n}\n\nexport function hasKeysOrUndefined(obj: any): any {\n return Object.keys(obj).length === 0 ? undefined : obj;\n}\n\nexport function hasConflicts(get: any, localId: string): boolean {\n const state = get() as SyncState;\n if (state.syncState.conflicts) {\n return !!state.syncState.conflicts[localId];\n }\n return false;\n}\n\nexport function resolveConflict(set: any, localId: string, keepLocalFields: boolean) {\n set((state: any) => {\n const syncState: SyncState['syncState'] = state.syncState || {};\n const conflicts: Record<string, Conflict> = syncState.conflicts || {};\n const conflict = conflicts[localId];\n if (conflict) {\n const items = state[conflict.stateKey];\n const item = items.find((i: any) => i._localId === localId);\n if (!item) {\n return state;\n }\n\n const resolved: any = { ...item };\n let pendingChanges = [...syncState.pendingChanges];\n\n if (!keepLocalFields) {\n // Use remote value(s)\n for (const field of conflict.fields) {\n resolved[field.key] = field.remoteValue;\n }\n\n // Remove resolved pending change\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === conflict.stateKey && p.localId === localId));\n }\n\n // Replace with resolved item\n const nextItems = items.map((i: any) => (i._localId === localId ? resolved : i));\n const nextConflicts = { ...conflicts };\n delete nextConflicts[localId];\n\n return {\n [conflict.stateKey]: nextItems,\n syncState: {\n ...syncState,\n pendingChanges,\n conflicts: hasKeysOrUndefined(nextConflicts),\n },\n };\n }\n return state;\n });\n}\n","import { type ApiFunctions, type FieldConflict, type ConflictResolutionStrategy, type SyncedRecord, type PendingChange } from './types';\nimport { SyncAction } from './index';\nimport { createLocalId, hasKeysOrUndefined } 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\n set((state: any) => {\n let pendingChanges = [...(state.syncState.pendingChanges as PendingChange[])];\n const conflicts = { ...state.syncState.conflicts };\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items when 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 logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n\n switch (conflictResolutionStrategy) {\n case 'local-wins':\n // Ignore remote changes, keep local\n break;\n\n case 'remote-wins': {\n // Ignore local changes, keep remote\n const merged = { ...remote, _localId: localItem._localId };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Remove pending change so it isn't pushed after pull\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === stateKey && p.localId === localItem._localId));\n break;\n }\n\n case 'try-shallow-merge': {\n // List fields that local and remote have changed\n const changes = pendingChange.changes || {};\n const before = pendingChange.before || {};\n const fields: FieldConflict[] = Object.entries(changes)\n .filter(([k, localValue]) => k in before && k in remote && before[k] !== remote[k] && localValue !== remote[k])\n .map(([key, localValue]) => ({ key, localValue, remoteValue: remote[key] }));\n\n if (fields.length > 0) {\n logger.warn(`[zync] pull:${conflictResolutionStrategy}:conflicts-found`, JSON.stringify(fields, null, 4));\n conflicts[localItem._localId] = { stateKey, fields };\n } else {\n // No conflicts, merge remote into local but only preserve fields that were\n // actually changed locally\n const localChangedKeys = Object.keys(changes);\n const preservedLocal: any = { _localId: localItem._localId };\n for (const k of localChangedKeys) {\n if (k in localItem) preservedLocal[k] = localItem[k];\n }\n\n const merged = { ...remote, ...preservedLocal };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Merge now resolved, drop pending and conflict\n delete conflicts[localItem._localId];\n }\n break;\n }\n }\n } else {\n // No pending changes, merge remote into local\n const merged = { ...localItem, ...remote };\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: createLocalId() }];\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 pendingChanges,\n conflicts: hasKeysOrUndefined(conflicts),\n lastPulled: {\n ...(state.syncState.lastPulled || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n}\n","import { hasConflicts, removeFromPendingChanges, samePendingVersion, setPendingChangeBefore, setPendingChangeToUpdate } from './helpers';\nimport { createLocalId, 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\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, changes } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success stateKey=${stateKey} localId=${localId} id=${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.Update: {\n if (hasConflicts(get, change.localId)) {\n logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);\n return;\n }\n\n const exists = await api.update(id, changes);\n if (exists) {\n logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure pending.before is not stale for conflict resolution\n setPendingChangeBefore(get, stateKey, localId, changes);\n }\n return;\n } else {\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:missing-remote:no-local-item stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\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 logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'insert-remote-record': {\n const newItem = {\n ...item,\n _localId: createLocalId(),\n updated_at: new Date().toISOString(),\n };\n\n // replace old with modified and queue Create\n setAndQueueToSync((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? newItem : i)),\n }));\n\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${newItem.id}`);\n break;\n }\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-strategy 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);\n }\n break;\n }\n\n case SyncAction.Create: {\n const result = await api.add(changes);\n if (result) {\n logger.debug(`[zync] push:create:success stateKey=${stateKey} localId=${localId} id=${id}`);\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\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure any pendingChanges entry has id and is now an Update\n setPendingChangeToUpdate(get, stateKey, localId, result.id);\n }\n\n const finalItem = { ...changes, ...result, _localId: localId };\n\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, finalItem);\n } else {\n logger.warn(`[zync] push:create:no-result stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import { createLocalId } from './helpers';\nimport type { Logger } from './logger';\nimport type { ApiFunctions } from './types';\n\nexport async function startFirstLoad(set: any, syncApi: Record<string, ApiFunctions>, logger: Logger) {\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 = syncApi[stateKey];\n if (!api?.firstLoad) {\n logger.error(`[zync] firstLoad:no-api-function stateKey=${stateKey}`);\n continue;\n }\n\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: createLocalId(),\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 if (lastId !== undefined && lastId === batch[batch.length - 1].id) {\n throw new Error(`Duplicate records downloaded, stopping to prevent infinite loop`);\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","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDB(dbName: string, storeName: string) {\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;;;ACtBA,IAAM,cAAc,CAAC,YAAY,cAAc,SAAS;AAEjD,SAAS,gBAAwB;AACpC,SAAO,OAAO,WAAW;AAC7B;AAEO,SAAS,MAAM,IAA2B;AAC7C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAC3D;AAEO,SAAS,aAAa,OAAoB,SAAiB,gBAAwB,cAAsB;AAC5G,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,QAAM,UAAU,UAAU,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS;AACrD,UAAM,EAAE,IAAI,YAAY,SAAS,GAAG,KAAK,IAAI;AAC7C,WAAO;AAAA,MACH,CAAC,OAAO,GAAG;AAAA,MACX,CAAC,cAAc,GAAG;AAAA,MAClB,CAAC,YAAY,GAAG;AAAA,MAChB,GAAG;AAAA,IACP;AAAA,EACJ,CAAC;AACD,SAAO,UAAU,SAAS,OAAO,CAAC;AACtC;AAEO,SAAS,eAAe,OAAoB,WAAmB,kBAA0B,gBAAwB;AACpH,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,QAAM,UAAU,UAAU,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS;AACrD,UAAM,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC,gBAAgB,GAAG,YAAY,CAAC,cAAc,GAAG,SAAS,GAAG,KAAK,IAAI;AAChG,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACP;AAAA,EACJ,CAAC;AACD,SAAO,UAAU,SAAS,OAAO,CAAC;AACtC;AAEO,SAAS,SAAS,GAAuB;AAC5C,UAAQ,GAAG;AAAA,IACP;AACI,aAAO;AAAA,IACX;AACI,aAAO;AAAA,IACX;AACI,aAAO;AAAA,EACf;AACJ;AAEO,SAAS,eAAe,MAAW;AACtC,QAAM,SAAS,EAAE,GAAG,KAAK;AACzB,aAAW,KAAK,YAAa,QAAO,OAAO,CAAC;AAC5C,SAAO;AACX;AAEO,SAAS,mBAAmB,KAAU,UAAkB,SAAiB,SAA0B;AACtG,QAAM,UAA2B,IAAI,EAAE,UAAU,kBAAkB,CAAC;AACpE,QAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,aAAa,QAAQ;AACtF,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,uBAAuB,gBAAiC,UAAkB,SAAoC;AAC1H,aAAW,CAAC,SAAS,MAAM,KAAK,SAAS;AACrC,QAAI,cAAc,eAAe,OAAO,OAAO;AAC/C,UAAM,YAAY,eAAe,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,aAAa,QAAQ;AAC7F,UAAM,aAAa,OAAO,KAAK,WAAW,EAAE,SAAS;AACrD,UAAM,SAAS,OAAO,gBAAgB,+BAA2B,OAAO,gBAAgB;AAExF,QAAI,oCAAgC,OAAO,eAAe,OAAO,eAAe,OAAO,YAAY,aAAa,OAAO,YAAY,UAAU;AAEzI,oBAAc,eAAe,OAAO,WAAW;AAAA,IACnD;AAEA,QAAI,WAAW;AACX,UAAI,UAAU,kCAA8B;AAExC;AAAA,MACJ;AAEA,gBAAU,WAAW;AAErB,UAAI,kCAA8B;AAC9B,kBAAU;AAAA,MACd,WAAW,YAAY;AAEnB,kBAAU,UAAU,EAAE,GAAG,UAAU,SAAS,GAAG,YAAY;AAAA,MAC/D;AAAA,IACJ,WAAW,oCAAgC,YAAY;AACnD,qBAAe,KAAK,EAAE,QAAQ,UAAU,SAAS,IAAI,OAAO,IAAI,SAAS,GAAG,SAAS,aAAa,QAAQ,eAAe,OAAO,WAAW,EAAE,CAAC;AAAA,IAClJ;AAAA,EACJ;AACJ;AAEO,SAAS,yBAAyB,KAAU,UAAkB,SAAiB,IAAU;AAE5F,QAAM,iBAAkC,IAAI,EAAE,UAAU,kBAAkB,CAAC;AAC3E,QAAM,SAAS,eAAe,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,EAAE,YAAY,OAAO;AAC1F,MAAI,QAAQ;AACR,WAAO;AACP,QAAI,GAAI,QAAO,KAAK;AAAA,EACxB;AACJ;AAEO,SAAS,uBAAuB,KAAU,UAAkB,SAAiB,QAAa;AAC7F,QAAM,iBAAkC,IAAI,EAAE,UAAU,kBAAkB,CAAC;AAC3E,QAAM,SAAS,eAAe,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,EAAE,YAAY,OAAO;AAC1F,MAAI,QAAQ;AACR,WAAO,SAAS,EAAE,GAAG,OAAO,QAAQ,GAAG,OAAO;AAAA,EAClD;AACJ;AAEO,SAAS,mBAAmB,gBAAiC,WAA4E;AAC5I,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,eAAe,EAAE,GAAG,UAAU;AAEpC,aAAW,UAAU,gBAAgB;AACjC,UAAM,WAAW,aAAa,OAAO,OAAO;AAC5C,QAAI,YAAY,OAAO,SAAS;AAE5B,YAAM,YAAY,SAAS,OAAO,IAAI,CAAC,MAAM;AACzC,YAAI,EAAE,OAAO,OAAO,SAAS;AACzB,iBAAO,EAAE,GAAG,GAAG,YAAY,OAAO,QAAQ,EAAE,GAAG,EAAE;AAAA,QACrD;AACA,eAAO;AAAA,MACX,CAAC;AAED,mBAAa,OAAO,OAAO,IAAI,EAAE,UAAU,SAAS,UAAU,QAAQ,UAAU;AAAA,IACpF;AAAA,EACJ;AAEA,SAAO;AACX;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,MAAM;AAC7D,UAAM,IAAI,MAAM,0CAA0C,QAAQ,GAAG;AAAA,EACzE;AACA,SAAO;AACX;AAgBO,SAAS,YAAY,SAAgB,SAA2C;AACnF,QAAM,aAAa,oBAAI,IAAiB;AACxC,aAAW,QAAQ,SAAS;AACxB,QAAI,QAAQ,KAAK,UAAU;AACvB,iBAAW,IAAI,KAAK,UAAU,EAAE,GAAG,KAAK,CAAC;AAAA,IAC7C;AAAA,EACJ;AAEA,QAAM,aAAa,oBAAI,IAA0B;AAGjD,aAAW,UAAU,SAAS;AAC1B,UAAM,OAAO,EAAE,GAAG,OAAO;AACzB,QAAI,QAAQ,KAAK,UAAU;AACvB,YAAM,OAAO,WAAW,IAAI,KAAK,QAAQ;AACzC,UAAI,MAAM;AACN,cAAM,OAAY,CAAC;AACnB,mBAAW,OAAO,MAAM;AACpB,cAAI,QAAQ,cAAc,KAAK,GAAG,MAAM,KAAK,GAAG,GAAG;AAC/C,iBAAK,GAAG,IAAI,KAAK,GAAG;AAAA,UACxB;AAAA,QACJ;AACA,YAAI,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAE9B,qBAAW,IAAI,KAAK,UAAU,EAAE,aAAa,MAAM,aAAa,MAAM,SAAS,MAAM,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,QACjH;AAAA,MACJ,OAAO;AAEH,mBAAW,IAAI,KAAK,UAAU,EAAE,aAAa,MAAM,aAAa,MAAM,SAAS,MAAM,IAAI,KAAK,GAAG,CAAC;AAAA,MACtG;AAAA,IACJ;AAAA,EACJ;AAGA,aAAW,CAAC,SAAS,IAAI,KAAK,YAAY;AACtC,QAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,KAAK,EAAE,aAAa,OAAO,GAAG;AACnD,iBAAW,IAAI,SAAS,EAAE,aAAa,MAAM,aAAa,MAAM,SAAS,MAAM,IAAI,KAAK,GAAG,CAAC;AAAA,IAChG;AAAA,EACJ;AAEA,SAAO;AACX;AAEO,SAAS,mBAAmB,KAAe;AAC9C,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW,IAAI,SAAY;AACvD;AAEO,SAAS,aAAa,KAAU,SAA0B;AAC7D,QAAM,QAAQ,IAAI;AAClB,MAAI,MAAM,UAAU,WAAW;AAC3B,WAAO,CAAC,CAAC,MAAM,UAAU,UAAU,OAAO;AAAA,EAC9C;AACA,SAAO;AACX;AAEO,SAAS,gBAAgB,KAAU,SAAiB,iBAA0B;AACjF,MAAI,CAAC,UAAe;AAChB,UAAM,YAAoC,MAAM,aAAa,CAAC;AAC9D,UAAM,YAAsC,UAAU,aAAa,CAAC;AACpE,UAAM,WAAW,UAAU,OAAO;AAClC,QAAI,UAAU;AACV,YAAM,QAAQ,MAAM,SAAS,QAAQ;AACrC,YAAM,OAAO,MAAM,KAAK,CAAC,MAAW,EAAE,aAAa,OAAO;AAC1D,UAAI,CAAC,MAAM;AACP,eAAO;AAAA,MACX;AAEA,YAAM,WAAgB,EAAE,GAAG,KAAK;AAChC,UAAI,iBAAiB,CAAC,GAAG,UAAU,cAAc;AAEjD,UAAI,CAAC,iBAAiB;AAElB,mBAAW,SAAS,SAAS,QAAQ;AACjC,mBAAS,MAAM,GAAG,IAAI,MAAM;AAAA,QAChC;AAGA,yBAAiB,eAAe,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,SAAS,YAAY,EAAE,YAAY,QAAQ;AAAA,MAC9G;AAGA,YAAM,YAAY,MAAM,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,WAAW,CAAE;AAC/E,YAAM,gBAAgB,EAAE,GAAG,UAAU;AACrC,aAAO,cAAc,OAAO;AAE5B,aAAO;AAAA,QACH,CAAC,SAAS,QAAQ,GAAG;AAAA,QACrB,WAAW;AAAA,UACP,GAAG;AAAA,UACH;AAAA,UACA,WAAW,mBAAmB,aAAa;AAAA,QAC/C;AAAA,MACJ;AAAA,IACJ;AACA,WAAO;AAAA,EACX,CAAC;AACL;;;ACxQA,eAAsB,KAAK,KAAU,KAAU,UAAkB,KAAmB,QAAgB,4BAAwD;AACxJ,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;AAEb,MAAI,CAAC,UAAe;AAChB,QAAI,iBAAiB,CAAC,GAAI,MAAM,UAAU,cAAkC;AAC5E,UAAM,YAAY,EAAE,GAAG,MAAM,UAAU,UAAU;AACjD,UAAM,aAAoB,MAAM,QAAQ,KAAK,CAAC;AAC9C,QAAI,YAAY,CAAC,GAAG,UAAU;AAE9B,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,UAAI,WAAW;AACX,cAAM,gBAAgB,eAAe,KAAK,CAAC,MAAW,EAAE,aAAa,YAAY,EAAE,YAAY,UAAU,QAAQ;AACjH,YAAI,eAAe;AACf,iBAAO,MAAM,iCAAiC,0BAA0B,aAAa,QAAQ,OAAO,OAAO,EAAE,EAAE;AAE/G,kBAAQ,4BAA4B;AAAA,YAChC,KAAK;AAED;AAAA,YAEJ,KAAK,eAAe;AAEhB,oBAAM,SAAS,EAAE,GAAG,QAAQ,UAAU,UAAU,SAAS;AACzD,0BAAY,UAAU,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,WAAW,SAAS,CAAE;AAEtF,+BAAiB,eAAe,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,YAAY,EAAE,YAAY,UAAU,SAAS;AAC5G;AAAA,YACJ;AAAA,YAEA,KAAK,qBAAqB;AAEtB,oBAAM,UAAU,cAAc,WAAW,CAAC;AAC1C,oBAAM,SAAS,cAAc,UAAU,CAAC;AACxC,oBAAM,SAA0B,OAAO,QAAQ,OAAO,EACjD,OAAO,CAAC,CAAC,GAAG,UAAU,MAAM,KAAK,UAAU,KAAK,UAAU,OAAO,CAAC,MAAM,OAAO,CAAC,KAAK,eAAe,OAAO,CAAC,CAAC,EAC7G,IAAI,CAAC,CAAC,KAAK,UAAU,OAAO,EAAE,KAAK,YAAY,aAAa,OAAO,GAAG,EAAE,EAAE;AAE/E,kBAAI,OAAO,SAAS,GAAG;AACnB,uBAAO,KAAK,eAAe,0BAA0B,oBAAoB,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACxG,0BAAU,UAAU,QAAQ,IAAI,EAAE,UAAU,OAAO;AAAA,cACvD,OAAO;AAGH,sBAAM,mBAAmB,OAAO,KAAK,OAAO;AAC5C,sBAAM,iBAAsB,EAAE,UAAU,UAAU,SAAS;AAC3D,2BAAW,KAAK,kBAAkB;AAC9B,sBAAI,KAAK,UAAW,gBAAe,CAAC,IAAI,UAAU,CAAC;AAAA,gBACvD;AAEA,sBAAM,SAAS,EAAE,GAAG,QAAQ,GAAG,eAAe;AAC9C,4BAAY,UAAU,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,WAAW,SAAS,CAAE;AAEtF,uBAAO,UAAU,UAAU,QAAQ;AAAA,cACvC;AACA;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ,OAAO;AAEH,gBAAM,SAAS,EAAE,GAAG,WAAW,GAAG,OAAO;AACzC,sBAAY,UAAU,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,WAAW,SAAS,CAAE;AACtF,iBAAO,MAAM,qCAAqC,QAAQ,OAAO,OAAO,EAAE,EAAE;AAAA,QAChF;AAAA,MACJ,OAAO;AAEH,oBAAY,CAAC,GAAG,WAAW,EAAE,GAAG,QAAQ,UAAU,cAAc,EAAE,CAAC;AACnE,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;AAAA,QACA,WAAW,mBAAmB,SAAS;AAAA,QACvC,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;;;AC5GA,eAAsB,QAClB,KACA,KACA,QACA,KACA,QACA,mBACA,iBACA,mCACA,kBACF;AACE,SAAO,MAAM,8BAA8B,OAAO,MAAM,aAAa,OAAO,QAAQ,YAAY,OAAO,OAAO,EAAE;AAEhH,QAAM,EAAE,QAAQ,UAAU,SAAS,IAAI,SAAS,QAAQ,IAAI;AAE5D,UAAQ,QAAQ;AAAA,IACZ;AACI,UAAI,CAAC,IAAI;AACL,eAAO,KAAK,qCAAqC,QAAQ,YAAY,OAAO,EAAE;AAC9E,iCAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,MACJ;AAEA,YAAM,IAAI,OAAO,EAAE;AACnB,aAAO,MAAM,uCAAuC,QAAQ,YAAY,OAAO,OAAO,EAAE,EAAE;AAC1F,+BAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,IAEJ,4BAAwB;AACpB,UAAI,aAAa,KAAK,OAAO,OAAO,GAAG;AACnC,eAAO,KAAK,uDAAuD,QAAQ,YAAY,OAAO,OAAO,EAAE,EAAE;AACzG;AAAA,MACJ;AAEA,YAAM,SAAS,MAAM,IAAI,OAAO,IAAI,OAAO;AAC3C,UAAI,QAAQ;AACR,eAAO,MAAM,uCAAuC,QAAQ,YAAY,OAAO,OAAO,EAAE,EAAE;AAC1F,YAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,mCAAyB,KAAK,SAAS,QAAQ;AAAA,QACnD,OAAO;AAEH,iCAAuB,KAAK,UAAU,SAAS,OAAO;AAAA,QAC1D;AACA;AAAA,MACJ,OAAO;AACH,cAAM,QAAQ,IAAI;AAClB,cAAM,QAAe,MAAM,QAAQ,KAAK,CAAC;AACzC,cAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO;AACrD,YAAI,CAAC,MAAM;AACP,iBAAO,KAAK,qDAAqD,QAAQ,YAAY,OAAO,EAAE;AAC9F,mCAAyB,KAAK,SAAS,QAAQ;AAC/C;AAAA,QACJ;AAEA,gBAAQ,iBAAiB;AAAA,UACrB,KAAK;AACD,gBAAI,CAAC,OAAY;AAAA,cACb,CAAC,QAAQ,IAAI,EAAE,QAAQ,KAAK,CAAC,GAAG,OAAO,CAAC,MAAW,EAAE,aAAa,OAAO;AAAA,YAC7E,EAAE;AACF,mBAAO,MAAM,8BAA8B,eAAe,aAAa,QAAQ,OAAO,KAAK,EAAE,EAAE;AAC/F;AAAA,UAEJ,KAAK,wBAAwB;AACzB,kBAAM,UAAU;AAAA,cACZ,GAAG;AAAA,cACH,UAAU,cAAc;AAAA,cACxB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,YACvC;AAGA,8BAAkB,CAAC,OAAY;AAAA,cAC3B,CAAC,QAAQ,IAAI,EAAE,QAAQ,KAAK,CAAC,GAAG,IAAI,CAAC,MAAY,EAAE,aAAa,UAAU,UAAU,CAAE;AAAA,YAC1F,EAAE;AAEF,mBAAO,MAAM,8BAA8B,eAAe,aAAa,QAAQ,OAAO,QAAQ,EAAE,EAAE;AAClG;AAAA,UACJ;AAAA,UAEA,KAAK;AACD,mBAAO,MAAM,8BAA8B,eAAe,aAAa,QAAQ,OAAO,KAAK,EAAE,EAAE;AAC/F;AAAA,UAEJ;AACI,mBAAO,MAAM,wDAAwD,QAAQ,OAAO,KAAK,EAAE,aAAa,eAAe,EAAE;AACzH;AAAA,QACR;AAEA,iCAAyB,KAAK,SAAS,QAAQ;AAE/C,4CAAoC,iBAAiB,IAAI;AAAA,MAC7D;AACA;AAAA,IACJ;AAAA,IAEA,4BAAwB;AACpB,YAAM,SAAS,MAAM,IAAI,IAAI,OAAO;AACpC,UAAI,QAAQ;AACR,eAAO,MAAM,uCAAuC,QAAQ,YAAY,OAAO,OAAO,EAAE,EAAE;AAG1F,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;AAEF,YAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,mCAAyB,KAAK,SAAS,QAAQ;AAAA,QACnD,OAAO;AAEH,mCAAyB,KAAK,UAAU,SAAS,OAAO,EAAE;AAAA,QAC9D;AAEA,cAAM,YAAY,EAAE,GAAG,SAAS,GAAG,QAAQ,UAAU,QAAQ;AAG7D,2BAAmB,KAAK,KAAK,mBAAmB,UAAU,SAAS;AAAA,MACvE,OAAO;AACH,eAAO,KAAK,yCAAyC,QAAQ,YAAY,OAAO,OAAO,EAAE,EAAE;AAC3F,YAAI,mBAAmB,KAAK,UAAU,SAAS,OAAO,GAAG;AACrD,mCAAyB,KAAK,SAAS,QAAQ;AAAA,QACnD;AAAA,MACJ;AACA;AAAA,IACJ;AAAA,EACJ;AACJ;;;ACpIA,eAAsB,eAAe,KAAU,SAAuC,QAAgB;AAClG,MAAI;AAEJ,aAAW,YAAY,OAAO,KAAK,OAAO,GAAG;AACzC,QAAI;AACA,aAAO,KAAK,mCAAmC,QAAQ,EAAE;AAEzD,YAAM,MAAM,QAAQ,QAAQ;AAC5B,UAAI,CAAC,KAAK,WAAW;AACjB,eAAO,MAAM,6CAA6C,QAAQ,EAAE;AACpE;AAAA,MACJ;AAEA,UAAI;AAGJ,aAAO,MAAM;AACT,cAAM,QAAQ,MAAM,IAAI,UAAU,MAAM;AACxC,YAAI,CAAC,OAAO,OAAQ;AAGpB,YAAI,CAAC,UAAe;AAChB,gBAAM,QAAe,MAAM,QAAQ,KAAK,CAAC;AACzC,gBAAM,YAAY,IAAI,IAAc,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEnF,cAAI,SAAS,IAAI,KAAK,MAAM,UAAU,WAAW,QAAQ,KAAK,CAAC;AAC/D,gBAAM,OAAO,CAAC,GAAG,KAAK;AACtB,qBAAW,UAAU,OAAO;AACxB,kBAAM,gBAAgB,IAAI,KAAK,OAAO,cAAc,CAAC;AACrD,gBAAI,gBAAgB,OAAQ,UAAS;AAErC,gBAAI,OAAO,QAAS;AAEpB,mBAAO,OAAO;AAEd,kBAAM,YAAY,OAAO,KAAK,UAAU,IAAI,OAAO,EAAE,IAAI;AACzD,gBAAI,WAAW;AACX,oBAAM,SAAS;AAAA,gBACX,GAAG;AAAA,gBACH,GAAG;AAAA,gBACH,UAAU,UAAU;AAAA,cACxB;AACA,oBAAM,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,aAAa,UAAU,QAAQ;AACnE,kBAAI,OAAO,EAAG,MAAK,GAAG,IAAI;AAAA,YAC9B,OAAO;AACH,mBAAK,KAAK;AAAA,gBACN,GAAG;AAAA,gBACH,UAAU,cAAc;AAAA,cAC5B,CAAC;AAAA,YACL;AAAA,UACJ;AAEA,iBAAO;AAAA,YACH,CAAC,QAAQ,GAAG;AAAA,YACZ,WAAW;AAAA,cACP,GAAI,MAAM,aAAa,CAAC;AAAA,cACxB,YAAY;AAAA,gBACR,GAAI,MAAM,UAAU,cAAc,CAAC;AAAA,gBACnC,CAAC,QAAQ,GAAG,OAAO,YAAY;AAAA,cACnC;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ,CAAC;AAED,YAAI,WAAW,UAAa,WAAW,MAAM,MAAM,SAAS,CAAC,EAAE,IAAI;AAC/D,gBAAM,IAAI,MAAM,iEAAiE;AAAA,QACrF;AAEA,iBAAS,MAAM,MAAM,SAAS,CAAC,EAAE;AAAA,MACrC;AAEA,aAAO,KAAK,kCAAkC,QAAQ,EAAE;AAAA,IAC5D,SAAS,KAAK;AACV,kBAAY,aAAc;AAC1B,aAAO,MAAM,mCAAmC,QAAQ,IAAI,GAAG;AAAA,IACnE;AAAA,EACJ;AAEA,MAAI,CAAC,WAAgB;AAAA,IACjB,WAAW;AAAA,MACP,GAAI,MAAM,aAAa,CAAC;AAAA,MACxB,eAAe;AAAA,MACf,OAAO;AAAA,IACX;AAAA,EACJ,EAAE;AACN;;;ACvFO,SAAS,gBAAgB,QAAgB,WAAmB;AAE/D,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;;;ANrDO,IAAK,aAAL,kBAAKA,gBAAL;AACH,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,YAAS;AAHD,SAAAA;AAAA,GAAA;AAMZ,IAAM,+BAA+B;AACrC,IAAM,iBAAyB;AAC/B,IAAM,wBAAkC;AACxC,IAAM,yCAAsE;AAC5E,IAAM,uCAAmE;AAElE,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,6BAA6B,YAAY,8BAA8B;AAC7E,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,UACtB,WAAW,UAAU;AAAA,QACzB;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,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB,QAAQ;AAAA;AAAA,QACZ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,UAAoD,CAAC,KAAU,KAAU,aAAkB;AAC7F,QAAI,mBAAmB;AAEvB,mBAAe,WAAW;AACtB,UAAI,IAAI,EAAE,UAAU,WAAW,OAAQ;AAEvC,UAAI,CAAC,WAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAI,MAAM,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,QAAQ,0BAA0B;AAAA,QAC1E,SAAS,KAAK;AACV,2BAAiB,kBAAmB;AACpC,iBAAO,MAAM,8BAA8B,QAAQ,IAAI,GAAG;AAAA,QAC9D;AAAA,MACJ;AAGA,YAAM,kBAAmC,CAAC,GAAI,IAAI,EAAE,UAAU,kBAAkB,CAAC,CAAE;AAGnF,sBAAgB,KAAK,CAAC,GAAG,MAAM,SAAS,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,CAAC;AAEtE,iBAAW,UAAU,iBAAiB;AAClC,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,2BAAiB,kBAAmB;AACpC,iBAAO,MAAM,4BAA4B,MAAM,IAAI,GAAG;AAAA,QAC1D;AAAA,MACJ;AAEA,UAAI,CAAC,WAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB,QAAQ;AAAA,UACR,OAAO;AAAA,QACX;AAAA,MACJ,EAAE;AAAA,IACN;AAEA,aAAS,kBAAkB,SAAc;AACrC,UAAI,OAAO,YAAY,YAAY;AAC/B,YAAI,CAAC,UAAe,aAAa,OAAO,QAAQ,KAAK,CAAC,CAAC;AAAA,MAC3D,OAAO;AACH,YAAI,CAAC,UAAe,aAAa,OAAO,OAAO,CAAC;AAAA,MACpD;AAAA,IACJ;AAEA,aAAS,aAAa,OAAY,SAAc;AAC5C,YAAM,iBAAkC,MAAM,UAAU,kBAAkB,CAAC;AAE3E,aAAO,KAAK,OAAO,EAAE,IAAI,CAAC,aAAa;AACnC,cAAM,UAAU,MAAM,QAAQ;AAC9B,cAAM,UAAU,QAAQ,QAAQ;AAChC,cAAM,UAAU,YAAY,SAAS,OAAO;AAC5C,+BAAuB,gBAAgB,UAAU,OAAO;AAAA,MAC5D,CAAC;AAGD,YAAM,YAAY,mBAAmB,gBAAgB,MAAM,UAAU,SAAS;AAE9E,aAAO;AAAA,QACH,GAAG;AAAA,QACH,WAAW;AAAA,UACP,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB;AAAA,UACA;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAEA,aAAS,OAAO,SAAkB;AAC9B,UAAI,CAAC,WAAgB;AAAA,QACjB,WAAW;AAAA,UACP,GAAI,MAAM,aAAa,CAAC;AAAA,UACxB,QAAQ,UAAU,SAAS;AAAA,QAC/B;AAAA,MACJ,EAAE;AAEF,qBAAe,OAAO;AACtB,kCAA4B,OAAO;AAAA,IACvC;AAEA,aAAS,eAAe,OAAgB;AACpC,UAAI,OAAO;AACP,iBAAS;AAAA,MACb,OAAO;AACH,2BAAmB;AAAA,MACvB;AAAA,IACJ;AAEA,mBAAe,WAAW;AACtB,UAAI,iBAAkB;AACtB,yBAAmB;AAEnB,aAAO,MAAM;AACT,YAAI,CAAC,iBAAkB;AACvB,cAAM,SAAS;AACf,cAAM,MAAM,YAAY;AAAA,MAC5B;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,uBAAe,IAAI;AAAA,MACvB,OAAO;AACH,eAAO,MAAM,iCAAiC;AAC9C,uBAAe,KAAK;AAAA,MACxB;AAAA,IACJ;AAGA,aAAS,OAAO;AAAA,MACZ;AAAA,MACA,gBAAgB,MAAM,eAAe,KAAK,SAAS,MAAM;AAAA,MACzD,iBAAiB,CAAC,SAAiB,cAAuB,gBAAgB,KAAK,SAAS,SAAS;AAAA,IACrG;AAEA,UAAM,YAAY,aAAa,KAAK,KAAK,iBAAiB;AAE1D,WAAO;AAAA,MACH,GAAG;AAAA,MACH,WAAW;AAAA;AAAA,QAEP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW;AAAA,QACX,eAAe;AAAA,QACf,gBAAgB,CAAC;AAAA,QACjB,YAAY,CAAC;AAAA,MACjB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,QAAQ,SAAS,qBAAqB;AACjD;","names":["SyncAction"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/helpers.ts","../src/pull.ts","../src/push.ts","../src/firstLoad.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, findChanges, tryAddToPendingChanges, tryUpdateConflicts, resolveConflict, sleep, isPullIntervalNow } from './helpers';\nimport {\n type ApiFunctions,\n type SyncOptions,\n type SyncState,\n type SyncedStateCreator,\n type PendingChange,\n type UseStoreWithSync,\n type MissingRemoteRecordStrategy,\n type ConflictResolutionStrategy,\n} from './types';\nimport { pull } from './pull';\nimport { pushOne } from './push';\nimport { startFirstLoad } from './firstLoad';\n\nexport { createIndexedDB } from './indexedDBStorage';\nexport { createLocalId, changeKeysTo, changeKeysFrom } from './helpers';\nexport type { ApiFunctions, UseStoreWithSync, SyncState } from './types';\n\nexport enum SyncAction {\n Create = 'create',\n Update = 'update',\n Remove = 'remove',\n}\n\nconst DEFAULT_SYNC_INTERVAL_MILLIS = 2000;\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 = 'try-shallow-merge';\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 apiConfig = syncOptions.apiConfig ?? {};\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 lastUpdatedAt: syncState.lastUpdatedAt,\n lastPulled: syncState.lastPulled,\n conflicts: syncState.conflicts,\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 syncTimerStarted = false;\n\n async function syncOnce() {\n if (get().syncState.status !== 'idle') return;\n\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: 'syncing',\n },\n }));\n\n let firstSyncError: Error | undefined;\n const lastPulled: SyncState['syncState']['lastPulled'] = { ...get().syncState.lastPulled };\n\n // 1) PULL for each stateKey\n for (const stateKey of Object.keys(syncApi)) {\n try {\n if (!isPullIntervalNow(stateKey, apiConfig, lastPulled)) continue;\n\n const api = findApi(stateKey, syncApi);\n await pull(set, get, stateKey, api, logger, conflictResolutionStrategy);\n lastPulled[stateKey] = new Date().toISOString();\n } catch (err) {\n firstSyncError = firstSyncError ?? (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 firstSyncError = firstSyncError ?? (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: firstSyncError,\n lastPulled,\n } as SyncState['syncState'],\n }));\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 }\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 tryAddToPendingChanges(pendingChanges, stateKey, changes);\n });\n\n // Prevent stale conflicts reporting old values to user\n const conflicts = tryUpdateConflicts(pendingChanges, state.syncState.conflicts);\n\n return {\n ...partial,\n syncState: {\n ...(state.syncState || {}),\n pendingChanges,\n conflicts,\n } as SyncState['syncState'],\n };\n }\n\n function enable(enabled: boolean) {\n set((state: any) => ({\n syncState: {\n ...(state.syncState || {}),\n status: enabled ? 'idle' : 'disabled',\n },\n }));\n\n startSyncTimer(enabled);\n addVisibilityChangeListener(enabled);\n }\n\n function startSyncTimer(start: boolean) {\n if (start) {\n tryStart(); // Unawaited async\n } else {\n syncTimerStarted = false;\n }\n }\n\n async function tryStart() {\n if (syncTimerStarted) return;\n syncTimerStarted = true;\n\n while (true) {\n if (!syncTimerStarted) break;\n await syncOnce();\n await sleep(syncInterval);\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 startSyncTimer(true);\n } else {\n logger.debug('[zync] sync:pause-in-background');\n startSyncTimer(false);\n }\n }\n\n // public useStore.sync api, similar in principle to useStore.persist\n storeApi.sync = {\n enable,\n startFirstLoad: () => startFirstLoad(set, syncApi, logger),\n resolveConflict: (localId: string, keepLocal: boolean) => resolveConflict(set, localId, keepLocal),\n };\n\n const userState = stateCreator(set, get, setAndQueueToSync) as TStore;\n\n return {\n ...userState,\n syncState: {\n // set defaults\n status: 'hydrating',\n error: undefined,\n conflicts: undefined,\n firstLoadDone: false,\n pendingChanges: [],\n lastUpdatedAt: {},\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 { ApiConfig, ApiFunctions, Conflict, FieldConflict, PendingChange, SyncState } from './types';\n\nconst SYNC_FIELDS = ['_localId', 'updated_at', 'deleted'] as const;\n\nexport function createLocalId(): string {\n return crypto.randomUUID();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function changeKeysTo(input: any | any[], toIdKey: string, toUpdatedAtKey: string, toDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { id, updated_at, deleted, ...rest } = item;\n return {\n [toIdKey]: id,\n [toUpdatedAtKey]: updated_at,\n [toDeletedKey]: deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function changeKeysFrom(input: any | any[], fromIdKey: string, fromUpdatedAtKey: string, fromDeletedKey: string) {\n if (!input) return input;\n const isArray = Array.isArray(input);\n const result = (isArray ? input : [input]).map((item) => {\n const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;\n return {\n id,\n updated_at,\n deleted,\n ...rest,\n };\n });\n return isArray ? result : result[0];\n}\n\nexport function orderFor(a: SyncAction): number {\n switch (a) {\n case SyncAction.Create:\n return 1;\n case SyncAction.Update:\n return 2;\n case SyncAction.Remove:\n return 3;\n }\n}\n\nexport function omitSyncFields(item: any) {\n const result = { ...item };\n for (const k of SYNC_FIELDS) delete result[k];\n return result;\n}\n\nexport function samePendingVersion(get: any, stateKey: string, localId: string, version: number): boolean {\n const pending: PendingChange[] = get().syncState.pendingChanges || [];\n const curChange = pending.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 tryAddToPendingChanges(pendingChanges: PendingChange[], stateKey: string, changes: Map<string, ChangeRecord>) {\n for (const [localId, change] of changes) {\n let omittedChanges = omitSyncFields(change.changes);\n const omittedCurrentItem = omitSyncFields(change.currentItem);\n const omittedUpdatedItem = omitSyncFields(change.updatedItem);\n const queueItem = pendingChanges.find((p) => p.localId === localId && p.stateKey === stateKey);\n const hasChanges = Object.keys(omittedChanges).length > 0;\n const action = change.updatedItem === null ? SyncAction.Remove : change.currentItem === null ? SyncAction.Create : SyncAction.Update;\n\n if (action === SyncAction.Update && change.updatedItem && change.currentItem && change.currentItem._localId !== change.updatedItem._localId) {\n // Here when insert-remote-record swaps local remotely deleted item with a fresh copy to push up\n omittedChanges = omittedUpdatedItem;\n }\n\n if (queueItem) {\n if (queueItem.action === SyncAction.Remove) {\n // Once a Remove is queued, it stays a Remove\n continue;\n }\n\n queueItem.version += 1;\n\n if (action === SyncAction.Remove) {\n queueItem.action = SyncAction.Remove;\n } else if (hasChanges) {\n // Never change the action here, it stays Create or Update and is removed when synced\n queueItem.changes = { ...queueItem.changes, ...omittedChanges };\n queueItem.after = { ...queueItem.after, ...omittedUpdatedItem };\n }\n } else if (action === SyncAction.Remove || hasChanges) {\n pendingChanges.push({\n action,\n stateKey,\n localId,\n id: change.id,\n version: 1,\n changes: omittedChanges,\n before: omittedCurrentItem,\n after: omittedUpdatedItem,\n });\n }\n }\n}\n\nexport function setPendingChangeToUpdate(get: any, stateKey: string, localId: string, id?: any) {\n // id is optional as the user may client assign the id, but not return it from the api\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.action = SyncAction.Update;\n if (id) change.id = id;\n }\n}\n\nexport function setPendingChangeBefore(get: any, stateKey: string, localId: string, before: any) {\n const pendingChanges: PendingChange[] = get().syncState.pendingChanges || [];\n const change = pendingChanges.find((p) => p.stateKey === stateKey && p.localId === localId);\n if (change) {\n change.before = { ...change.before, ...before };\n }\n}\n\nexport function tryUpdateConflicts(pendingChanges: PendingChange[], conflicts?: Record<string, Conflict>): Record<string, Conflict> | undefined {\n if (!conflicts) return conflicts;\n\n const newConflicts = { ...conflicts };\n\n for (const change of pendingChanges) {\n const conflict = newConflicts[change.localId];\n if (conflict && change.changes) {\n // Loop changed fields and update their old possibly stale value to the current local value\n const newFields = conflict.fields.map((f) => {\n if (f.key in change.changes) {\n return { ...f, localValue: change.changes[f.key] } as FieldConflict;\n }\n return f;\n });\n\n newConflicts[change.localId] = { stateKey: conflict.stateKey, fields: newFields };\n }\n }\n\n return newConflicts;\n}\n\nexport function findApi(stateKey: string, syncApi: Record<string, ApiFunctions>): ApiFunctions {\n const api = syncApi[stateKey];\n if (!api || !api.add || !api.update || !api.remove || !api.list) {\n throw new Error(`Missing API function(s) for state key: ${stateKey}.`);\n }\n\n return api;\n}\n\nexport function isPullIntervalNow(stateKey: string, apiConfig: Record<string, ApiConfig>, lastPulled: SyncState['syncState']['lastPulled']): boolean {\n const config = apiConfig[stateKey];\n if (!config || !config.pullInterval) {\n return true;\n }\n\n const lastPulledTime = new Date(lastPulled[stateKey] ?? 0).getTime();\n return Date.now() > lastPulledTime + config.pullInterval;\n}\n\ntype ChangeRecord = {\n currentItem?: any;\n updatedItem?: any;\n changes: any;\n id?: 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 update of updated) {\n const item = { ...update };\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 // Changes\n changesMap.set(item._localId, { currentItem: curr, updatedItem: item, changes: diff, id: curr.id ?? item.id });\n }\n } else {\n // Addition\n changesMap.set(item._localId, { currentItem: null, updatedItem: item, changes: item, id: item.id });\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, id: curr.id });\n }\n }\n\n return changesMap;\n}\n\nexport function hasKeysOrUndefined(obj: any): any {\n return Object.keys(obj).length === 0 ? undefined : obj;\n}\n\nexport function hasConflicts(get: any, localId: string): boolean {\n const state = get() as SyncState;\n if (state.syncState.conflicts) {\n return !!state.syncState.conflicts[localId];\n }\n return false;\n}\n\nexport function resolveConflict(set: any, localId: string, keepLocalFields: boolean) {\n set((state: any) => {\n const syncState: SyncState['syncState'] = state.syncState || {};\n const conflicts: Record<string, Conflict> = syncState.conflicts || {};\n const conflict = conflicts[localId];\n if (conflict) {\n const items = state[conflict.stateKey];\n const item = items.find((i: any) => i._localId === localId);\n if (!item) {\n return state;\n }\n\n const resolved: any = { ...item };\n let pendingChanges = [...syncState.pendingChanges];\n\n if (!keepLocalFields) {\n // Use remote value(s)\n for (const field of conflict.fields) {\n resolved[field.key] = field.remoteValue;\n }\n\n // Remove resolved pending change\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === conflict.stateKey && p.localId === localId));\n }\n\n // Replace with resolved item\n const nextItems = items.map((i: any) => (i._localId === localId ? resolved : i));\n const nextConflicts = { ...conflicts };\n delete nextConflicts[localId];\n\n return {\n [conflict.stateKey]: nextItems,\n syncState: {\n ...syncState,\n pendingChanges,\n conflicts: hasKeysOrUndefined(nextConflicts),\n },\n };\n }\n return state;\n });\n}\n","import { type ApiFunctions, type FieldConflict, type ConflictResolutionStrategy, type SyncedRecord, type PendingChange, type SyncState } from './types';\nimport { SyncAction } from './index';\nimport { createLocalId, hasKeysOrUndefined } 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 lastUpdatedAt: SyncState['syncState']['lastUpdatedAt'] = get().syncState.lastUpdatedAt || {};\n let lastUpdatedAtDate = new Date(lastUpdatedAt[stateKey] || new Date(0));\n\n logger.debug(`[zync] pull:start stateKey=${stateKey} since=${lastUpdatedAtDate.toISOString()}`);\n\n const serverData = (await api.list(lastUpdatedAtDate)) as SyncedRecord[];\n if (!serverData?.length) return;\n\n set((state: any) => {\n let pendingChanges = [...(state.syncState.pendingChanges as PendingChange[])];\n const conflicts = { ...state.syncState.conflicts };\n const localItems: any[] = state[stateKey] || [];\n let nextItems = [...localItems];\n\n const localById = new Map<any, any>(localItems.filter((l) => l.id).map((l) => [l.id, l]));\n // prevent resurrecting deleted items when 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 > lastUpdatedAtDate) lastUpdatedAtDate = 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 logger.debug(`[zync] pull:conflict-strategy:${conflictResolutionStrategy} stateKey=${stateKey} id=${remote.id}`);\n\n switch (conflictResolutionStrategy) {\n case 'local-wins':\n // Ignore remote changes, keep local\n break;\n\n case 'remote-wins': {\n // Ignore local changes, keep remote\n const merged = { ...remote, _localId: localItem._localId };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Remove pending change so it isn't pushed after pull\n pendingChanges = pendingChanges.filter((p) => !(p.stateKey === stateKey && p.localId === localItem._localId));\n break;\n }\n\n case 'try-shallow-merge': {\n // List fields that local and remote have changed\n const changes = pendingChange.changes || {};\n const before = pendingChange.before || {};\n const fields: FieldConflict[] = Object.entries(changes)\n .filter(([k, localValue]) => k in before && k in remote && before[k] !== remote[k] && localValue !== remote[k])\n .map(([key, localValue]) => ({ key, localValue, remoteValue: remote[key] }));\n\n if (fields.length > 0) {\n logger.warn(`[zync] pull:${conflictResolutionStrategy}:conflicts-found`, JSON.stringify(fields, null, 4));\n conflicts[localItem._localId] = { stateKey, fields };\n } else {\n // No conflicts, merge remote into local but only preserve fields that were\n // actually changed locally\n const localChangedKeys = Object.keys(changes);\n const preservedLocal: any = { _localId: localItem._localId };\n for (const k of localChangedKeys) {\n if (k in localItem) preservedLocal[k] = localItem[k];\n }\n\n const merged = { ...remote, ...preservedLocal };\n nextItems = nextItems.map((i: any) => (i._localId === localItem._localId ? merged : i));\n // Merge now resolved, drop pending and conflict\n delete conflicts[localItem._localId];\n }\n break;\n }\n }\n } else {\n // No pending changes, merge remote into local\n const merged = { ...localItem, ...remote };\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: createLocalId() }];\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 pendingChanges,\n conflicts: hasKeysOrUndefined(conflicts),\n lastUpdatedAt: {\n ...(state.syncState.lastUpdatedAt || {}),\n [stateKey]: lastUpdatedAtDate.toISOString(),\n },\n },\n };\n });\n}\n","import { hasConflicts, removeFromPendingChanges, samePendingVersion, setPendingChangeBefore, setPendingChangeToUpdate } from './helpers';\nimport { createLocalId, 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\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, changes, after } = change;\n\n switch (action) {\n case SyncAction.Remove:\n if (!id) {\n logger.warn(`[zync] push:remove:no-id stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\n }\n\n await api.remove(id);\n logger.debug(`[zync] push:remove:success stateKey=${stateKey} localId=${localId} id=${id}`);\n removeFromPendingChanges(set, localId, stateKey);\n break;\n\n case SyncAction.Update: {\n if (hasConflicts(get, change.localId)) {\n logger.warn(`[zync] push:update:skipping-with-conflicts stateKey=${stateKey} localId=${localId} id=${id}`);\n return;\n }\n\n const exists = await api.update(id, changes, after);\n if (exists) {\n logger.debug(`[zync] push:update:success stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure pending.before is not stale for conflict resolution\n setPendingChangeBefore(get, stateKey, localId, changes);\n }\n return;\n } else {\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:missing-remote:no-local-item stateKey=${stateKey} localId=${localId}`);\n removeFromPendingChanges(set, localId, stateKey);\n return;\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 logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${item.id}`);\n break;\n\n case 'insert-remote-record': {\n const newItem = {\n ...item,\n _localId: createLocalId(),\n updated_at: new Date().toISOString(),\n };\n\n // replace old with modified and queue Create\n setAndQueueToSync((s: any) => ({\n [stateKey]: (s[stateKey] || []).map((i: any) => (i._localId === localId ? newItem : i)),\n }));\n\n logger.debug(`[zync] push:missing-remote:${missingStrategy} stateKey=${stateKey} id=${newItem.id}`);\n break;\n }\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-strategy 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);\n }\n break;\n }\n\n case SyncAction.Create: {\n const result = await api.add(changes);\n if (result) {\n logger.debug(`[zync] push:create:success stateKey=${stateKey} localId=${localId} id=${id}`);\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\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n } else {\n // Item changed during request, ensure any pendingChanges entry has id and is now an Update\n setPendingChangeToUpdate(get, stateKey, localId, result.id);\n }\n\n const finalItem = { ...changes, ...result, _localId: localId };\n\n // Call hook so userland can perform any cascading adjustments\n onAfterRemoteAdd?.(set, get, setAndQueueToSync, stateKey, finalItem);\n } else {\n logger.warn(`[zync] push:create:no-result stateKey=${stateKey} localId=${localId} id=${id}`);\n if (samePendingVersion(get, stateKey, localId, version)) {\n removeFromPendingChanges(set, localId, stateKey);\n }\n }\n break;\n }\n }\n}\n","import { createLocalId } from './helpers';\nimport type { Logger } from './logger';\nimport type { ApiFunctions } from './types';\n\nexport async function startFirstLoad(set: any, syncApi: Record<string, ApiFunctions>, logger: Logger) {\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 = syncApi[stateKey];\n if (!api?.firstLoad) {\n logger.error(`[zync] firstLoad:no-api-function stateKey=${stateKey}`);\n continue;\n }\n\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.lastUpdatedAt[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: createLocalId(),\n });\n }\n }\n\n return {\n [stateKey]: next,\n syncState: {\n ...(state.syncState || {}),\n lastUpdatedAt: {\n ...(state.syncState.lastUpdatedAt || {}),\n [stateKey]: newest.toISOString(),\n },\n },\n };\n });\n\n if (lastId !== undefined && lastId === batch[batch.length - 1].id) {\n throw new Error(`Duplicate records downloaded, stopping to prevent infinite loop`);\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","import type { IDBPDatabase } from 'idb';\n\nexport function createIndexedDB(dbName: string, storeName: string) {\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anfenn/zync",
3
- "version": "0.4.8",
3
+ "version": "0.5.1",
4
4
  "private": false,
5
5
  "description": "Sync middleware for Zustand",
6
6
  "keywords": [],