cry-synced-db-client 2.0.6 → 2.0.7

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/dist/index.js CHANGED
@@ -919,21 +919,23 @@ var InMemManager = class {
919
919
  const config = this.collections.get(collection);
920
920
  const source = (_a = opts == null ? void 0 : opts.source) != null ? _a : "incremental";
921
921
  if (operation === "upsert") {
922
- this.inMemDb.saveMany(collection, items, { source });
922
+ const itemsToWrite = source === "incremental" ? this.dropRevRegressions(collection, items) : items;
923
+ if (itemsToWrite.length === 0) return;
924
+ this.inMemDb.saveMany(collection, itemsToWrite, { source });
923
925
  if (this.useObjectMetadata && (config == null ? void 0 : config.hasMetadata)) {
924
926
  const ids = [];
925
- for (const item of items) ids.push(item._id);
927
+ for (const item of itemsToWrite) ids.push(item._id);
926
928
  let metadatas;
927
929
  if (config.onObjectsUpdated) {
928
930
  try {
929
- metadatas = config.onObjectsUpdated(items);
931
+ metadatas = config.onObjectsUpdated(itemsToWrite);
930
932
  } catch (err) {
931
933
  console.error(`[InMem] onObjectsUpdated callback failed: ${err}`, err);
932
934
  return;
933
935
  }
934
936
  } else if (config.onObjectUpdated) {
935
937
  try {
936
- metadatas = items.map((item) => config.onObjectUpdated(item));
938
+ metadatas = itemsToWrite.map((item) => config.onObjectUpdated(item));
937
939
  } catch (err) {
938
940
  console.error(`[InMem] onObjectUpdated callback failed: ${err}`, err);
939
941
  return;
@@ -952,6 +954,30 @@ var InMemManager = class {
952
954
  }
953
955
  }
954
956
  }
957
+ /**
958
+ * Filter out items whose `_rev` is lower than what in-mem already holds
959
+ * for that id — an incremental write with a stale rev is, by definition,
960
+ * confirming/echoing a write that a later one has already superseded.
961
+ * Items without a numeric `_rev` on either side are let through unchanged
962
+ * (legacy collections without rev tracking).
963
+ */
964
+ dropRevRegressions(collection, items) {
965
+ const result = [];
966
+ for (const item of items) {
967
+ const incomingRev = item._rev;
968
+ if (typeof incomingRev !== "number") {
969
+ result.push(item);
970
+ continue;
971
+ }
972
+ const current = this.inMemDb.getById(collection, item._id);
973
+ const currentRev = current == null ? void 0 : current._rev;
974
+ if (typeof currentRev === "number" && incomingRev < currentRev) {
975
+ continue;
976
+ }
977
+ result.push(item);
978
+ }
979
+ return result;
980
+ }
955
981
  /**
956
982
  * Initialize collection from Dexie data.
957
983
  * Called during SyncedDb.init().
@@ -3866,8 +3892,8 @@ var SyncEngine = class {
3866
3892
  collection,
3867
3893
  idsToCheck
3868
3894
  );
3869
- const dexieSaveBatch = [];
3870
- const inMemUpdateBatch = [];
3895
+ const saveIds = [];
3896
+ const revById = /* @__PURE__ */ new Map();
3871
3897
  const inMemDeleteIds = [];
3872
3898
  const dexieDeleteIds = [];
3873
3899
  for (let i = 0; i < insertedAndUpdated.length; i++) {
@@ -3875,17 +3901,29 @@ var SyncEngine = class {
3875
3901
  const dexieItem = dexieItems[i];
3876
3902
  if (mustRefreshIds.has(String(entity._id))) continue;
3877
3903
  if (dexieItem) {
3878
- dexieItem._rev = entity._rev;
3879
- dexieItem._ts = entity._ts;
3880
3904
  if (dexieItem._deleted) {
3881
3905
  inMemDeleteIds.push(entity._id);
3882
3906
  dexieDeleteIds.push(entity._id);
3883
3907
  } else {
3884
- dexieSaveBatch.push(dexieItem);
3885
- inMemUpdateBatch.push(dexieItem);
3908
+ saveIds.push(entity._id);
3909
+ revById.set(String(entity._id), { rev: entity._rev, ts: entity._ts });
3886
3910
  }
3887
3911
  }
3888
3912
  }
3913
+ const dexieSaveBatch = [];
3914
+ const inMemUpdateBatch = [];
3915
+ if (saveIds.length > 0) {
3916
+ const freshItems = await this.dexieDb.getByIds(collection, saveIds);
3917
+ for (const freshItem of freshItems) {
3918
+ if (!freshItem) continue;
3919
+ const revTs = revById.get(String(freshItem._id));
3920
+ if (!revTs) continue;
3921
+ freshItem._rev = revTs.rev;
3922
+ freshItem._ts = revTs.ts;
3923
+ dexieSaveBatch.push(freshItem);
3924
+ inMemUpdateBatch.push(freshItem);
3925
+ }
3926
+ }
3889
3927
  if (dexieSaveBatch.length > 0) {
3890
3928
  await this.dexieDb.saveMany(collection, dexieSaveBatch);
3891
3929
  }
@@ -28,6 +28,14 @@ export declare class InMemManager implements I_InMemManager {
28
28
  writeBatch<T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
29
29
  source?: SyncSource;
30
30
  }): void;
31
+ /**
32
+ * Filter out items whose `_rev` is lower than what in-mem already holds
33
+ * for that id — an incremental write with a stale rev is, by definition,
34
+ * confirming/echoing a write that a later one has already superseded.
35
+ * Items without a numeric `_rev` on either side are let through unchanged
36
+ * (legacy collections without rev tracking).
37
+ */
38
+ private dropRevRegressions;
31
39
  /**
32
40
  * Initialize collection from Dexie data.
33
41
  * Called during SyncedDb.init().
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -20,8 +20,9 @@
20
20
  "build": "bun run clean && bun run build:js && bun run build:types",
21
21
  "build:js": "esbuild ./src/index.ts --bundle --outdir=./dist --target=es2017 --format=esm --platform=browser --external:dexie --external:bson --external:cry-helpers",
22
22
  "build:types": "tsc --emitDeclarationOnly --outDir dist",
23
- "test": "bun test --preload ./test/preload-bun.cjs test/*.test.ts test/restProxy/*.test.ts; vitest run",
24
- "test:bun": "bun test test/*.test.ts test/restProxy/*.test.ts",
23
+ "test": "bash test/run-all.sh",
24
+ "test:ci": "SKIP_REAL_MONGO=1 bash test/run-all.sh",
25
+ "test:bun": "bun test --preload ./test/preload-bun.cjs test/*.test.ts test/restProxy/*.test.ts test/node-only-bun/*.test.ts",
25
26
  "test:node-only": "vitest run",
26
27
  "test:real-mongo": "USE_REAL_MONGO=1 npx vitest run test/node-only/",
27
28
  "prepublishOnly": "bun run build"