@sanity-labs/client-fake-for-test 0.4.0 → 0.5.0

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.d.cts CHANGED
@@ -268,6 +268,8 @@ export declare type FakeMutation =
268
268
  *
269
269
  * - `seed`, `add`, `reset`, `snapshot`, `store` — bulk-load helpers,
270
270
  * scoped to the current dataset.
271
+ * - `simulateConcurrentEdit()` — force the next N revision-guarded writes
272
+ * to a document to 409, for optimistic-locking retry tests.
271
273
  * - `datasets()` — lists known dataset keys in this registry.
272
274
  *
273
275
  * Methods deliberately omitted:
@@ -785,6 +787,15 @@ export declare interface TestClient {
785
787
  snapshot: () => readonly SanityDocument[];
786
788
  /** Direct store access for the current dataset. */
787
789
  store: () => TestStore;
790
+ /**
791
+ * Simulate `count` concurrent edits to `id` in the current dataset: the
792
+ * next `count` revision-guarded mutations (those passing `ifRevisionId`)
793
+ * to that document throw a 409-shaped conflict, as if another client
794
+ * committed between the caller's read and write. Lets a test exercise
795
+ * optimistic-locking retry paths deterministically, without timing or
796
+ * interleaving. Mutations that don't pass `ifRevisionId` are unaffected.
797
+ */
798
+ simulateConcurrentEdit: (id: string, count?: number) => void;
788
799
  /** List `(projectId, dataset)` pairs known in this registry. */
789
800
  datasets: () => {
790
801
  projectId: string;
package/dist/index.d.ts CHANGED
@@ -268,6 +268,8 @@ export declare type FakeMutation =
268
268
  *
269
269
  * - `seed`, `add`, `reset`, `snapshot`, `store` — bulk-load helpers,
270
270
  * scoped to the current dataset.
271
+ * - `simulateConcurrentEdit()` — force the next N revision-guarded writes
272
+ * to a document to 409, for optimistic-locking retry tests.
271
273
  * - `datasets()` — lists known dataset keys in this registry.
272
274
  *
273
275
  * Methods deliberately omitted:
@@ -785,6 +787,15 @@ export declare interface TestClient {
785
787
  snapshot: () => readonly SanityDocument[];
786
788
  /** Direct store access for the current dataset. */
787
789
  store: () => TestStore;
790
+ /**
791
+ * Simulate `count` concurrent edits to `id` in the current dataset: the
792
+ * next `count` revision-guarded mutations (those passing `ifRevisionId`)
793
+ * to that document throw a 409-shaped conflict, as if another client
794
+ * committed between the caller's read and write. Lets a test exercise
795
+ * optimistic-locking retry paths deterministically, without timing or
796
+ * interleaving. Mutations that don't pass `ifRevisionId` are unaffected.
797
+ */
798
+ simulateConcurrentEdit: (id: string, count?: number) => void;
788
799
  /** List `(projectId, dataset)` pairs known in this registry. */
789
800
  datasets: () => {
790
801
  projectId: string;
package/dist/index.js CHANGED
@@ -859,7 +859,13 @@ const RECORDED_METHODS = /* @__PURE__ */ new Set([
859
859
  return { projectId, dataset };
860
860
  };
861
861
  function createTestClient(options = {}) {
862
- const defaultProjectId = options.projectId ?? DEFAULT_PROJECT_ID, defaultDataset = options.dataset ?? DEFAULT_DATASET, backend = { registry: /* @__PURE__ */ new Map(), log: [], stubs: /* @__PURE__ */ new Map(), calls: [] }, registry = backend.registry, ensureStore = (projectId, dataset) => {
862
+ const defaultProjectId = options.projectId ?? DEFAULT_PROJECT_ID, defaultDataset = options.dataset ?? DEFAULT_DATASET, backend = {
863
+ registry: /* @__PURE__ */ new Map(),
864
+ log: [],
865
+ stubs: /* @__PURE__ */ new Map(),
866
+ calls: [],
867
+ concurrentEdits: /* @__PURE__ */ new Map()
868
+ }, registry = backend.registry, ensureStore = (projectId, dataset) => {
863
869
  const key = registryKey(projectId, dataset);
864
870
  let store = registry.get(key);
865
871
  return store === void 0 && (store = createTestStore(), registry.set(key, store)), store;
@@ -933,7 +939,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
933
939
  const key = registryKey(projectId, dataset);
934
940
  let s = registry.get(key);
935
941
  return s === void 0 && (s = createTestStore(), registry.set(key, s)), s;
936
- })(), record = (transactionId, mutations) => {
942
+ })(), concurrentEditKey = (id) => registryKey(projectId, dataset) + " " + id, record = (transactionId, mutations) => {
937
943
  backend.log.push({ transactionId, projectId, dataset, mutations });
938
944
  }, writeResult = (documents, results, transactionId, opts) => formatMutationResult(
939
945
  documents,
@@ -961,6 +967,11 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
961
967
  };
962
968
  }, checkRevision = (id, ifRevisionId) => {
963
969
  if (ifRevisionId === void 0) return;
970
+ const editKey = concurrentEditKey(id), pendingEdits = backend.concurrentEdits.get(editKey) ?? 0;
971
+ if (pendingEdits > 0)
972
+ throw backend.concurrentEdits.set(editKey, pendingEdits - 1), fakeError(
973
+ `ifRevisionId check failed: document "${id}" was concurrently edited (simulated via simulateConcurrentEdit) \u2014 the revision-guarded mutation lost the race; re-read and retry. (This mirrors Sanity's optimistic-locking 409.)`
974
+ );
964
975
  const existing = store.get(id);
965
976
  if (existing === void 0)
966
977
  throw fakeError(
@@ -1230,6 +1241,10 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1230
1241
  reset: () => store.reset(),
1231
1242
  snapshot: () => store.snapshot(),
1232
1243
  store: () => store,
1244
+ simulateConcurrentEdit: (id, count = 1) => {
1245
+ const editKey = concurrentEditKey(id);
1246
+ backend.concurrentEdits.set(editKey, (backend.concurrentEdits.get(editKey) ?? 0) + count);
1247
+ },
1233
1248
  datasets: () => [...registry.keys()].map(parseRegistryKey),
1234
1249
  stub: (name, handler) => {
1235
1250
  backend.stubs.set(name, handler);