@sanity-labs/client-fake-for-test 0.6.0 → 0.7.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/dist/index.d.cts CHANGED
@@ -1,5 +1,11 @@
1
1
  export declare type Action = ReleaseAction | VersionAction;
2
2
 
3
+ /** Options for `action()`. Only `tag` is meaningful to the fake. */
4
+ export declare interface ActionOptions {
5
+ /** Request tag, recorded on the {@link CallRecord} (`null` = explicit suppression). */
6
+ tag?: string | null;
7
+ }
8
+
3
9
  export declare interface ActionResult {
4
10
  transactionId: string;
5
11
  }
@@ -51,6 +57,8 @@ export declare interface CallRecord {
51
57
  result?: unknown;
52
58
  /** Thrown or rejected value, set if the call failed. */
53
59
  error?: unknown;
60
+ /** Request tag from the call's options, when one was passed (`null` = explicit suppression). */
61
+ tag?: string | null;
54
62
  projectId: string;
55
63
  dataset: string;
56
64
  }
@@ -321,8 +329,12 @@ export declare interface FetchOptions {
321
329
  * raw response. Ignored when `filterResponse` is not `false`.
322
330
  */
323
331
  returnQuery?: boolean;
324
- /** Accepted for signature parity; not simulated. */
325
- tag?: string;
332
+ /**
333
+ * Request tag, recorded on the {@link CallRecord} for assertions.
334
+ * `null` mirrors `@sanity/client`'s explicit-suppression form and is
335
+ * recorded as-is. No other behavior is simulated.
336
+ */
337
+ tag?: string | null;
326
338
  /** Accepted for signature parity; not simulated. */
327
339
  signal?: AbortSignal;
328
340
  }
@@ -429,6 +441,8 @@ export declare interface MutationLogEntry {
429
441
  projectId: string;
430
442
  dataset: string;
431
443
  mutations: TxnMutation[];
444
+ /** Request tag the commit carried, when one was passed (`null` = explicit suppression). */
445
+ tag?: string | null;
432
446
  }
433
447
 
434
448
  /** The operation recorded per affected document, matching `@sanity/client`. */
@@ -456,8 +470,21 @@ export declare interface MutationOptions {
456
470
  visibility?: "sync" | "async" | "deferred";
457
471
  /** Accepted for signature parity; not simulated. */
458
472
  autoGenerateArrayKeys?: boolean;
473
+ /**
474
+ * Request tag, recorded on the {@link CallRecord} and the
475
+ * {@link MutationLogEntry} for assertions. `null` mirrors
476
+ * `@sanity/client`'s explicit-suppression form and is recorded as-is.
477
+ * No other behavior is simulated.
478
+ */
479
+ tag?: string | null;
480
+ }
481
+
482
+ /** Options for `PatchHandle.commit()`. Only `tag` is meaningful to the fake. */
483
+ export declare interface PatchCommitOptions {
484
+ /** Request tag, recorded on the mutation log entry (`null` = explicit suppression). */
485
+ tag?: string | null;
459
486
  /** Accepted for signature parity; not simulated. */
460
- tag?: string;
487
+ visibility?: "sync" | "async" | "deferred";
461
488
  }
462
489
 
463
490
  export declare interface PatchExecutor {
@@ -465,6 +492,7 @@ export declare interface PatchExecutor {
465
492
  documentId: string,
466
493
  ops: PatchOp[],
467
494
  ifRev: string | undefined,
495
+ options: PatchCommitOptions | undefined,
468
496
  ) => Promise<SanityDocument>;
469
497
  }
470
498
 
@@ -480,7 +508,7 @@ export declare interface PatchHandle {
480
508
  items: unknown[],
481
509
  ) => PatchHandle;
482
510
  ifRevisionId: (rev: string) => PatchHandle;
483
- commit: () => Promise<SanityDocument>;
511
+ commit: (options?: PatchCommitOptions) => Promise<SanityDocument>;
484
512
  /** Test-only introspection — not on real Patch */
485
513
  toJSON: () => {
486
514
  id: string;
@@ -727,7 +755,7 @@ export declare interface TestClient {
727
755
  url?: string;
728
756
  uri?: string;
729
757
  signal?: AbortSignal;
730
- tag?: string;
758
+ tag?: string | null;
731
759
  }) => Promise<T>;
732
760
  create: <T extends SanityDocumentLike>(
733
761
  doc: T,
@@ -765,7 +793,10 @@ export declare interface TestClient {
765
793
  * Returns a synthetic `transactionId`. Multi-action arrays are applied
766
794
  * atomically — any failure rolls back the batch.
767
795
  */
768
- action: (action: Action | Action[]) => Promise<ActionResult>;
796
+ action: (
797
+ action: Action | Action[],
798
+ options?: ActionOptions,
799
+ ) => Promise<ActionResult>;
769
800
  /** Helpers mirroring `@sanity/client`'s `client.releases.*` surface. */
770
801
  releases: ReleasesHandle;
771
802
  /** Helper for `sanity.action.document.version.create`. */
@@ -987,6 +1018,12 @@ export declare interface TxnCommitOptions {
987
1018
  returnFirst?: boolean;
988
1019
  /** Override the synthetic transaction id (mirrors `client.transaction(undefined, { transactionId })`). */
989
1020
  transactionId?: string;
1021
+ /**
1022
+ * Request tag, recorded on the mutation log entry for assertions.
1023
+ * `null` mirrors `@sanity/client`'s explicit-suppression form and is
1024
+ * recorded as-is. No other behavior is simulated.
1025
+ */
1026
+ tag?: string | null;
990
1027
  }
991
1028
 
992
1029
  export declare type TxnCommitResult =
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  export declare type Action = ReleaseAction | VersionAction;
2
2
 
3
+ /** Options for `action()`. Only `tag` is meaningful to the fake. */
4
+ export declare interface ActionOptions {
5
+ /** Request tag, recorded on the {@link CallRecord} (`null` = explicit suppression). */
6
+ tag?: string | null;
7
+ }
8
+
3
9
  export declare interface ActionResult {
4
10
  transactionId: string;
5
11
  }
@@ -51,6 +57,8 @@ export declare interface CallRecord {
51
57
  result?: unknown;
52
58
  /** Thrown or rejected value, set if the call failed. */
53
59
  error?: unknown;
60
+ /** Request tag from the call's options, when one was passed (`null` = explicit suppression). */
61
+ tag?: string | null;
54
62
  projectId: string;
55
63
  dataset: string;
56
64
  }
@@ -321,8 +329,12 @@ export declare interface FetchOptions {
321
329
  * raw response. Ignored when `filterResponse` is not `false`.
322
330
  */
323
331
  returnQuery?: boolean;
324
- /** Accepted for signature parity; not simulated. */
325
- tag?: string;
332
+ /**
333
+ * Request tag, recorded on the {@link CallRecord} for assertions.
334
+ * `null` mirrors `@sanity/client`'s explicit-suppression form and is
335
+ * recorded as-is. No other behavior is simulated.
336
+ */
337
+ tag?: string | null;
326
338
  /** Accepted for signature parity; not simulated. */
327
339
  signal?: AbortSignal;
328
340
  }
@@ -429,6 +441,8 @@ export declare interface MutationLogEntry {
429
441
  projectId: string;
430
442
  dataset: string;
431
443
  mutations: TxnMutation[];
444
+ /** Request tag the commit carried, when one was passed (`null` = explicit suppression). */
445
+ tag?: string | null;
432
446
  }
433
447
 
434
448
  /** The operation recorded per affected document, matching `@sanity/client`. */
@@ -456,8 +470,21 @@ export declare interface MutationOptions {
456
470
  visibility?: "sync" | "async" | "deferred";
457
471
  /** Accepted for signature parity; not simulated. */
458
472
  autoGenerateArrayKeys?: boolean;
473
+ /**
474
+ * Request tag, recorded on the {@link CallRecord} and the
475
+ * {@link MutationLogEntry} for assertions. `null` mirrors
476
+ * `@sanity/client`'s explicit-suppression form and is recorded as-is.
477
+ * No other behavior is simulated.
478
+ */
479
+ tag?: string | null;
480
+ }
481
+
482
+ /** Options for `PatchHandle.commit()`. Only `tag` is meaningful to the fake. */
483
+ export declare interface PatchCommitOptions {
484
+ /** Request tag, recorded on the mutation log entry (`null` = explicit suppression). */
485
+ tag?: string | null;
459
486
  /** Accepted for signature parity; not simulated. */
460
- tag?: string;
487
+ visibility?: "sync" | "async" | "deferred";
461
488
  }
462
489
 
463
490
  export declare interface PatchExecutor {
@@ -465,6 +492,7 @@ export declare interface PatchExecutor {
465
492
  documentId: string,
466
493
  ops: PatchOp[],
467
494
  ifRev: string | undefined,
495
+ options: PatchCommitOptions | undefined,
468
496
  ) => Promise<SanityDocument>;
469
497
  }
470
498
 
@@ -480,7 +508,7 @@ export declare interface PatchHandle {
480
508
  items: unknown[],
481
509
  ) => PatchHandle;
482
510
  ifRevisionId: (rev: string) => PatchHandle;
483
- commit: () => Promise<SanityDocument>;
511
+ commit: (options?: PatchCommitOptions) => Promise<SanityDocument>;
484
512
  /** Test-only introspection — not on real Patch */
485
513
  toJSON: () => {
486
514
  id: string;
@@ -727,7 +755,7 @@ export declare interface TestClient {
727
755
  url?: string;
728
756
  uri?: string;
729
757
  signal?: AbortSignal;
730
- tag?: string;
758
+ tag?: string | null;
731
759
  }) => Promise<T>;
732
760
  create: <T extends SanityDocumentLike>(
733
761
  doc: T,
@@ -765,7 +793,10 @@ export declare interface TestClient {
765
793
  * Returns a synthetic `transactionId`. Multi-action arrays are applied
766
794
  * atomically — any failure rolls back the batch.
767
795
  */
768
- action: (action: Action | Action[]) => Promise<ActionResult>;
796
+ action: (
797
+ action: Action | Action[],
798
+ options?: ActionOptions,
799
+ ) => Promise<ActionResult>;
769
800
  /** Helpers mirroring `@sanity/client`'s `client.releases.*` surface. */
770
801
  releases: ReleasesHandle;
771
802
  /** Helper for `sanity.action.document.version.create`. */
@@ -987,6 +1018,12 @@ export declare interface TxnCommitOptions {
987
1018
  returnFirst?: boolean;
988
1019
  /** Override the synthetic transaction id (mirrors `client.transaction(undefined, { transactionId })`). */
989
1020
  transactionId?: string;
1021
+ /**
1022
+ * Request tag, recorded on the mutation log entry for assertions.
1023
+ * `null` mirrors `@sanity/client`'s explicit-suppression form and is
1024
+ * recorded as-is. No other behavior is simulated.
1025
+ */
1026
+ tag?: string | null;
990
1027
  }
991
1028
 
992
1029
  export declare type TxnCommitResult =
package/dist/index.js CHANGED
@@ -136,7 +136,7 @@ function createPatch(documentId, executor) {
136
136
  dec: (props) => (ops.push({ kind: "dec", props }), handle),
137
137
  insert: (position, anchor, items) => (ops.push({ kind: "insert", position, anchor, items }), handle),
138
138
  ifRevisionId: (rev) => (ifRev = rev, handle),
139
- commit: () => executor.apply(documentId, ops, ifRev),
139
+ commit: (options) => executor.apply(documentId, ops, ifRev, options),
140
140
  toJSON: () => ({
141
141
  id: documentId,
142
142
  ops: [...ops],
@@ -837,6 +837,25 @@ function wrapWithGuards(client, config) {
837
837
  }
838
838
  });
839
839
  }
840
+ const OPTIONS_ARG_POSITION = {
841
+ fetch: 2,
842
+ getDocument: 1,
843
+ getDocuments: 1,
844
+ create: 1,
845
+ createOrReplace: 1,
846
+ createIfNotExists: 1,
847
+ delete: 1,
848
+ mutate: 1,
849
+ action: 1,
850
+ request: 0
851
+ };
852
+ function tagFromArgs(method, args) {
853
+ const position = OPTIONS_ARG_POSITION[method];
854
+ if (position === void 0) return;
855
+ const options = args[position];
856
+ if (!(typeof options != "object" || options === null || !("tag" in options)))
857
+ return options.tag;
858
+ }
840
859
  const RECORDED_METHODS = /* @__PURE__ */ new Set([
841
860
  "fetch",
842
861
  "getDocument",
@@ -854,6 +873,15 @@ const RECORDED_METHODS = /* @__PURE__ */ new Set([
854
873
  "unpublishVersion",
855
874
  "request"
856
875
  ]), DEFAULT_PROJECT_ID = "test", DEFAULT_DATASET = "test";
876
+ function serializeWrite(backend, run) {
877
+ const result = backend.writeChain.then(run);
878
+ return backend.writeChain = result.then(
879
+ () => {
880
+ },
881
+ () => {
882
+ }
883
+ ), result;
884
+ }
857
885
  function requireIdentity(backend, token, site) {
858
886
  if (backend.identities.has(token)) return;
859
887
  const known = [...backend.identities.keys()];
@@ -878,7 +906,8 @@ function createTestClient(options = {}) {
878
906
  stubs: /* @__PURE__ */ new Map(),
879
907
  calls: [],
880
908
  concurrentEdits: /* @__PURE__ */ new Map(),
881
- identities: new Map(Object.entries(options.identities ?? {}))
909
+ identities: new Map(Object.entries(options.identities ?? {})),
910
+ writeChain: Promise.resolve()
882
911
  }, registry = backend.registry;
883
912
  rejectAmbiguousIdentity("createTestClient()", options), options.token !== void 0 && requireIdentity(backend, options.token, "createTestClient()");
884
913
  const ensureStore = (projectId, dataset) => {
@@ -967,8 +996,14 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
967
996
  const key = registryKey(projectId, dataset);
968
997
  let s = registry.get(key);
969
998
  return s === void 0 && (s = createTestStore(), registry.set(key, s)), s;
970
- })(), concurrentEditKey = (id) => registryKey(projectId, dataset) + " " + id, record = (transactionId, mutations) => {
971
- backend.log.push({ transactionId, projectId, dataset, mutations });
999
+ })(), concurrentEditKey = (id) => registryKey(projectId, dataset) + " " + id, record = (transactionId, mutations, tag) => {
1000
+ backend.log.push({
1001
+ transactionId,
1002
+ projectId,
1003
+ dataset,
1004
+ mutations,
1005
+ ...tag !== void 0 ? { tag } : {}
1006
+ });
972
1007
  }, writeResult = (documents, results, transactionId, opts) => formatMutationResult(
973
1008
  documents,
974
1009
  results,
@@ -1092,7 +1127,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1092
1127
  doc === void 0 ? store.remove(id) : store.put(doc);
1093
1128
  throw error;
1094
1129
  }
1095
- record(transactionId, mutations);
1130
+ record(transactionId, mutations, txnOptions?.tag);
1096
1131
  const documents = touchedIds.map((id) => store.get(id)).filter((d) => d !== void 0);
1097
1132
  return formatMutationResult(
1098
1133
  documents,
@@ -1101,7 +1136,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1101
1136
  txnOptions?.returnDocuments ?? !1,
1102
1137
  txnOptions?.returnFirst ?? !1
1103
1138
  );
1104
- }, accessVisibleDocs = async () => {
1139
+ }, runAction = (actions) => serializeWrite(backend, async () => applyActions(store, actions)), accessVisibleDocs = async () => {
1105
1140
  const all = store.all();
1106
1141
  if (activeAccess() === void 0) return all;
1107
1142
  const out = [];
@@ -1145,7 +1180,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1145
1180
  const view = await visibleDocs(effective);
1146
1181
  return ids.map((id) => resolveDocument(view, id, effective) ?? null);
1147
1182
  },
1148
- create: async (doc, opts) => {
1183
+ create: (doc, opts) => serializeWrite(backend, async () => {
1149
1184
  if (checkRevision(doc._id, opts?.ifRevisionId), store.get(doc._id) !== void 0)
1150
1185
  throw fakeError(
1151
1186
  `create() failed: a document with _id "${doc._id}" already exists in dataset "${projectId}:${dataset}". Use createOrReplace() to overwrite it, or createIfNotExists() to leave the existing one untouched.`
@@ -1153,19 +1188,19 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1153
1188
  const promoted = promote2(doc);
1154
1189
  await gate(promoted, "create"), await guardGate("create", null, promoted);
1155
1190
  const transactionId = opts?.transactionId ?? cryptoRandomKey();
1156
- return opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "create", doc }])), writeResult(
1191
+ return opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "create", doc }], opts?.tag)), writeResult(
1157
1192
  [promoted],
1158
1193
  [{ id: promoted._id, operation: "create" }],
1159
1194
  transactionId,
1160
1195
  opts
1161
1196
  );
1162
- },
1163
- createOrReplace: async (doc, opts) => {
1197
+ }),
1198
+ createOrReplace: (doc, opts) => serializeWrite(backend, async () => {
1164
1199
  checkRevision(doc._id, opts?.ifRevisionId);
1165
1200
  const promoted = promote2(doc), existing = store.get(doc._id);
1166
1201
  await gate(existing ?? promoted, existing !== void 0 ? "update" : "create"), await guardGate(existing !== void 0 ? "update" : "create", existing ?? null, promoted);
1167
1202
  const transactionId = opts?.transactionId ?? cryptoRandomKey();
1168
- opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "createOrReplace", doc }]));
1203
+ opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "createOrReplace", doc }], opts?.tag));
1169
1204
  const operation = existing !== void 0 ? "update" : "create";
1170
1205
  return writeResult(
1171
1206
  [promoted],
@@ -1173,8 +1208,8 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1173
1208
  transactionId,
1174
1209
  opts
1175
1210
  );
1176
- },
1177
- createIfNotExists: async (doc, opts) => {
1211
+ }),
1212
+ createIfNotExists: (doc, opts) => serializeWrite(backend, async () => {
1178
1213
  checkRevision(doc._id, opts?.ifRevisionId);
1179
1214
  const existing = store.get(doc._id), transactionId = opts?.transactionId ?? cryptoRandomKey();
1180
1215
  if (existing !== void 0)
@@ -1185,41 +1220,55 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1185
1220
  opts
1186
1221
  );
1187
1222
  const promoted = promote2(doc);
1188
- return await gate(promoted, "create"), await guardGate("create", null, promoted), opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "createIfNotExists", doc }])), writeResult(
1223
+ return await gate(promoted, "create"), await guardGate("create", null, promoted), opts?.dryRun !== !0 && (store.put(promoted), record(transactionId, [{ kind: "createIfNotExists", doc }], opts?.tag)), writeResult(
1189
1224
  [promoted],
1190
1225
  [{ id: promoted._id, operation: "create" }],
1191
1226
  transactionId,
1192
1227
  opts
1193
1228
  );
1194
- },
1195
- delete: async (id, opts) => {
1229
+ }),
1230
+ delete: (id, opts) => serializeWrite(backend, async () => {
1196
1231
  checkRevision(id, opts?.ifRevisionId);
1197
1232
  const existing = store.get(id);
1198
1233
  existing !== void 0 && await gate(existing, "update"), existing !== void 0 && await guardGate("delete", existing, null);
1199
1234
  const transactionId = opts?.transactionId ?? cryptoRandomKey();
1200
1235
  let removed = existing;
1201
- return opts?.dryRun !== !0 && (removed = store.remove(id), removed !== void 0 && record(transactionId, [{ kind: "delete", id }])), opts?.returnDocuments === void 0 && opts?.returnFirst === void 0 ? removed !== void 0 ? { _id: id } : null : formatMutationResult(
1236
+ return opts?.dryRun !== !0 && (removed = store.remove(id), removed !== void 0 && record(transactionId, [{ kind: "delete", id }], opts?.tag)), opts?.returnDocuments === void 0 && opts?.returnFirst === void 0 ? removed !== void 0 ? { _id: id } : null : formatMutationResult(
1202
1237
  removed !== void 0 ? [removed] : [],
1203
1238
  removed !== void 0 ? [{ id, operation: "delete" }] : [],
1204
1239
  transactionId,
1205
1240
  opts.returnDocuments ?? !0,
1206
1241
  opts.returnFirst ?? !0
1207
1242
  );
1208
- },
1243
+ }),
1209
1244
  patch: (documentId) => createPatch(documentId, {
1210
- apply: async (docId, ops, ifRev) => {
1245
+ apply: (docId, ops, ifRev, options) => serializeWrite(backend, async () => {
1211
1246
  const doc = await applyPatch(docId, ops, ifRev);
1212
- return record(cryptoRandomKey(), [
1213
- { kind: "patch", documentId: docId, ops, ...ifRev !== void 0 ? { ifRev } : {} }
1214
- ]), doc;
1215
- }
1247
+ return record(
1248
+ cryptoRandomKey(),
1249
+ [
1250
+ {
1251
+ kind: "patch",
1252
+ documentId: docId,
1253
+ ops,
1254
+ ...ifRev !== void 0 ? { ifRev } : {}
1255
+ }
1256
+ ],
1257
+ options?.tag
1258
+ ), doc;
1259
+ })
1260
+ }),
1261
+ transaction: () => createTransaction({
1262
+ apply: (mutations, txnOptions) => serializeWrite(backend, () => applyTransaction(mutations, txnOptions))
1216
1263
  }),
1217
- transaction: () => createTransaction({ apply: applyTransaction }),
1218
- mutate: async (operations, options) => applyTransaction(toTxnMutations(operations), options),
1219
- action: async (action) => applyActions(store, action),
1264
+ mutate: (operations, options) => serializeWrite(backend, () => applyTransaction(toTxnMutations(operations), options)),
1265
+ // Synchronous writes still take the lock: an action landing while a
1266
+ // guarded patch is parked in its gate would otherwise be clobbered
1267
+ // when that patch resumes over its pre-action snapshot.
1268
+ action: (action) => runAction(action),
1220
1269
  releases: {
1221
1270
  create: async ({ releaseId, metadata }) => {
1222
- const result = applyActions(store, {
1271
+ const result = await runAction({
1223
1272
  actionType: "sanity.action.release.create",
1224
1273
  releaseId,
1225
1274
  ...metadata !== void 0 ? { metadata } : {}
@@ -1230,30 +1279,30 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1230
1279
  metadata: doc?.metadata ?? { releaseType: "undecided" }
1231
1280
  };
1232
1281
  },
1233
- edit: async ({ releaseId, patch }) => applyActions(store, { actionType: "sanity.action.release.edit", releaseId, patch }),
1282
+ edit: ({ releaseId, patch }) => runAction({ actionType: "sanity.action.release.edit", releaseId, patch }),
1234
1283
  get: async ({ releaseId }) => store.get(`_.releases.${releaseId}`),
1235
1284
  fetchDocuments: async ({ releaseId }) => {
1236
1285
  const prefix = `versions.${releaseId}.`;
1237
1286
  return store.all().filter((d) => d._id.startsWith(prefix));
1238
1287
  },
1239
- schedule: async ({ releaseId, publishAt }) => applyActions(store, {
1288
+ schedule: ({ releaseId, publishAt }) => runAction({
1240
1289
  actionType: "sanity.action.release.schedule",
1241
1290
  releaseId,
1242
1291
  publishAt
1243
1292
  }),
1244
- unschedule: async ({ releaseId }) => applyActions(store, { actionType: "sanity.action.release.unschedule", releaseId }),
1245
- publish: async ({ releaseId }) => applyActions(store, { actionType: "sanity.action.release.publish", releaseId }),
1246
- archive: async ({ releaseId }) => applyActions(store, { actionType: "sanity.action.release.archive", releaseId }),
1247
- unarchive: async ({ releaseId }) => applyActions(store, { actionType: "sanity.action.release.unarchive", releaseId }),
1248
- delete: async ({ releaseId }) => applyActions(store, { actionType: "sanity.action.release.delete", releaseId })
1293
+ unschedule: ({ releaseId }) => runAction({ actionType: "sanity.action.release.unschedule", releaseId }),
1294
+ publish: ({ releaseId }) => runAction({ actionType: "sanity.action.release.publish", releaseId }),
1295
+ archive: ({ releaseId }) => runAction({ actionType: "sanity.action.release.archive", releaseId }),
1296
+ unarchive: ({ releaseId }) => runAction({ actionType: "sanity.action.release.unarchive", releaseId }),
1297
+ delete: ({ releaseId }) => runAction({ actionType: "sanity.action.release.delete", releaseId })
1249
1298
  },
1250
- createVersion: async ({ releaseId, publishedId, document }) => applyActions(store, {
1299
+ createVersion: ({ releaseId, publishedId, document }) => runAction({
1251
1300
  actionType: "sanity.action.document.version.create",
1252
1301
  releaseId,
1253
1302
  publishedId,
1254
1303
  document
1255
1304
  }),
1256
- unpublishVersion: async ({ releaseId, publishedId }) => applyActions(store, {
1305
+ unpublishVersion: ({ releaseId, publishedId }) => runAction({
1257
1306
  actionType: "sanity.action.document.version.unpublish",
1258
1307
  versionId: `versions.${releaseId}.${publishedId}`,
1259
1308
  publishedId
@@ -1305,8 +1354,8 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
1305
1354
  return wrapWithGuards(client, {
1306
1355
  getStub: (name) => backend.stubs.get(name),
1307
1356
  onCall: (method, args) => {
1308
- const rec = { method, args, projectId, dataset };
1309
- return backend.calls.push(rec), (outcome) => {
1357
+ const rec = { method, args, projectId, dataset }, tag = tagFromArgs(method, args);
1358
+ return tag !== void 0 && (rec.tag = tag), backend.calls.push(rec), (outcome) => {
1310
1359
  "error" in outcome ? rec.error = outcome.error : rec.result = outcome.result;
1311
1360
  };
1312
1361
  },