cry-synced-db-client 0.1.134 → 0.1.136

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Versions
2
2
 
3
+ ## 0.1.136 (2026-04-20)
4
+
5
+ - `DexieDb.saveMany` is now fail-safe:
6
+ - Items with invalid `_id` (non-string or empty string) are skipped with
7
+ `console.error` that includes collection name and the offending `_id` /
8
+ item payload.
9
+ - `bulkPut` errors are caught and logged (collection + affected `_id` list)
10
+ so a single bad record no longer aborts the entire sync cycle.
11
+
12
+ ## 0.1.135 (2026-04-20)
13
+
14
+ - Conflict resolution: server wins on primitive field conflicts when `external._rev > local._rev`
15
+ - Previously local always won for overlapping primitive fields during conflict merge
16
+ - New rule applies recursively to object elements inside arrays (via `mergeObjectArrays` → `mergeObjects`)
17
+ - Arrays still unionize; nested objects without `_rev` keep local-wins behavior
18
+ - Affects dirty-conflict resolution path ([SyncEngine.resolveCollectionConflict](src/db/sync/SyncEngine.ts))
19
+
3
20
  ## 0.1.126 (2026-04-08)
4
21
 
5
22
  - Eviction: remove out-of-scope records from Dexie and in-mem cache
package/dist/index.js CHANGED
@@ -2319,6 +2319,7 @@ function resolveConflict(local, external) {
2319
2319
  }
2320
2320
  function mergeObjects(local, external) {
2321
2321
  const result = __spreadValues({}, local);
2322
+ const serverWinsOnConflict = typeof local._rev === "number" && typeof external._rev === "number" && external._rev > local._rev;
2322
2323
  for (const key of Object.keys(external)) {
2323
2324
  if (key === "_id" || key === "_dirty") {
2324
2325
  continue;
@@ -2336,6 +2337,8 @@ function mergeObjects(local, external) {
2336
2337
  result[key] = mergeArrays(localValue, externalValue);
2337
2338
  } else if (isPlainObject3(localValue) && isPlainObject3(externalValue)) {
2338
2339
  result[key] = mergeObjects(localValue, externalValue);
2340
+ } else if (serverWinsOnConflict) {
2341
+ result[key] = externalValue;
2339
2342
  }
2340
2343
  }
2341
2344
  return result;
@@ -5000,8 +5003,30 @@ var DexieDb = class extends Dexie {
5000
5003
  async saveMany(collection, items) {
5001
5004
  if (items.length === 0) return;
5002
5005
  const table = this.getTable(collection);
5003
- for (const item of items) this.ensureStringId(item);
5004
- await table.bulkPut(items);
5006
+ const valid = [];
5007
+ for (const item of items) {
5008
+ this.ensureStringId(item);
5009
+ if (typeof item._id !== "string" || item._id.length === 0) {
5010
+ console.error(
5011
+ `DexieDb.saveMany: skipping item with invalid _id in "${collection}"`,
5012
+ { _id: item._id, _idType: typeof item._id, item }
5013
+ );
5014
+ continue;
5015
+ }
5016
+ valid.push(item);
5017
+ }
5018
+ if (valid.length === 0) return;
5019
+ try {
5020
+ await table.bulkPut(valid);
5021
+ } catch (err) {
5022
+ const ids = valid.map((it) => String(it._id));
5023
+ console.error(
5024
+ `DexieDb.saveMany: bulkPut failed for "${collection}" (${valid.length} items):`,
5025
+ err,
5026
+ "_ids:",
5027
+ ids
5028
+ );
5029
+ }
5005
5030
  }
5006
5031
  async deleteOne(collection, id) {
5007
5032
  const table = this.getTable(collection);
@@ -5,13 +5,15 @@ import type { DbEntity } from "../types/DbEntity";
5
5
  * 1. Če ima lokalni objekt _rev in ima objekt s serverja nižji ali isti _rev, ignoriramo server
6
6
  * 2. Polja, ki niso array in niso object:
7
7
  * - če lokalna verzija nima polja, zunanja pa ga ima, polje dodamo
8
- * - če imata oba objekta polje, vrednost s serverja zavržemo
8
+ * - če imata oba objekta polje:
9
+ * - če external._rev > local._rev (oba definirana), zmaga server
10
+ * - sicer ohranimo lokalno vrednost
9
11
  * 3. Polja tipa array:
10
12
  * - če lokalni objekt nima polja, ga dodamo
11
13
  * - če je tip podatkov string[], shranimo deduplicirano unijo
12
14
  * - če je tip podatkov Object[]:
13
15
  * - elemente brez _id dodamo v lokalni array
14
- * - objekte z _id primerjamo rekurzivno
16
+ * - objekte z _id primerjamo rekurzivno (rekurzija uporabi isto _rev pravilo)
15
17
  * 4. Če je tip podatkov Record<string, Object>:
16
18
  * - za vsak key, ki ga ni v lokalnem objektu, dodamo vrednost
17
19
  * - za vsak key, ki obstaja, primerjamo rekurzivno
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.134",
3
+ "version": "0.1.136",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",