@sanity/sdk 2.12.0 → 2.14.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.
Files changed (49) hide show
  1. package/dist/_chunks-dts/createGroqSearchFilter.d.ts +925 -0
  2. package/dist/_chunks-dts/createGroqSearchFilter.d.ts.map +1 -0
  3. package/dist/_chunks-es/createGroqSearchFilter.js +261 -225
  4. package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
  5. package/dist/_chunks-es/version.js +1 -1
  6. package/dist/_exports/_internal.d.ts +3 -2
  7. package/dist/_exports/_internal.d.ts.map +1 -0
  8. package/dist/index.d.ts +1856 -2
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +207 -133
  11. package/dist/index.js.map +1 -1
  12. package/package.json +11 -11
  13. package/src/auth/authLogger.ts +30 -0
  14. package/src/auth/authStore.test.ts +96 -1
  15. package/src/auth/authStore.ts +55 -24
  16. package/src/auth/handleAuthCallback.test.ts +23 -1
  17. package/src/auth/handleAuthCallback.ts +25 -6
  18. package/src/auth/logout.test.ts +68 -1
  19. package/src/auth/logout.ts +22 -3
  20. package/src/auth/refreshStampedToken.test.ts +15 -0
  21. package/src/auth/refreshStampedToken.ts +12 -1
  22. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +17 -2
  23. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +9 -0
  24. package/src/document/applyDocumentActions.test.ts +24 -0
  25. package/src/document/applyDocumentActions.ts +13 -2
  26. package/src/document/documentConstants.ts +7 -0
  27. package/src/document/documentStore.test.ts +69 -0
  28. package/src/document/documentStore.ts +36 -5
  29. package/src/document/listen.ts +1 -1
  30. package/src/document/permissions.test.ts +79 -0
  31. package/src/document/permissions.ts +8 -7
  32. package/src/document/processActions/create.ts +7 -4
  33. package/src/document/processActions/delete.ts +4 -4
  34. package/src/document/processActions/discard.ts +2 -2
  35. package/src/document/processActions/edit.ts +4 -3
  36. package/src/document/processActions/processActions.ts +9 -0
  37. package/src/document/processActions/publish.ts +4 -4
  38. package/src/document/processActions/releaseArchive.ts +4 -4
  39. package/src/document/processActions/releaseCreate.ts +2 -2
  40. package/src/document/processActions/releaseDelete.ts +2 -2
  41. package/src/document/processActions/releaseEdit.ts +2 -1
  42. package/src/document/processActions/releasePublish.ts +2 -2
  43. package/src/document/processActions/releaseSchedule.ts +4 -4
  44. package/src/document/processActions/shared.ts +15 -3
  45. package/src/document/processActions/unpublish.ts +3 -3
  46. package/src/document/reducers.ts +4 -3
  47. package/src/document/resourceRules.test.ts +178 -0
  48. package/src/document/resourceRules.ts +117 -0
  49. package/dist/_chunks-dts/utils.d.ts +0 -2774
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { switchMap, from, firstValueFrom, EMPTY, asapScheduler, distinctUntilChanged, map as map$1, combineLatest, of, concatMap, withLatestFrom, filter as filter$1, concat, timer, throwError, first as first$1, Subject, takeUntil, share, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, skip, Observable, NEVER, fromEvent, Subscription, debounceTime, defer } from "rxjs";
2
- import { createLogger, pickProperties, insecureRandomId, getClientState, bindActionGlobally, createStateSourceAction, setCleanupTimeout, omitProperty, defineStore, authStore, AuthStateType, getCleanedUrl, getTokenFromLocation, createLoggedInAuthState, getAuthCode, REQUEST_TAG_PREFIX, DEFAULT_API_VERSION, getDefaultLocation, isDeepEqual, configureLogging as configureLogging$1, isReleasePerspective, bindActionByResource, isDatasetResource, isMediaLibraryResource, isCanvasResource, getUsersKey, addSubscription, parseUsersKey, getClient, PROJECT_API_VERSION, setUsersError, setUsersData, API_VERSION as API_VERSION$8, getDashboardOrganizationId as getDashboardOrganizationId$1, USERS_STATE_CLEAR_DELAY, removeSubscription, updateLastLoadMoreRequest, cancelRequest, initializeRequest, getTokenState, getQueryState, resolveQuery, bindActionByResourceAndPerspective, PREVIEW_PROJECTION, transformProjectionToPreview } from "./_chunks-es/createGroqSearchFilter.js";
3
- import { createGroqSearchFilter, getActiveReleasesState, getAllReleasesState, getAuthState, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType, getCurrentUserState, getIsInDashboardState, getLoginUrlState, getPerspectiveState, getQueryKey, isCanvasSource, isDatasetSource, isMediaLibrarySource, isProjectUserNotFoundClientError, isStudioConfig, parseQueryKey, setAuthToken } from "./_chunks-es/createGroqSearchFilter.js";
1
+ import { switchMap, from, firstValueFrom, EMPTY, asapScheduler, distinctUntilChanged, map as map$1, combineLatest, of, concatMap, withLatestFrom, filter as filter$1, concat, timer, throwError, first as first$1, Subject, takeUntil, share, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, retry, throttle, race, skip, Observable, NEVER, fromEvent, Subscription, debounceTime, defer } from "rxjs";
2
+ import { createLogger, pickProperties, insecureRandomId, getClientState, bindActionGlobally, createStateSourceAction, setCleanupTimeout, omitProperty, defineStore, authStore, getAuthLogger, AuthStateType, getCleanedUrl, getTokenFromLocation, createLoggedInAuthState, getAuthCode, REQUEST_TAG_PREFIX, DEFAULT_API_VERSION, getDefaultLocation, isDeepEqual, configureLogging as configureLogging$1, isReleasePerspective, bindActionByResource, isDatasetResource, isMediaLibraryResource, isCanvasResource, getCurrentUserState, getUsersKey, addSubscription, USERS_STATE_CLEAR_DELAY, removeSubscription, parseUsersKey, getClient, PROJECT_API_VERSION, setUsersError, setUsersData, API_VERSION as API_VERSION$8, getDashboardOrganizationId as getDashboardOrganizationId$1, updateLastLoadMoreRequest, cancelRequest, initializeRequest, getTokenState, getQueryState, resolveQuery, bindActionByResourceAndPerspective, PREVIEW_PROJECTION, transformProjectionToPreview } from "./_chunks-es/createGroqSearchFilter.js";
3
+ import { createGroqSearchFilter, getActiveReleasesState, getAllReleasesState, getAuthState, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType, getIsInDashboardState, getLoginUrlState, getPerspectiveState, getQueryKey, isCanvasSource, isDatasetSource, isMediaLibrarySource, isProjectUserNotFoundClientError, isStudioConfig, parseQueryKey, setAuthToken } from "./_chunks-es/createGroqSearchFilter.js";
4
4
  import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter, map, delay, tap, catchError, scan, share as share$1 } from "rxjs/operators";
5
5
  import { createController, createNode } from "@sanity/comlink";
6
6
  import { createSelector } from "reselect";
@@ -328,30 +328,35 @@ function observeOrganizationVerificationState(instance, projectIds) {
328
328
  }
329
329
  const handleAuthCallback = bindActionGlobally(
330
330
  authStore,
331
- async ({ state }, locationHref = getDefaultLocation()) => {
332
- const { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey } = state.get().options;
333
- if (providedToken) return !1;
331
+ async ({ state, instance }, locationHref = getDefaultLocation()) => {
332
+ const logger = getAuthLogger(instance), { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey } = state.get().options;
333
+ if (providedToken)
334
+ return logger.debug("Skipping auth callback - token already provided"), !1;
334
335
  const { authState } = state.get();
335
- if (authState.type === AuthStateType.LOGGING_IN && authState.isExchangingToken) return !1;
336
+ if (authState.type === AuthStateType.LOGGING_IN && authState.isExchangingToken)
337
+ return logger.debug("Skipping auth callback - token exchange already in progress"), !1;
336
338
  const cleanedUrl = getCleanedUrl(locationHref), tokenFromUrl = getTokenFromLocation(locationHref);
337
339
  if (tokenFromUrl)
338
- return state.set("setTokenFromUrl", {
340
+ return logger.info("Auth token found in URL, logging in"), state.set("setTokenFromUrl", {
339
341
  authState: createLoggedInAuthState(tokenFromUrl, null)
340
342
  }), cleanedUrl;
341
343
  const authCode = getAuthCode(callbackUrl, locationHref);
342
- if (!authCode) return !1;
344
+ if (!authCode)
345
+ return logger.debug("No auth code found in callback URL"), !1;
343
346
  const parsedUrl = new URL(locationHref);
344
347
  let dashboardContext = {};
345
348
  try {
346
349
  const contextParam = parsedUrl.searchParams.get("_context");
347
350
  if (contextParam) {
348
351
  const parsedContext = JSON.parse(contextParam);
349
- parsedContext && typeof parsedContext == "object" && (delete parsedContext.sid, dashboardContext = parsedContext);
352
+ parsedContext && typeof parsedContext == "object" && (delete parsedContext.sid, dashboardContext = parsedContext, logger.debug("Dashboard context parsed from callback URL", {
353
+ hasDashboardContext: !0
354
+ }));
350
355
  }
351
356
  } catch (err) {
352
- console.error("Failed to parse dashboard context:", err);
357
+ logger.warn("Failed to parse dashboard context from callback URL", { error: err });
353
358
  }
354
- state.set("exchangeSessionForToken", {
359
+ logger.info("Exchanging auth code for token"), state.set("exchangeSessionForToken", {
355
360
  authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !0 },
356
361
  dashboardContext
357
362
  });
@@ -362,36 +367,51 @@ const handleAuthCallback = bindActionGlobally(
362
367
  useProjectHostname: !1,
363
368
  useCdn: !1,
364
369
  ...apiHost && { apiHost }
365
- }), { token } = await client.request({
370
+ });
371
+ logger.debug("Fetching token from auth endpoint");
372
+ const { token } = await client.request({
366
373
  method: "GET",
367
374
  uri: "/auth/fetch",
368
375
  query: { sid: authCode },
369
376
  tag: "fetch-token"
370
377
  });
371
- return storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: createLoggedInAuthState(token, null) }), cleanedUrl;
378
+ return logger.info("Auth token obtained successfully, user logged in"), storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: createLoggedInAuthState(token, null) }), cleanedUrl;
372
379
  } catch (error) {
373
- return state.set("exchangeSessionForTokenError", { authState: { type: AuthStateType.ERROR, error } }), cleanedUrl;
380
+ return logger.error("Failed to exchange auth code for token", { error }), state.set("exchangeSessionForTokenError", { authState: { type: AuthStateType.ERROR, error } }), cleanedUrl;
374
381
  }
375
382
  }
376
- ), logout = bindActionGlobally(authStore, async ({ state }) => {
377
- const { clientFactory, apiHost, providedToken, storageArea, storageKey } = state.get().options;
378
- if (providedToken) return;
383
+ ), logout = bindActionGlobally(authStore, async ({ state, instance }) => {
384
+ const logger = getAuthLogger(instance), { clientFactory, apiHost, providedToken, storageArea, storageKey } = state.get().options;
385
+ if (providedToken) {
386
+ logger.debug("Skipping logout - token is statically provided");
387
+ return;
388
+ }
379
389
  const { authState } = state.get();
380
- if (authState.type === AuthStateType.LOGGED_OUT && authState.isDestroyingSession) return;
390
+ if (authState.type === AuthStateType.LOGGED_OUT && authState.isDestroyingSession) {
391
+ logger.debug("Skipping logout - already in progress");
392
+ return;
393
+ }
381
394
  const token = authState.type === AuthStateType.LOGGED_IN && authState.token;
382
395
  try {
383
- token && (state.set("loggingOut", {
384
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !0 }
385
- }), await clientFactory({
386
- token,
387
- requestTagPrefix: REQUEST_TAG_PREFIX,
388
- apiVersion: DEFAULT_API_VERSION,
389
- ...apiHost && { apiHost },
390
- useProjectHostname: !1,
391
- useCdn: !1
392
- }).request({ uri: "/auth/logout", method: "POST", tag: "logout" }));
396
+ if (token) {
397
+ logger.info("Logging out user"), state.set("loggingOut", {
398
+ authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !0 }
399
+ });
400
+ const client = clientFactory({
401
+ token,
402
+ requestTagPrefix: REQUEST_TAG_PREFIX,
403
+ apiVersion: DEFAULT_API_VERSION,
404
+ ...apiHost && { apiHost },
405
+ useProjectHostname: !1,
406
+ useCdn: !1
407
+ });
408
+ logger.debug("Calling logout endpoint"), await client.request({ uri: "/auth/logout", method: "POST", tag: "logout" });
409
+ } else
410
+ logger.debug("No token to logout - already logged out");
411
+ } catch (error) {
412
+ throw logger.error("Logout request failed", { error }), error;
393
413
  } finally {
394
- state.set("logoutSuccess", {
414
+ logger.info("User logged out, clearing stored tokens"), state.set("logoutSuccess", {
395
415
  authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
396
416
  }), storageArea?.removeItem(storageKey), storageArea?.removeItem(`${storageKey}_last_refresh`);
397
417
  }
@@ -519,7 +539,7 @@ const handleAuthCallback = bindActionGlobally(
519
539
  status: nodeEntry.status
520
540
  } : void 0),
521
541
  onSubscribe: ({ state, instance }, nodeInput) => {
522
- const nodeName = nodeInput.name, subscriberId = Symbol("comlink-node-subscriber");
542
+ const nodeName = nodeInput.name, subscriberId = /* @__PURE__ */ Symbol("comlink-node-subscriber");
523
543
  getOrCreateNode(instance, nodeInput);
524
544
  let subs = state.get().subscriptions.get(nodeName);
525
545
  return subs || (subs = /* @__PURE__ */ new Set(), state.get().subscriptions.set(nodeName, subs)), subs.add(subscriberId), () => {
@@ -666,7 +686,7 @@ function unarchiveRelease(handle) {
666
686
  function deleteRelease(handle) {
667
687
  return { type: "release.delete", ...handle };
668
688
  }
669
- const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$4 = "v2025-05-06", RELEASE_DOCUMENTS_PATH = "_.releases";
689
+ const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$4 = "v2025-05-06", OUT_OF_SYNC_RETRY_BASE_DELAY = 500, OUT_OF_SYNC_RETRY_MAX_DELAY = 1e4, RELEASE_DOCUMENTS_PATH = "_.releases";
670
690
  function getReleaseDocumentId(releaseId) {
671
691
  return `${RELEASE_DOCUMENTS_PATH}.${releaseId}`;
672
692
  }
@@ -1186,6 +1206,52 @@ class MultiKeyWeakMap {
1186
1206
  this.#setDeep(arrangedKeys, this.#rootMap, value);
1187
1207
  }
1188
1208
  }
1209
+ function checkGrant(grantExpr, document, identity) {
1210
+ const value = evaluateSync(grantExpr, { params: { document }, identity });
1211
+ return value.type === "boolean" && value.data;
1212
+ }
1213
+ class ActionError extends Error {
1214
+ documentId;
1215
+ transactionId;
1216
+ constructor(options) {
1217
+ super(options.message), Object.assign(this, options);
1218
+ }
1219
+ }
1220
+ class PermissionActionError extends ActionError {
1221
+ }
1222
+ function applySingleDocPatch({
1223
+ base: initialBase,
1224
+ working: initialWorking,
1225
+ documentId,
1226
+ patches,
1227
+ transactionId,
1228
+ timestamp,
1229
+ grants,
1230
+ identity,
1231
+ notFoundMessage = "Cannot edit document because it does not exist.",
1232
+ permissionMessage = `You do not have permission to edit document "${documentId}".`
1233
+ }) {
1234
+ let base = initialBase, working = initialWorking;
1235
+ const userPatches = patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
1236
+ if (!userPatches?.length)
1237
+ return { base, working, diffedPatches: [], workingMutations: [] };
1238
+ if (!working[documentId] || !base[documentId])
1239
+ throw new ActionError({ documentId, transactionId, message: notFoundMessage });
1240
+ const baseBefore = base[documentId];
1241
+ base = processMutations({ documents: base, transactionId, mutations: userPatches, timestamp });
1242
+ const baseAfter = base[documentId], diffedPatches = diffValue(baseBefore, baseAfter), workingBefore = working[documentId];
1243
+ if (!checkGrant(grants.update, workingBefore, identity))
1244
+ throw new PermissionActionError({ documentId, transactionId, message: permissionMessage });
1245
+ const workingMutations = diffedPatches.map((patch) => ({
1246
+ patch: { id: documentId, ...patch }
1247
+ }));
1248
+ return working = processMutations({
1249
+ documents: working,
1250
+ transactionId,
1251
+ mutations: workingMutations,
1252
+ timestamp
1253
+ }), { base, working, diffedPatches, workingMutations };
1254
+ }
1189
1255
  function createGrantsLookup(datasetAcl) {
1190
1256
  const filtersByGrant = {
1191
1257
  create: /* @__PURE__ */ new Set(),
@@ -1196,7 +1262,7 @@ function createGrantsLookup(datasetAcl) {
1196
1262
  for (const entry of datasetAcl)
1197
1263
  for (const grant of entry.permissions) {
1198
1264
  const set2 = filtersByGrant[grant];
1199
- set2.add(entry.filter), filtersByGrant[grant] = set2;
1265
+ set2 && (set2.add(entry.filter), filtersByGrant[grant] = set2);
1200
1266
  }
1201
1267
  return Object.fromEntries(
1202
1268
  Object.entries(filtersByGrant).map(([grant, filters]) => {
@@ -1246,22 +1312,18 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
1246
1312
  const normalizedActions = Array.isArray(actions) ? actions : [actions], actionsKey = JSON.stringify(normalizedActions);
1247
1313
  return nestedCache.get(actionsKey) || (nestedCache.set(actionsKey, normalizedActions), normalizedActions);
1248
1314
  }
1249
- );
1250
- function checkGrant$1(grantExpr, document) {
1251
- const value = evaluateSync(grantExpr, { params: { document } });
1252
- return value.type === "boolean" && value.data;
1253
- }
1254
- const enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
1315
+ ), enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
1255
1316
  function calculatePermissions(...args) {
1256
1317
  return _calculatePermissions(...args);
1257
1318
  }
1258
1319
  const _calculatePermissions = createSelector(
1259
1320
  [
1260
1321
  ({ state: { grants } }) => grants,
1322
+ ({ state: { identity } }) => identity,
1261
1323
  documentsSelector,
1262
1324
  memoizedActionsSelector
1263
1325
  ],
1264
- (grants, documents, actions) => {
1326
+ (grants, identity, documents, actions) => {
1265
1327
  if (!documents || !grants || !actions) return;
1266
1328
  const timestamp = (/* @__PURE__ */ new Date()).toISOString(), reasons = [];
1267
1329
  try {
@@ -1271,7 +1333,8 @@ const _calculatePermissions = createSelector(
1271
1333
  working: documents,
1272
1334
  base: documents,
1273
1335
  timestamp,
1274
- grants
1336
+ grants,
1337
+ identity
1275
1338
  });
1276
1339
  } catch (error) {
1277
1340
  if (error instanceof PermissionActionError)
@@ -1293,7 +1356,7 @@ const _calculatePermissions = createSelector(
1293
1356
  if (action.type === "document.edit" && !action.patches?.length) {
1294
1357
  const docId = action.documentId;
1295
1358
  let doc;
1296
- action.liveEdit ? doc = documents[docId] : isReleasePerspective(action.perspective) ? doc = documents[getVersionId(DocumentId(docId), action.perspective.releaseName)] : doc = documents[getDraftId(DocumentId(docId))] ?? documents[getPublishedId(DocumentId(docId))], doc ? checkGrant$1(grants.update, doc) || reasons.push({
1359
+ action.liveEdit ? doc = documents[docId] : isReleasePerspective(action.perspective) ? doc = documents[getVersionId(DocumentId(docId), action.perspective.releaseName)] : doc = documents[getDraftId(DocumentId(docId))] ?? documents[getPublishedId(DocumentId(docId))], doc ? checkGrant(grants.update, doc, identity) || reasons.push({
1297
1360
  type: "access",
1298
1361
  message: `You are not allowed to edit the document with ID "${docId}".`,
1299
1362
  documentId: docId
@@ -1317,53 +1380,8 @@ const _calculatePermissions = createSelector(
1317
1380
  };
1318
1381
  }
1319
1382
  );
1320
- function checkGrant(grantExpr, document) {
1321
- const value = evaluateSync(grantExpr, { params: { document } });
1322
- return value.type === "boolean" && value.data;
1323
- }
1324
- class ActionError extends Error {
1325
- documentId;
1326
- transactionId;
1327
- constructor(options) {
1328
- super(options.message), Object.assign(this, options);
1329
- }
1330
- }
1331
- class PermissionActionError extends ActionError {
1332
- }
1333
- function applySingleDocPatch({
1334
- base: initialBase,
1335
- working: initialWorking,
1336
- documentId,
1337
- patches,
1338
- transactionId,
1339
- timestamp,
1340
- grants,
1341
- notFoundMessage = "Cannot edit document because it does not exist.",
1342
- permissionMessage = `You do not have permission to edit document "${documentId}".`
1343
- }) {
1344
- let base = initialBase, working = initialWorking;
1345
- const userPatches = patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
1346
- if (!userPatches?.length)
1347
- return { base, working, diffedPatches: [], workingMutations: [] };
1348
- if (!working[documentId] || !base[documentId])
1349
- throw new ActionError({ documentId, transactionId, message: notFoundMessage });
1350
- const baseBefore = base[documentId];
1351
- base = processMutations({ documents: base, transactionId, mutations: userPatches, timestamp });
1352
- const baseAfter = base[documentId], diffedPatches = diffValue(baseBefore, baseAfter), workingBefore = working[documentId];
1353
- if (!checkGrant(grants.update, workingBefore))
1354
- throw new PermissionActionError({ documentId, transactionId, message: permissionMessage });
1355
- const workingMutations = diffedPatches.map((patch) => ({
1356
- patch: { id: documentId, ...patch }
1357
- }));
1358
- return working = processMutations({
1359
- documents: working,
1360
- transactionId,
1361
- mutations: workingMutations,
1362
- timestamp
1363
- }), { base, working, diffedPatches, workingMutations };
1364
- }
1365
1383
  function handleCreate(action, ctx) {
1366
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1384
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1367
1385
  let { base, working } = ctx;
1368
1386
  const documentId = getId(action.documentId);
1369
1387
  if (action.liveEdit) {
@@ -1388,7 +1406,7 @@ function handleCreate(action, ctx) {
1388
1406
  transactionId,
1389
1407
  mutations: mutations2,
1390
1408
  timestamp
1391
- }), !checkGrant(grants.create, working[documentId]))
1409
+ }), !checkGrant(grants.create, working[documentId], identity))
1392
1410
  throw new PermissionActionError({
1393
1411
  documentId,
1394
1412
  transactionId,
@@ -1426,13 +1444,13 @@ function handleCreate(action, ctx) {
1426
1444
  transactionId,
1427
1445
  mutations,
1428
1446
  timestamp
1429
- }), versionId && !checkGrant(grants.create, working[versionId]))
1447
+ }), versionId && !checkGrant(grants.create, working[versionId], identity))
1430
1448
  throw new PermissionActionError({
1431
1449
  documentId,
1432
1450
  transactionId,
1433
1451
  message: `You do not have permission to create a release version for document "${documentId}".`
1434
1452
  });
1435
- if (!versionId && !checkGrant(grants.create, working[draftId]))
1453
+ if (!versionId && !checkGrant(grants.create, working[draftId], identity))
1436
1454
  throw new PermissionActionError({
1437
1455
  documentId,
1438
1456
  transactionId,
@@ -1445,7 +1463,7 @@ function handleCreate(action, ctx) {
1445
1463
  }), { base, working };
1446
1464
  }
1447
1465
  function handleDelete(action, ctx) {
1448
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1466
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1449
1467
  let { base, working } = ctx;
1450
1468
  const documentId = action.documentId;
1451
1469
  if (isReleasePerspective(action.perspective))
@@ -1461,7 +1479,7 @@ function handleDelete(action, ctx) {
1461
1479
  transactionId,
1462
1480
  message: "The document you are trying to delete does not exist."
1463
1481
  });
1464
- if (!checkGrant(grants.update, working[documentId]))
1482
+ if (!checkGrant(grants.update, working[documentId], identity))
1465
1483
  throw new PermissionActionError({
1466
1484
  documentId,
1467
1485
  transactionId,
@@ -1477,7 +1495,7 @@ function handleDelete(action, ctx) {
1477
1495
  transactionId,
1478
1496
  message: working[draftId] ? "Cannot delete a document without a published version." : "The document you are trying to delete does not exist."
1479
1497
  });
1480
- const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId]), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId]);
1498
+ const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId], identity), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId], identity);
1481
1499
  if (cantDeleteDraft || cantDeletePublished)
1482
1500
  throw new PermissionActionError({
1483
1501
  documentId,
@@ -1492,7 +1510,7 @@ function handleDelete(action, ctx) {
1492
1510
  }), { base, working };
1493
1511
  }
1494
1512
  function handleDiscard(action, ctx) {
1495
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1513
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1496
1514
  let { base, working } = ctx;
1497
1515
  const documentId = getId(action.documentId);
1498
1516
  if (action.liveEdit)
@@ -1508,7 +1526,7 @@ function handleDiscard(action, ctx) {
1508
1526
  transactionId,
1509
1527
  message: `There is no draft or version available to discard for document "${documentId}".`
1510
1528
  });
1511
- if (!checkGrant(grants.update, working[versionId]))
1529
+ if (!checkGrant(grants.update, working[versionId], identity))
1512
1530
  throw new PermissionActionError({
1513
1531
  documentId,
1514
1532
  transactionId,
@@ -1520,7 +1538,7 @@ function handleDiscard(action, ctx) {
1520
1538
  }), { base, working };
1521
1539
  }
1522
1540
  function handleEdit(action, ctx) {
1523
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1541
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1524
1542
  let { base, working } = ctx;
1525
1543
  const documentId = getId(action.documentId);
1526
1544
  if (action.liveEdit) {
@@ -1531,7 +1549,8 @@ function handleEdit(action, ctx) {
1531
1549
  patches: action.patches,
1532
1550
  transactionId,
1533
1551
  timestamp,
1534
- grants
1552
+ grants,
1553
+ identity
1535
1554
  });
1536
1555
  return outgoingMutations.push(...result.workingMutations), { base: result.base, working: result.working };
1537
1556
  }
@@ -1564,7 +1583,7 @@ function handleEdit(action, ctx) {
1564
1583
  const baseAfter = base[patchDocumentId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
1565
1584
  if (!isReleasePerspective(action.perspective) && !working[draftId] && working[publishedId]) {
1566
1585
  const newDraftFromPublished = { ...working[publishedId], _id: draftId };
1567
- if (!checkGrant(grants.create, newDraftFromPublished))
1586
+ if (!checkGrant(grants.create, newDraftFromPublished, identity))
1568
1587
  throw new PermissionActionError({
1569
1588
  documentId,
1570
1589
  transactionId,
@@ -1573,7 +1592,7 @@ function handleEdit(action, ctx) {
1573
1592
  workingMutations.push({ create: newDraftFromPublished });
1574
1593
  }
1575
1594
  const workingBefore = working[patchDocumentId] ?? working[publishedId];
1576
- if (!checkGrant(grants.update, workingBefore))
1595
+ if (!checkGrant(grants.update, workingBefore, identity))
1577
1596
  throw new PermissionActionError({
1578
1597
  documentId,
1579
1598
  transactionId,
@@ -1594,7 +1613,7 @@ function handleEdit(action, ctx) {
1594
1613
  ), { base, working };
1595
1614
  }
1596
1615
  function handlePublish(action, ctx) {
1597
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1616
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1598
1617
  let { base, working } = ctx;
1599
1618
  const documentId = getId(action.documentId);
1600
1619
  if (action.liveEdit || isReleasePerspective(action.perspective))
@@ -1617,19 +1636,19 @@ function handlePublish(action, ctx) {
1617
1636
  message: "Publish aborted: The document has changed elsewhere. Please try again."
1618
1637
  });
1619
1638
  const newPublishedFromDraft = { ...strengthenOnPublish(workingDraft), _id: publishedId }, mutations = [{ delete: { id: draftId } }, { createOrReplace: newPublishedFromDraft }];
1620
- if (working[draftId] && !checkGrant(grants.update, working[draftId]))
1639
+ if (working[draftId] && !checkGrant(grants.update, working[draftId], identity))
1621
1640
  throw new PermissionActionError({
1622
1641
  documentId,
1623
1642
  transactionId,
1624
1643
  message: `Publish failed: You do not have permission to update the draft for "${documentId}".`
1625
1644
  });
1626
- if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft))
1645
+ if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft, identity))
1627
1646
  throw new PermissionActionError({
1628
1647
  documentId,
1629
1648
  transactionId,
1630
1649
  message: `Publish failed: You do not have permission to update the published version of "${documentId}".`
1631
1650
  });
1632
- if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft))
1651
+ if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft, identity))
1633
1652
  throw new PermissionActionError({
1634
1653
  documentId,
1635
1654
  transactionId,
@@ -1657,14 +1676,14 @@ function strengthenOnPublish(draft) {
1657
1676
  return strengthen(draft);
1658
1677
  }
1659
1678
  function handleReleaseArchive(action, ctx) {
1660
- const { base, working, grants, outgoingActions, transactionId } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1679
+ const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1661
1680
  if (!existing)
1662
1681
  throw new ActionError({
1663
1682
  documentId: releaseDocumentId,
1664
1683
  transactionId,
1665
1684
  message: `Cannot archive release "${action.releaseId}" because it does not exist.`
1666
1685
  });
1667
- if (!checkGrant(grants.update, existing))
1686
+ if (!checkGrant(grants.update, existing, identity))
1668
1687
  throw new PermissionActionError({
1669
1688
  documentId: releaseDocumentId,
1670
1689
  transactionId,
@@ -1676,14 +1695,14 @@ function handleReleaseArchive(action, ctx) {
1676
1695
  }), { base, working };
1677
1696
  }
1678
1697
  function handleReleaseUnarchive(action, ctx) {
1679
- const { base, working, grants, outgoingActions, transactionId } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1698
+ const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1680
1699
  if (!existing)
1681
1700
  throw new ActionError({
1682
1701
  documentId: releaseDocumentId,
1683
1702
  transactionId,
1684
1703
  message: `Cannot unarchive release "${action.releaseId}" because it does not exist.`
1685
1704
  });
1686
- if (!checkGrant(grants.update, existing))
1705
+ if (!checkGrant(grants.update, existing, identity))
1687
1706
  throw new PermissionActionError({
1688
1707
  documentId: releaseDocumentId,
1689
1708
  transactionId,
@@ -1695,7 +1714,7 @@ function handleReleaseUnarchive(action, ctx) {
1695
1714
  }), { base, working };
1696
1715
  }
1697
1716
  function handleReleaseCreate(action, ctx) {
1698
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1717
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx;
1699
1718
  let { base, working } = ctx;
1700
1719
  const releaseDocumentId = getReleaseDocumentId(action.releaseId);
1701
1720
  if (working[releaseDocumentId] || base[releaseDocumentId])
@@ -1711,7 +1730,7 @@ function handleReleaseCreate(action, ctx) {
1711
1730
  state: "active",
1712
1731
  metadata: action.metadata
1713
1732
  } }];
1714
- if (base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), !checkGrant(grants.create, working[releaseDocumentId]))
1733
+ if (base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), !checkGrant(grants.create, working[releaseDocumentId], identity))
1715
1734
  throw new PermissionActionError({
1716
1735
  documentId: releaseDocumentId,
1717
1736
  transactionId,
@@ -1725,7 +1744,7 @@ function handleReleaseCreate(action, ctx) {
1725
1744
  }
1726
1745
  const DELETABLE_STATES = /* @__PURE__ */ new Set(["archived", "published"]);
1727
1746
  function handleReleaseDelete(action, ctx) {
1728
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1747
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx;
1729
1748
  let { base, working } = ctx;
1730
1749
  const releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1731
1750
  if (!existing)
@@ -1741,7 +1760,7 @@ function handleReleaseDelete(action, ctx) {
1741
1760
  transactionId,
1742
1761
  message: `Cannot delete release "${action.releaseId}" while it is "${state}". Archive it first.`
1743
1762
  });
1744
- if (!checkGrant(grants.update, existing))
1763
+ if (!checkGrant(grants.update, existing, identity))
1745
1764
  throw new PermissionActionError({
1746
1765
  documentId: releaseDocumentId,
1747
1766
  transactionId,
@@ -1754,7 +1773,7 @@ function handleReleaseDelete(action, ctx) {
1754
1773
  }), { base, working };
1755
1774
  }
1756
1775
  function handleReleaseEdit(action, ctx) {
1757
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx, { base, working } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), result = applySingleDocPatch({
1776
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx, { base, working } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), result = applySingleDocPatch({
1758
1777
  base,
1759
1778
  working,
1760
1779
  documentId: releaseDocumentId,
@@ -1762,6 +1781,7 @@ function handleReleaseEdit(action, ctx) {
1762
1781
  transactionId,
1763
1782
  timestamp,
1764
1783
  grants,
1784
+ identity,
1765
1785
  notFoundMessage: `Cannot edit release "${action.releaseId}" because it does not exist.`,
1766
1786
  permissionMessage: `You do not have permission to edit release "${action.releaseId}".`
1767
1787
  });
@@ -1774,14 +1794,14 @@ function handleReleaseEdit(action, ctx) {
1774
1794
  ), { base: result.base, working: result.working };
1775
1795
  }
1776
1796
  function handleReleasePublish(action, ctx) {
1777
- const { base, working, grants, outgoingActions, transactionId } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1797
+ const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1778
1798
  if (!existing)
1779
1799
  throw new ActionError({
1780
1800
  documentId: releaseDocumentId,
1781
1801
  transactionId,
1782
1802
  message: `Cannot publish release "${action.releaseId}" because it does not exist.`
1783
1803
  });
1784
- if (!checkGrant(grants.update, existing))
1804
+ if (!checkGrant(grants.update, existing, identity))
1785
1805
  throw new PermissionActionError({
1786
1806
  documentId: releaseDocumentId,
1787
1807
  transactionId,
@@ -1793,7 +1813,7 @@ function handleReleasePublish(action, ctx) {
1793
1813
  }), { base, working };
1794
1814
  }
1795
1815
  function handleReleaseSchedule(action, ctx) {
1796
- const { base, working, grants, outgoingActions, transactionId } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId);
1816
+ const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId);
1797
1817
  if (Number.isNaN(Date.parse(action.publishAt)))
1798
1818
  throw new ActionError({
1799
1819
  documentId: releaseDocumentId,
@@ -1807,7 +1827,7 @@ function handleReleaseSchedule(action, ctx) {
1807
1827
  transactionId,
1808
1828
  message: `Cannot schedule release "${action.releaseId}" because it does not exist.`
1809
1829
  });
1810
- if (!checkGrant(grants.update, existing))
1830
+ if (!checkGrant(grants.update, existing, identity))
1811
1831
  throw new PermissionActionError({
1812
1832
  documentId: releaseDocumentId,
1813
1833
  transactionId,
@@ -1820,14 +1840,14 @@ function handleReleaseSchedule(action, ctx) {
1820
1840
  }), { base, working };
1821
1841
  }
1822
1842
  function handleReleaseUnschedule(action, ctx) {
1823
- const { base, working, grants, outgoingActions, transactionId } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1843
+ const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
1824
1844
  if (!existing)
1825
1845
  throw new ActionError({
1826
1846
  documentId: releaseDocumentId,
1827
1847
  transactionId,
1828
1848
  message: `Cannot unschedule release "${action.releaseId}" because it does not exist.`
1829
1849
  });
1830
- if (!checkGrant(grants.update, existing))
1850
+ if (!checkGrant(grants.update, existing, identity))
1831
1851
  throw new PermissionActionError({
1832
1852
  documentId: releaseDocumentId,
1833
1853
  transactionId,
@@ -1839,7 +1859,7 @@ function handleReleaseUnschedule(action, ctx) {
1839
1859
  }), { base, working };
1840
1860
  }
1841
1861
  function handleUnpublish(action, ctx) {
1842
- const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1862
+ const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
1843
1863
  let { base, working } = ctx;
1844
1864
  const documentId = getId(action.documentId);
1845
1865
  if (action.liveEdit || isReleasePerspective(action.perspective))
@@ -1859,13 +1879,13 @@ function handleUnpublish(action, ctx) {
1859
1879
  { delete: { id: publishedId } },
1860
1880
  { createIfNotExists: newDraftFromPublished }
1861
1881
  ];
1862
- if (!checkGrant(grants.update, sourceDoc))
1882
+ if (!checkGrant(grants.update, sourceDoc, identity))
1863
1883
  throw new PermissionActionError({
1864
1884
  documentId,
1865
1885
  transactionId,
1866
1886
  message: `You do not have permission to unpublish the document "${documentId}".`
1867
1887
  });
1868
- if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished))
1888
+ if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished, identity))
1869
1889
  throw new PermissionActionError({
1870
1890
  documentId,
1871
1891
  transactionId,
@@ -1891,7 +1911,8 @@ function processActions({
1891
1911
  working: initialWorking,
1892
1912
  base: initialBase,
1893
1913
  timestamp,
1894
- grants
1914
+ grants,
1915
+ identity
1895
1916
  }) {
1896
1917
  let base = { ...initialBase }, working = { ...initialWorking };
1897
1918
  const outgoingActions = [], outgoingMutations = [], liveEditAction = actions.find((action) => !isReleaseAction(action) && action.liveEdit), otherAction = actions.find((action) => isReleaseAction(action) || !action.liveEdit);
@@ -1908,6 +1929,7 @@ function processActions({
1908
1929
  transactionId,
1909
1930
  timestamp,
1910
1931
  grants,
1932
+ identity,
1911
1933
  outgoingActions,
1912
1934
  outgoingMutations
1913
1935
  });
@@ -1992,7 +2014,8 @@ function applyFirstQueuedTransaction(prev) {
1992
2014
  working,
1993
2015
  base: working,
1994
2016
  timestamp,
1995
- grants: prev.grants
2017
+ grants: prev.grants,
2018
+ identity: prev.identity
1996
2019
  }), applied = {
1997
2020
  ...queued,
1998
2021
  ...result,
@@ -2114,7 +2137,7 @@ function revertOutgoingTransaction(prev) {
2114
2137
  const nextApplied = [];
2115
2138
  for (const t of prev.applied)
2116
2139
  try {
2117
- const next = processActions({ ...t, working, grants: prev.grants });
2140
+ const next = processActions({ ...t, working, grants: prev.grants, identity: prev.identity });
2118
2141
  working = next.working, nextApplied.push({ ...t, ...next });
2119
2142
  } catch (error) {
2120
2143
  if (error instanceof ActionError) continue;
@@ -2161,7 +2184,7 @@ function applyRemoteDocument(prev, { document, documentId, previousRev, revision
2161
2184
  const nextApplied = [];
2162
2185
  for (const curr of prev.applied)
2163
2186
  try {
2164
- const next = processActions({ ...curr, working, grants: prev.grants });
2187
+ const next = processActions({ ...curr, working, grants: prev.grants, identity: prev.identity });
2165
2188
  working = next.working, nextApplied.push({ ...curr, ...next });
2166
2189
  } catch (error) {
2167
2190
  if (error instanceof ActionError) {
@@ -2349,7 +2372,8 @@ const documentStore = defineStore({
2349
2372
  subscribeToQueuedAndApplyNextTransaction(context),
2350
2373
  subscribeToSubscriptionsAndListenToDocuments(context),
2351
2374
  subscribeToAppliedAndSubmitNextTransaction(context),
2352
- subscribeToClientAndFetchDatasetAcl(context)
2375
+ subscribeToClientAndFetchDatasetAcl(context),
2376
+ subscribeToCurrentUserAndSetIdentity(context)
2353
2377
  ];
2354
2378
  return () => {
2355
2379
  sharedListener.dispose(), subscriptions.forEach((subscription) => subscription.unsubscribe());
@@ -2542,8 +2566,15 @@ const _resolveDocument = bindActionByResource(
2542
2566
  mergeMap$1(
2543
2567
  (group) => group.pipe(
2544
2568
  switchMap((e) => e.add ? listen(context, e.id).pipe(
2545
- catchError$1((error) => {
2546
- throw error instanceof OutOfSyncError && listen(context, e.id), error;
2569
+ retry({
2570
+ delay: (error, retryCount) => {
2571
+ if (!(error instanceof OutOfSyncError)) return throwError(() => error);
2572
+ const backoff = Math.min(
2573
+ OUT_OF_SYNC_RETRY_BASE_DELAY * 2 ** (retryCount - 1),
2574
+ OUT_OF_SYNC_RETRY_MAX_DELAY
2575
+ );
2576
+ return timer(backoff);
2577
+ }
2547
2578
  }),
2548
2579
  tap$1(
2549
2580
  (remote) => state.set(
@@ -2582,15 +2613,58 @@ const _resolveDocument = bindActionByResource(
2582
2613
  ).subscribe({
2583
2614
  error: (error) => state.set("setError", { error })
2584
2615
  });
2585
- };
2616
+ }, subscribeToCurrentUserAndSetIdentity = ({
2617
+ instance,
2618
+ state
2619
+ }) => getCurrentUserState(instance).observable.subscribe({
2620
+ next: (currentUser) => state.set("setIdentity", { identity: currentUser?.id }),
2621
+ // A transient identity-fetch failure (network blip, expired token, or a
2622
+ // normal logout/re-login transition) should not brick all document
2623
+ // operations. Reset the identity to `undefined` and keep going — GROQ's
2624
+ // `identity()` then evaluates to null, matching the unauthenticated state.
2625
+ error: () => state.set("setIdentity", { identity: void 0 })
2626
+ }), MEDIA_LIBRARY_DRAFTED_TYPES = /* @__PURE__ */ new Set(["sanity.asset"]);
2627
+ function getEffectiveDocumentModel(resource, documentType) {
2628
+ return resource ? isCanvasResource(resource) ? { liveEdit: !0, supportsReleases: !1 } : isMediaLibraryResource(resource) ? { liveEdit: !(documentType && MEDIA_LIBRARY_DRAFTED_TYPES.has(documentType)), supportsReleases: !1 } : { liveEdit: void 0, supportsReleases: !0 } : { liveEdit: void 0, supportsReleases: !0 };
2629
+ }
2630
+ function describeResource(resource) {
2631
+ return resource && isCanvasResource(resource) ? "Canvas" : resource && isMediaLibraryResource(resource) ? "Media Library" : "this resource";
2632
+ }
2633
+ function normalizeActionsForResource(actions, resource) {
2634
+ const stripped = [], normalized = actions.map((action) => {
2635
+ if (action.type !== "document.edit") return action;
2636
+ const { liveEdit: forcedLiveEdit, supportsReleases } = getEffectiveDocumentModel(
2637
+ resource,
2638
+ action.documentType
2639
+ ), shouldRemovePerspective = isReleasePerspective(action.perspective) && !supportsReleases, shouldForceLiveEdit = forcedLiveEdit === !0 && !action.liveEdit;
2640
+ if (!shouldRemovePerspective && !shouldForceLiveEdit) return action;
2641
+ const corrected = { ...action };
2642
+ return shouldForceLiveEdit && (corrected.liveEdit = !0), shouldRemovePerspective && (corrected.perspective = void 0), corrected.documentId = getEffectiveDocumentId({
2643
+ ...corrected,
2644
+ documentId: getPublishedId(DocumentId(corrected.documentId))
2645
+ }), shouldRemovePerspective && stripped.push({ documentType: action.documentType, documentId: corrected.documentId }), corrected;
2646
+ });
2647
+ if (stripped.length > 0) {
2648
+ const docs = stripped.map((e) => `${e.documentType} (${e.documentId})`).join(", ");
2649
+ console.warn(
2650
+ `[sanity-sdk] ${describeResource(resource)} does not support release perspectives \u2014 falling back to the standard editing path for: ${docs}`
2651
+ );
2652
+ }
2653
+ return normalized;
2654
+ }
2586
2655
  function applyDocumentActions(...args) {
2587
2656
  return boundApplyDocumentActions(...args);
2588
2657
  }
2589
2658
  const boundApplyDocumentActions = bindActionByResource(documentStore, _applyDocumentActions);
2590
- async function _applyDocumentActions({ state }, { actions, transactionId = crypto.randomUUID(), disableBatching }) {
2591
- const { events } = state.get(), transaction = {
2659
+ async function _applyDocumentActions({ state }, {
2660
+ actions,
2661
+ resource,
2662
+ transactionId = crypto.randomUUID(),
2663
+ disableBatching
2664
+ }) {
2665
+ const { events } = state.get(), normalizedActions = normalizeActionsForResource(actions, resource), transaction = {
2592
2666
  transactionId,
2593
- actions,
2667
+ actions: normalizedActions,
2594
2668
  ...disableBatching && { disableBatching }
2595
2669
  }, fatalError$ = state.observable.pipe(
2596
2670
  map$1((s) => s.error),