@sanity/sdk 2.10.0 → 2.11.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.
Files changed (60) hide show
  1. package/dist/_chunks-dts/utils.d.ts +200 -28
  2. package/dist/_chunks-es/_internal.js +3 -14
  3. package/dist/_chunks-es/_internal.js.map +1 -1
  4. package/dist/_chunks-es/createGroqSearchFilter.js +17 -19
  5. package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
  6. package/dist/_chunks-es/version.js +1 -1
  7. package/dist/_exports/_internal.d.ts +16 -2
  8. package/dist/_exports/_internal.js +3 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +564 -459
  11. package/dist/index.js.map +1 -1
  12. package/package.json +16 -18
  13. package/src/_exports/_internal.ts +1 -0
  14. package/src/_exports/index.ts +25 -2
  15. package/src/agent/agentActions.ts +21 -25
  16. package/src/auth/refreshStampedToken.test.ts +2 -2
  17. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +116 -0
  18. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +27 -9
  19. package/src/client/clientStore.test.ts +10 -46
  20. package/src/client/clientStore.ts +7 -14
  21. package/src/comlink/node/actions/getOrCreateNode.test.ts +5 -2
  22. package/src/comlink/node/actions/releaseNode.test.ts +3 -3
  23. package/src/config/sanityConfig.ts +0 -1
  24. package/src/document/documentStore.ts +3 -8
  25. package/src/document/permissions.ts +1 -1
  26. package/src/document/processActions/create.ts +135 -0
  27. package/src/document/processActions/delete.ts +100 -0
  28. package/src/document/processActions/discard.ts +63 -0
  29. package/src/document/processActions/edit.ts +176 -0
  30. package/src/document/processActions/processActions.ts +168 -0
  31. package/src/document/processActions/publish.ts +120 -0
  32. package/src/document/processActions/shared.ts +47 -0
  33. package/src/document/processActions/unpublish.ts +85 -0
  34. package/src/document/processActions.test.ts +1 -1
  35. package/src/document/reducers.ts +1 -1
  36. package/src/document/sharedListener.ts +3 -5
  37. package/src/organization/organization.test-d.ts +102 -0
  38. package/src/organization/organization.test.ts +138 -0
  39. package/src/organization/organization.ts +166 -0
  40. package/src/organizations/organizations.test-d.ts +77 -0
  41. package/src/organizations/organizations.test.ts +150 -0
  42. package/src/organizations/organizations.ts +132 -0
  43. package/src/presence/presenceStore.test.ts +5 -5
  44. package/src/preview/previewProjectionUtils.ts +2 -3
  45. package/src/project/project.test-d.ts +93 -0
  46. package/src/project/project.test.ts +108 -10
  47. package/src/project/project.ts +152 -26
  48. package/src/projection/subscribeToStateAndFetchBatches.ts +4 -9
  49. package/src/projects/projects.test-d.ts +38 -0
  50. package/src/projects/projects.test.ts +104 -38
  51. package/src/projects/projects.ts +74 -14
  52. package/src/query/queryStore.ts +2 -3
  53. package/src/releases/releasesStore.test.ts +1 -1
  54. package/src/releases/releasesStore.ts +2 -2
  55. package/src/store/createSanityInstance.ts +3 -3
  56. package/src/telemetry/devMode.test.ts +8 -0
  57. package/src/telemetry/devMode.ts +10 -9
  58. package/src/telemetry/initTelemetry.test.ts +0 -17
  59. package/src/telemetry/initTelemetry.ts +2 -12
  60. package/src/document/processActions.ts +0 -735
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
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, isDatasetResource, bindActionByResource, isMediaLibraryResource, isCanvasResource, getUsersKey, addSubscription, parseUsersKey, getClient, PROJECT_API_VERSION, setUsersError, setUsersData, API_VERSION as API_VERSION$6, getDashboardOrganizationId as getDashboardOrganizationId$1, USERS_STATE_CLEAR_DELAY, removeSubscription, updateLastLoadMoreRequest, cancelRequest, initializeRequest, getTokenState, getQueryState, resolveQuery, bindActionByResourceAndPerspective, PREVIEW_PROJECTION, transformProjectionToPreview } from "./_chunks-es/createGroqSearchFilter.js";
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
3
  import { createGroqSearchFilter, getActiveReleasesState, getAuthState, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType, getCurrentUserState, 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";
@@ -9,9 +9,9 @@ import { getVersionId, DocumentId, getPublishedId, getDraftId, isDraftId, isVers
9
9
  import { jsonMatch, stringifyPath, slicePath, getIndexForKey } from "@sanity/json-match";
10
10
  import { getIndexForKey as getIndexForKey2, getPathDepth, joinPaths, jsonMatch as jsonMatch2, slicePath as slicePath2, stringifyPath as stringifyPath2 } from "@sanity/json-match";
11
11
  import { evaluateSync, parse } from "groq-js";
12
- import { diffValue } from "@sanity/diff-patch";
13
12
  import { applyPatches, parsePatch } from "@sanity/diff-match-patch";
14
13
  import { isKeySegment, isKeyedObject } from "@sanity/types";
14
+ import { diffValue } from "@sanity/diff-patch";
15
15
  import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
16
16
  import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
17
17
  import { fromUrl } from "@sanity/bifur-client";
@@ -91,41 +91,31 @@ function createSanityInstance(config = {}) {
91
91
  };
92
92
  return instance;
93
93
  }
94
- const API_VERSION$5 = "vX";
95
- function agentGenerate(instance, options) {
96
- return getClientState(instance, {
97
- apiVersion: API_VERSION$5,
98
- projectId: instance.config.projectId,
99
- dataset: instance.config.dataset
100
- }).observable.pipe(switchMap((client) => client.observable.agent.action.generate(options)));
94
+ const API_VERSION$7 = "vX";
95
+ function agentGenerate(instance, options, resource) {
96
+ return getClientState(instance, { apiVersion: API_VERSION$7, resource }).observable.pipe(
97
+ switchMap((client) => client.observable.agent.action.generate(options))
98
+ );
101
99
  }
102
- function agentTransform(instance, options) {
103
- return getClientState(instance, {
104
- apiVersion: API_VERSION$5,
105
- projectId: instance.config.projectId,
106
- dataset: instance.config.dataset
107
- }).observable.pipe(switchMap((client) => client.observable.agent.action.transform(options)));
100
+ function agentTransform(instance, options, resource) {
101
+ return getClientState(instance, { apiVersion: API_VERSION$7, resource }).observable.pipe(
102
+ switchMap((client) => client.observable.agent.action.transform(options))
103
+ );
108
104
  }
109
- function agentTranslate(instance, options) {
110
- return getClientState(instance, {
111
- apiVersion: API_VERSION$5,
112
- projectId: instance.config.projectId,
113
- dataset: instance.config.dataset
114
- }).observable.pipe(switchMap((client) => client.observable.agent.action.translate(options)));
105
+ function agentTranslate(instance, options, resource) {
106
+ return getClientState(instance, { apiVersion: API_VERSION$7, resource }).observable.pipe(
107
+ switchMap((client) => client.observable.agent.action.translate(options))
108
+ );
115
109
  }
116
- function agentPrompt(instance, options) {
117
- return getClientState(instance, {
118
- apiVersion: API_VERSION$5,
119
- projectId: instance.config.projectId,
120
- dataset: instance.config.dataset
121
- }).observable.pipe(switchMap((client) => from(client.agent.action.prompt(options))));
110
+ function agentPrompt(instance, options, resource) {
111
+ return getClientState(instance, { apiVersion: API_VERSION$7, resource }).observable.pipe(
112
+ switchMap((client) => from(client.agent.action.prompt(options)))
113
+ );
122
114
  }
123
- function agentPatch(instance, options) {
124
- return getClientState(instance, {
125
- apiVersion: API_VERSION$5,
126
- projectId: instance.config.projectId,
127
- dataset: instance.config.dataset
128
- }).observable.pipe(switchMap((client) => from(client.agent.action.patch(options))));
115
+ function agentPatch(instance, options, resource) {
116
+ return getClientState(instance, { apiVersion: API_VERSION$7, resource }).observable.pipe(
117
+ switchMap((client) => from(client.agent.action.patch(options)))
118
+ );
129
119
  }
130
120
  function compareProjectOrganization(projectId, projectOrganizationId, currentDashboardOrgId) {
131
121
  return projectOrganizationId !== currentDashboardOrgId ? {
@@ -265,27 +255,42 @@ function createFetcherStore({
265
255
  );
266
256
  return { getState, resolveState };
267
257
  }
268
- const API_VERSION$4 = "v2025-02-19", project = createFetcherStore({
258
+ const API_VERSION$6 = "v2025-02-19";
259
+ function normalizeProjectOptions(options) {
260
+ return {
261
+ includeMembers: options?.includeMembers ?? !0,
262
+ includeFeatures: options?.includeFeatures ?? !0
263
+ };
264
+ }
265
+ function resolveProjectId(instance, options) {
266
+ const projectId = options?.projectId ?? instance.config.projectId;
267
+ if (!projectId)
268
+ throw new Error("A projectId is required to use the project API.");
269
+ return projectId;
270
+ }
271
+ function getProjectCacheKey(instance, options) {
272
+ const projectId = resolveProjectId(instance, options), { includeMembers, includeFeatures } = normalizeProjectOptions(options);
273
+ return `project:${projectId}${includeMembers ? ":members" : ""}${includeFeatures ? ":features" : ""}`;
274
+ }
275
+ const project = createFetcherStore({
269
276
  name: "Project",
270
- getKey: (instance, options) => {
271
- const projectId = options?.projectId ?? instance.config.projectId;
272
- if (!projectId)
273
- throw new Error("A projectId is required to use the project API.");
274
- return projectId;
275
- },
276
- fetcher: (instance) => (options = {}) => {
277
- const projectId = options.projectId ?? instance.config.projectId;
277
+ getKey: getProjectCacheKey,
278
+ fetcher: (instance) => (options) => {
279
+ const projectId = resolveProjectId(instance, options);
278
280
  return getClientState(instance, {
279
- apiVersion: API_VERSION$4,
280
- scope: "global",
281
- projectId
281
+ apiVersion: API_VERSION$6,
282
+ scope: "global"
282
283
  }).observable.pipe(
283
- switchMap(
284
- (client) => client.observable.projects.getById(
285
- // non-null assertion is fine with the above throwing
286
- projectId ?? instance.config.projectId
287
- )
288
- )
284
+ switchMap((client) => {
285
+ const normalized = normalizeProjectOptions(options), query = Object.fromEntries(
286
+ Object.entries(normalized).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
287
+ );
288
+ return client.observable.request({
289
+ uri: `/projects/${projectId}`,
290
+ query,
291
+ tag: "project.get"
292
+ });
293
+ })
289
294
  );
290
295
  }
291
296
  }), getProjectState = project.getState, resolveProject = project.resolveState, getDashboardOrganizationId = bindActionGlobally(
@@ -553,7 +558,7 @@ function configureLogging(config) {
553
558
  source: "programmatic"
554
559
  });
555
560
  }
556
- const API_VERSION$3 = "v2025-02-19", datasets = createFetcherStore({
561
+ const API_VERSION$5 = "v2025-02-19", datasets = createFetcherStore({
557
562
  name: "Datasets",
558
563
  getKey: (instance, options) => {
559
564
  const projectId = options?.projectId ?? instance.config.projectId;
@@ -562,7 +567,7 @@ const API_VERSION$3 = "v2025-02-19", datasets = createFetcherStore({
562
567
  return projectId;
563
568
  },
564
569
  fetcher: (instance) => (options) => getClientState(instance, {
565
- apiVersion: API_VERSION$3,
570
+ apiVersion: API_VERSION$5,
566
571
  // non-null assertion is fine because we check above
567
572
  projectId: options?.projectId ?? instance.config.projectId,
568
573
  useProjectHostname: !0
@@ -637,7 +642,7 @@ function discardDocument(doc) {
637
642
  documentId: effectiveDocumentId
638
643
  };
639
644
  }
640
- const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$2 = "v2025-05-06";
645
+ const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$4 = "v2025-05-06";
641
646
  function generateArrayKey(length = 12) {
642
647
  const numBytes = Math.ceil(length / 2), bytes = crypto.getRandomValues(new Uint8Array(numBytes));
643
648
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
@@ -1285,6 +1290,366 @@ class ActionError extends Error {
1285
1290
  }
1286
1291
  class PermissionActionError extends ActionError {
1287
1292
  }
1293
+ function handleCreate(action, ctx) {
1294
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1295
+ let { base, working } = ctx;
1296
+ const documentId = getId(action.documentId);
1297
+ if (action.liveEdit) {
1298
+ if (working[documentId])
1299
+ throw new ActionError({
1300
+ documentId,
1301
+ transactionId,
1302
+ message: "This document already exists."
1303
+ });
1304
+ const newDocBase2 = { _type: action.documentType, _id: documentId, ...action.initialValue }, mutations2 = [{ create: {
1305
+ _type: action.documentType,
1306
+ _id: documentId,
1307
+ ...action.initialValue
1308
+ } }];
1309
+ if (base = processMutations({
1310
+ documents: base,
1311
+ transactionId,
1312
+ mutations: [{ create: newDocBase2 }],
1313
+ timestamp
1314
+ }), working = processMutations({
1315
+ documents: working,
1316
+ transactionId,
1317
+ mutations: mutations2,
1318
+ timestamp
1319
+ }), !checkGrant(grants.create, working[documentId]))
1320
+ throw new PermissionActionError({
1321
+ documentId,
1322
+ transactionId,
1323
+ message: `You do not have permission to create document "${documentId}".`
1324
+ });
1325
+ return outgoingMutations.push(...mutations2), { base, working };
1326
+ }
1327
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1328
+ if (versionId ? working[versionId] : working[draftId]) {
1329
+ const errorDocType = versionId ? "release version" : "draft";
1330
+ throw new ActionError({
1331
+ documentId,
1332
+ transactionId,
1333
+ message: `A ${errorDocType} of this document already exists. Please use or discard the existing ${errorDocType} before creating a new one.`
1334
+ });
1335
+ }
1336
+ const newDocBase = {
1337
+ ...base[draftId] ?? base[publishedId],
1338
+ _type: action.documentType,
1339
+ _id: versionId ?? draftId,
1340
+ ...action.initialValue
1341
+ }, newDocWorking = {
1342
+ ...working[draftId] ?? working[publishedId],
1343
+ _type: action.documentType,
1344
+ _id: versionId ?? draftId,
1345
+ ...action.initialValue
1346
+ }, mutations = [{ create: newDocWorking }];
1347
+ if (base = processMutations({
1348
+ documents: base,
1349
+ transactionId,
1350
+ mutations: [{ create: newDocBase }],
1351
+ timestamp
1352
+ }), working = processMutations({
1353
+ documents: working,
1354
+ transactionId,
1355
+ mutations,
1356
+ timestamp
1357
+ }), versionId && !checkGrant(grants.create, working[versionId]))
1358
+ throw new PermissionActionError({
1359
+ documentId,
1360
+ transactionId,
1361
+ message: `You do not have permission to create a release version for document "${documentId}".`
1362
+ });
1363
+ if (!versionId && !checkGrant(grants.create, working[draftId]))
1364
+ throw new PermissionActionError({
1365
+ documentId,
1366
+ transactionId,
1367
+ message: `You do not have permission to create a draft for document "${documentId}".`
1368
+ });
1369
+ return outgoingMutations.push(...mutations), outgoingActions.push({
1370
+ actionType: "sanity.action.document.version.create",
1371
+ publishedId,
1372
+ attributes: newDocWorking
1373
+ }), { base, working };
1374
+ }
1375
+ function handleDelete(action, ctx) {
1376
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1377
+ let { base, working } = ctx;
1378
+ const documentId = action.documentId;
1379
+ if (isReleasePerspective(action.perspective))
1380
+ throw new ActionError({
1381
+ documentId,
1382
+ transactionId,
1383
+ message: 'Cannot delete a version document. You may want to use the "unpublish" or "discard" actions instead.'
1384
+ });
1385
+ if (action.liveEdit) {
1386
+ if (!working[documentId])
1387
+ throw new ActionError({
1388
+ documentId,
1389
+ transactionId,
1390
+ message: "The document you are trying to delete does not exist."
1391
+ });
1392
+ if (!checkGrant(grants.update, working[documentId]))
1393
+ throw new PermissionActionError({
1394
+ documentId,
1395
+ transactionId,
1396
+ message: "You do not have permission to delete this document."
1397
+ });
1398
+ const mutations2 = [{ delete: { id: documentId } }];
1399
+ return base = processMutations({ documents: base, transactionId, mutations: mutations2, timestamp }), working = processMutations({ documents: working, transactionId, mutations: mutations2, timestamp }), outgoingMutations.push(...mutations2), { base, working };
1400
+ }
1401
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1402
+ if (!working[publishedId])
1403
+ throw new ActionError({
1404
+ documentId,
1405
+ transactionId,
1406
+ message: working[draftId] ? "Cannot delete a document without a published version." : "The document you are trying to delete does not exist."
1407
+ });
1408
+ const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId]), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId]);
1409
+ if (cantDeleteDraft || cantDeletePublished)
1410
+ throw new PermissionActionError({
1411
+ documentId,
1412
+ transactionId,
1413
+ message: "You do not have permission to delete this document."
1414
+ });
1415
+ const mutations = [{ delete: { id: publishedId } }, { delete: { id: draftId } }], includeDrafts = working[draftId] ? [draftId] : void 0;
1416
+ return base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1417
+ actionType: "sanity.action.document.delete",
1418
+ publishedId,
1419
+ ...includeDrafts ? { includeDrafts } : {}
1420
+ }), { base, working };
1421
+ }
1422
+ function handleDiscard(action, ctx) {
1423
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1424
+ let { base, working } = ctx;
1425
+ const documentId = getId(action.documentId);
1426
+ if (action.liveEdit)
1427
+ throw new ActionError({
1428
+ documentId,
1429
+ transactionId,
1430
+ message: `Cannot discard changes for liveEdit document "${documentId}". LiveEdit documents do not support drafts.`
1431
+ });
1432
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : getDraftId(DocumentId(documentId)), mutations = [{ delete: { id: versionId } }];
1433
+ if (!working[versionId])
1434
+ throw new ActionError({
1435
+ documentId,
1436
+ transactionId,
1437
+ message: `There is no draft or version available to discard for document "${documentId}".`
1438
+ });
1439
+ if (!checkGrant(grants.update, working[versionId]))
1440
+ throw new PermissionActionError({
1441
+ documentId,
1442
+ transactionId,
1443
+ message: `You do not have permission to discard changes for document "${documentId}".`
1444
+ });
1445
+ return base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1446
+ actionType: "sanity.action.document.version.discard",
1447
+ versionId
1448
+ }), { base, working };
1449
+ }
1450
+ function handleEdit(action, ctx) {
1451
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1452
+ let { base, working } = ctx;
1453
+ const documentId = getId(action.documentId);
1454
+ if (action.liveEdit) {
1455
+ const userPatches2 = action.patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
1456
+ if (!userPatches2?.length) return { base, working };
1457
+ if (!working[documentId] || !base[documentId])
1458
+ throw new ActionError({
1459
+ documentId,
1460
+ transactionId,
1461
+ message: "Cannot edit document because it does not exist."
1462
+ });
1463
+ const baseBefore2 = base[documentId];
1464
+ userPatches2 && (base = processMutations({
1465
+ documents: base,
1466
+ transactionId,
1467
+ mutations: userPatches2,
1468
+ timestamp
1469
+ }));
1470
+ const baseAfter2 = base[documentId], patches2 = diffValue(baseBefore2, baseAfter2), workingBefore2 = working[documentId];
1471
+ if (!checkGrant(grants.update, workingBefore2))
1472
+ throw new PermissionActionError({
1473
+ documentId,
1474
+ transactionId,
1475
+ message: `You do not have permission to edit document "${documentId}".`
1476
+ });
1477
+ const workingMutations2 = patches2.map((patch) => ({ patch: { id: documentId, ...patch } }));
1478
+ return working = processMutations({
1479
+ documents: working,
1480
+ transactionId,
1481
+ mutations: workingMutations2,
1482
+ timestamp
1483
+ }), outgoingMutations.push(...workingMutations2), { base, working };
1484
+ }
1485
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), patchDocumentId = isReleasePerspective(action.perspective) ? versionId : draftId, userPatches = action.patches?.map((patch) => ({
1486
+ patch: { id: patchDocumentId, ...patch }
1487
+ }));
1488
+ if (!userPatches?.length) return { base, working };
1489
+ if (isReleasePerspective(action.perspective)) {
1490
+ if (!working[versionId] && !base[versionId])
1491
+ throw new ActionError({
1492
+ documentId,
1493
+ transactionId,
1494
+ message: "This document does not exist in the release. Please create it or add it to the release first."
1495
+ });
1496
+ } else if (!working[draftId] && !working[publishedId] || !base[draftId] && !base[publishedId])
1497
+ throw new ActionError({
1498
+ documentId,
1499
+ transactionId,
1500
+ message: "Cannot edit document because it does not exist in draft or published form."
1501
+ });
1502
+ const baseMutations = [];
1503
+ !isReleasePerspective(action.perspective) && !base[draftId] && base[publishedId] && baseMutations.push({ create: { ...base[publishedId], _id: draftId } });
1504
+ const baseBefore = base[patchDocumentId] ?? base[publishedId];
1505
+ userPatches && baseMutations.push(...userPatches), base = processMutations({
1506
+ documents: base,
1507
+ transactionId,
1508
+ mutations: baseMutations,
1509
+ timestamp
1510
+ });
1511
+ const baseAfter = base[patchDocumentId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
1512
+ if (!isReleasePerspective(action.perspective) && !working[draftId] && working[publishedId]) {
1513
+ const newDraftFromPublished = { ...working[publishedId], _id: draftId };
1514
+ if (!checkGrant(grants.create, newDraftFromPublished))
1515
+ throw new PermissionActionError({
1516
+ documentId,
1517
+ transactionId,
1518
+ message: "You do not have permission to create a draft for editing this document."
1519
+ });
1520
+ workingMutations.push({ create: newDraftFromPublished });
1521
+ }
1522
+ const workingBefore = working[patchDocumentId] ?? working[publishedId];
1523
+ if (!checkGrant(grants.update, workingBefore))
1524
+ throw new PermissionActionError({
1525
+ documentId,
1526
+ transactionId,
1527
+ message: `You do not have permission to edit document "${documentId}".`
1528
+ });
1529
+ return workingMutations.push(...patches.map((patch) => ({ patch: { id: patchDocumentId, ...patch } }))), working = processMutations({
1530
+ documents: working,
1531
+ transactionId,
1532
+ mutations: workingMutations,
1533
+ timestamp
1534
+ }), outgoingMutations.push(...workingMutations), outgoingActions.push(
1535
+ ...patches.map((patch) => ({
1536
+ actionType: "sanity.action.document.edit",
1537
+ draftId: patchDocumentId,
1538
+ publishedId,
1539
+ patch
1540
+ }))
1541
+ ), { base, working };
1542
+ }
1543
+ function handlePublish(action, ctx) {
1544
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1545
+ let { base, working } = ctx;
1546
+ const documentId = getId(action.documentId);
1547
+ if (action.liveEdit || isReleasePerspective(action.perspective))
1548
+ throw new ActionError({
1549
+ documentId,
1550
+ transactionId,
1551
+ message: "Cannot publish this document. Publishing is not supported for liveEdit or version (release) documents."
1552
+ });
1553
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), workingDraft = working[draftId], baseDraft = base[draftId];
1554
+ if (!workingDraft || !baseDraft)
1555
+ throw new ActionError({
1556
+ documentId,
1557
+ transactionId,
1558
+ message: `Cannot publish because no draft version was found for document "${documentId}".`
1559
+ });
1560
+ if (!isDeepEqual(workingDraft, baseDraft))
1561
+ throw new ActionError({
1562
+ documentId,
1563
+ transactionId,
1564
+ message: "Publish aborted: The document has changed elsewhere. Please try again."
1565
+ });
1566
+ const newPublishedFromDraft = { ...strengthenOnPublish(workingDraft), _id: publishedId }, mutations = [{ delete: { id: draftId } }, { createOrReplace: newPublishedFromDraft }];
1567
+ if (working[draftId] && !checkGrant(grants.update, working[draftId]))
1568
+ throw new PermissionActionError({
1569
+ documentId,
1570
+ transactionId,
1571
+ message: `Publish failed: You do not have permission to update the draft for "${documentId}".`
1572
+ });
1573
+ if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft))
1574
+ throw new PermissionActionError({
1575
+ documentId,
1576
+ transactionId,
1577
+ message: `Publish failed: You do not have permission to update the published version of "${documentId}".`
1578
+ });
1579
+ if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft))
1580
+ throw new PermissionActionError({
1581
+ documentId,
1582
+ transactionId,
1583
+ message: `Publish failed: You do not have permission to publish a new version of "${documentId}".`
1584
+ });
1585
+ return base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1586
+ actionType: "sanity.action.document.publish",
1587
+ draftId,
1588
+ publishedId
1589
+ }), { base, working };
1590
+ }
1591
+ function strengthenOnPublish(draft) {
1592
+ const isStrengthenReference = (value) => "_strengthenOnPublish" in value;
1593
+ function strengthen(value) {
1594
+ if (typeof value != "object" || !value) return value;
1595
+ if (isStrengthenReference(value)) {
1596
+ const { _strengthenOnPublish, _weak, ...rest } = value;
1597
+ return {
1598
+ ...rest,
1599
+ ..._strengthenOnPublish.weak && { _weak: !0 }
1600
+ };
1601
+ }
1602
+ return Array.isArray(value) ? value.map(strengthen) : Object.fromEntries(Object.entries(value).map(([k, v]) => [k, strengthen(v)]));
1603
+ }
1604
+ return strengthen(draft);
1605
+ }
1606
+ function handleUnpublish(action, ctx) {
1607
+ const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
1608
+ let { base, working } = ctx;
1609
+ const documentId = getId(action.documentId);
1610
+ if (action.liveEdit || isReleasePerspective(action.perspective))
1611
+ throw new ActionError({
1612
+ documentId,
1613
+ transactionId,
1614
+ message: "Cannot unpublish this document. Unpublishing is not supported for liveEdit or version (release) documents."
1615
+ });
1616
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1617
+ if (!working[publishedId] && !base[publishedId])
1618
+ throw new ActionError({
1619
+ documentId,
1620
+ transactionId,
1621
+ message: `Cannot unpublish because the document "${documentId}" is not currently published.`
1622
+ });
1623
+ const sourceDoc = working[publishedId] ?? base[publishedId], newDraftFromPublished = { ...sourceDoc, _id: draftId }, mutations = [
1624
+ { delete: { id: publishedId } },
1625
+ { createIfNotExists: newDraftFromPublished }
1626
+ ];
1627
+ if (!checkGrant(grants.update, sourceDoc))
1628
+ throw new PermissionActionError({
1629
+ documentId,
1630
+ transactionId,
1631
+ message: `You do not have permission to unpublish the document "${documentId}".`
1632
+ });
1633
+ if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished))
1634
+ throw new PermissionActionError({
1635
+ documentId,
1636
+ transactionId,
1637
+ message: `You do not have permission to create a draft from the published version of "${documentId}".`
1638
+ });
1639
+ return base = processMutations({
1640
+ documents: base,
1641
+ transactionId,
1642
+ mutations: [
1643
+ { delete: { id: publishedId } },
1644
+ { createIfNotExists: { ...base[publishedId] ?? sourceDoc, _id: draftId } }
1645
+ ],
1646
+ timestamp
1647
+ }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1648
+ actionType: "sanity.action.document.unpublish",
1649
+ draftId,
1650
+ publishedId
1651
+ }), { base, working };
1652
+ }
1288
1653
  function processActions({
1289
1654
  actions,
1290
1655
  transactionId,
@@ -1293,361 +1658,20 @@ function processActions({
1293
1658
  timestamp,
1294
1659
  grants
1295
1660
  }) {
1296
- let working = { ...initialWorking }, base = { ...initialBase };
1661
+ let base = { ...initialBase }, working = { ...initialWorking };
1297
1662
  const outgoingActions = [], outgoingMutations = [];
1298
- for (const action of actions)
1299
- switch (action.type) {
1300
- case "document.create": {
1301
- const documentId = getId(action.documentId);
1302
- if (action.liveEdit) {
1303
- if (working[documentId])
1304
- throw new ActionError({
1305
- documentId,
1306
- transactionId,
1307
- message: "This document already exists."
1308
- });
1309
- const newDocBase2 = { _type: action.documentType, _id: documentId, ...action.initialValue }, mutations2 = [{ create: {
1310
- _type: action.documentType,
1311
- _id: documentId,
1312
- ...action.initialValue
1313
- } }];
1314
- if (base = processMutations({
1315
- documents: base,
1316
- transactionId,
1317
- mutations: [{ create: newDocBase2 }],
1318
- timestamp
1319
- }), working = processMutations({
1320
- documents: working,
1321
- transactionId,
1322
- mutations: mutations2,
1323
- timestamp
1324
- }), !checkGrant(grants.create, working[documentId]))
1325
- throw new PermissionActionError({
1326
- documentId,
1327
- transactionId,
1328
- message: `You do not have permission to create document "${documentId}".`
1329
- });
1330
- outgoingMutations.push(...mutations2);
1331
- continue;
1332
- }
1333
- const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1334
- if (versionId ? working[versionId] : working[draftId]) {
1335
- const errorDocType = versionId ? "release version" : "draft";
1336
- throw new ActionError({
1337
- documentId,
1338
- transactionId,
1339
- message: `A ${errorDocType} of this document already exists. Please use or discard the existing ${errorDocType} before creating a new one.`
1340
- });
1341
- }
1342
- const newDocBase = {
1343
- ...base[draftId] ?? base[publishedId],
1344
- _type: action.documentType,
1345
- _id: versionId ?? draftId,
1346
- ...action.initialValue
1347
- }, newDocWorking = {
1348
- ...working[draftId] ?? working[publishedId],
1349
- _type: action.documentType,
1350
- _id: versionId ?? draftId,
1351
- ...action.initialValue
1352
- }, mutations = [{ create: newDocWorking }];
1353
- if (base = processMutations({
1354
- documents: base,
1355
- transactionId,
1356
- mutations: [{ create: newDocBase }],
1357
- timestamp
1358
- }), working = processMutations({
1359
- documents: working,
1360
- transactionId,
1361
- mutations,
1362
- timestamp
1363
- }), versionId && !checkGrant(grants.create, working[versionId]))
1364
- throw new PermissionActionError({
1365
- documentId,
1366
- transactionId,
1367
- message: `You do not have permission to create a release version for document "${documentId}".`
1368
- });
1369
- if (!versionId && !checkGrant(grants.create, working[draftId]))
1370
- throw new PermissionActionError({
1371
- documentId,
1372
- transactionId,
1373
- message: `You do not have permission to create a draft for document "${documentId}".`
1374
- });
1375
- outgoingMutations.push(...mutations), outgoingActions.push({
1376
- actionType: "sanity.action.document.version.create",
1377
- publishedId,
1378
- attributes: newDocWorking
1379
- });
1380
- continue;
1381
- }
1382
- case "document.delete": {
1383
- const documentId = action.documentId;
1384
- if (isReleasePerspective(action.perspective))
1385
- throw new ActionError({
1386
- documentId,
1387
- transactionId,
1388
- message: 'Cannot delete a version document. You may want to use the "unpublish" or "discard" actions instead.'
1389
- });
1390
- if (action.liveEdit) {
1391
- if (!working[documentId])
1392
- throw new ActionError({
1393
- documentId,
1394
- transactionId,
1395
- message: "The document you are trying to delete does not exist."
1396
- });
1397
- if (!checkGrant(grants.update, working[documentId]))
1398
- throw new PermissionActionError({
1399
- documentId,
1400
- transactionId,
1401
- message: "You do not have permission to delete this document."
1402
- });
1403
- const mutations2 = [{ delete: { id: documentId } }];
1404
- base = processMutations({ documents: base, transactionId, mutations: mutations2, timestamp }), working = processMutations({ documents: working, transactionId, mutations: mutations2, timestamp }), outgoingMutations.push(...mutations2);
1405
- continue;
1406
- }
1407
- const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1408
- if (!working[publishedId])
1409
- throw new ActionError({
1410
- documentId,
1411
- transactionId,
1412
- message: working[draftId] ? "Cannot delete a document without a published version." : "The document you are trying to delete does not exist."
1413
- });
1414
- const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId]), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId]);
1415
- if (cantDeleteDraft || cantDeletePublished)
1416
- throw new PermissionActionError({
1417
- documentId,
1418
- transactionId,
1419
- message: "You do not have permission to delete this document."
1420
- });
1421
- const mutations = [{ delete: { id: publishedId } }, { delete: { id: draftId } }], includeDrafts = working[draftId] ? [draftId] : void 0;
1422
- base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1423
- actionType: "sanity.action.document.delete",
1424
- publishedId,
1425
- ...includeDrafts ? { includeDrafts } : {}
1426
- });
1427
- continue;
1428
- }
1429
- case "document.discard": {
1430
- const documentId = getId(action.documentId);
1431
- if (action.liveEdit)
1432
- throw new ActionError({
1433
- documentId,
1434
- transactionId,
1435
- message: `Cannot discard changes for liveEdit document "${documentId}". LiveEdit documents do not support drafts.`
1436
- });
1437
- const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : getDraftId(DocumentId(documentId)), mutations = [{ delete: { id: versionId } }];
1438
- if (!working[versionId])
1439
- throw new ActionError({
1440
- documentId,
1441
- transactionId,
1442
- message: `There is no draft or version available to discard for document "${documentId}".`
1443
- });
1444
- if (!checkGrant(grants.update, working[versionId]))
1445
- throw new PermissionActionError({
1446
- documentId,
1447
- transactionId,
1448
- message: `You do not have permission to discard changes for document "${documentId}".`
1449
- });
1450
- base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1451
- actionType: "sanity.action.document.version.discard",
1452
- versionId
1453
- });
1454
- continue;
1455
- }
1456
- case "document.edit": {
1457
- const documentId = getId(action.documentId);
1458
- if (action.liveEdit) {
1459
- const userPatches2 = action.patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
1460
- if (!userPatches2?.length) continue;
1461
- if (!working[documentId] || !base[documentId])
1462
- throw new ActionError({
1463
- documentId,
1464
- transactionId,
1465
- message: "Cannot edit document because it does not exist."
1466
- });
1467
- const baseBefore2 = base[documentId];
1468
- userPatches2 && (base = processMutations({
1469
- documents: base,
1470
- transactionId,
1471
- mutations: userPatches2,
1472
- timestamp
1473
- }));
1474
- const baseAfter2 = base[documentId], patches2 = diffValue(baseBefore2, baseAfter2), workingBefore2 = working[documentId];
1475
- if (!checkGrant(grants.update, workingBefore2))
1476
- throw new PermissionActionError({
1477
- documentId,
1478
- transactionId,
1479
- message: `You do not have permission to edit document "${documentId}".`
1480
- });
1481
- const workingMutations2 = patches2.map((patch) => ({ patch: { id: documentId, ...patch } }));
1482
- working = processMutations({
1483
- documents: working,
1484
- transactionId,
1485
- mutations: workingMutations2,
1486
- timestamp
1487
- }), outgoingMutations.push(...workingMutations2);
1488
- continue;
1489
- }
1490
- const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), patchDocumentId = isReleasePerspective(action.perspective) ? versionId : draftId, userPatches = action.patches?.map((patch) => ({
1491
- patch: { id: patchDocumentId, ...patch }
1492
- }));
1493
- if (!userPatches?.length) continue;
1494
- if (isReleasePerspective(action.perspective)) {
1495
- if (!working[versionId] && !base[versionId])
1496
- throw new ActionError({
1497
- documentId,
1498
- transactionId,
1499
- message: "This document does not exist in the release. Please create it or add it to the release first."
1500
- });
1501
- } else if (!working[draftId] && !working[publishedId] || !base[draftId] && !base[publishedId])
1502
- throw new ActionError({
1503
- documentId,
1504
- transactionId,
1505
- message: "Cannot edit document because it does not exist in draft or published form."
1506
- });
1507
- const baseMutations = [];
1508
- !isReleasePerspective(action.perspective) && !base[draftId] && base[publishedId] && baseMutations.push({ create: { ...base[publishedId], _id: draftId } });
1509
- const baseBefore = base[patchDocumentId] ?? base[publishedId];
1510
- userPatches && baseMutations.push(...userPatches), base = processMutations({
1511
- documents: base,
1512
- transactionId,
1513
- mutations: baseMutations,
1514
- timestamp
1515
- });
1516
- const baseAfter = base[patchDocumentId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
1517
- if (!isReleasePerspective(action.perspective) && !working[draftId] && working[publishedId]) {
1518
- const newDraftFromPublished = { ...working[publishedId], _id: draftId };
1519
- if (!checkGrant(grants.create, newDraftFromPublished))
1520
- throw new PermissionActionError({
1521
- documentId,
1522
- transactionId,
1523
- message: "You do not have permission to create a draft for editing this document."
1524
- });
1525
- workingMutations.push({ create: newDraftFromPublished });
1526
- }
1527
- const workingBefore = working[patchDocumentId] ?? working[publishedId];
1528
- if (!checkGrant(grants.update, workingBefore))
1529
- throw new PermissionActionError({
1530
- documentId,
1531
- transactionId,
1532
- message: `You do not have permission to edit document "${documentId}".`
1533
- });
1534
- workingMutations.push(...patches.map((patch) => ({ patch: { id: patchDocumentId, ...patch } }))), working = processMutations({
1535
- documents: working,
1536
- transactionId,
1537
- mutations: workingMutations,
1538
- timestamp
1539
- }), outgoingMutations.push(...workingMutations), outgoingActions.push(
1540
- ...patches.map((patch) => ({
1541
- actionType: "sanity.action.document.edit",
1542
- draftId: patchDocumentId,
1543
- publishedId,
1544
- patch
1545
- }))
1546
- );
1547
- continue;
1548
- }
1549
- case "document.publish": {
1550
- const documentId = getId(action.documentId);
1551
- if (action.liveEdit || isReleasePerspective(action.perspective))
1552
- throw new ActionError({
1553
- documentId,
1554
- transactionId,
1555
- message: "Cannot publish this document. Publishing is not supported for liveEdit or version (release) documents."
1556
- });
1557
- const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), workingDraft = working[draftId], baseDraft = base[draftId];
1558
- if (!workingDraft || !baseDraft)
1559
- throw new ActionError({
1560
- documentId,
1561
- transactionId,
1562
- message: `Cannot publish because no draft version was found for document "${documentId}".`
1563
- });
1564
- if (!isDeepEqual(workingDraft, baseDraft))
1565
- throw new ActionError({
1566
- documentId,
1567
- transactionId,
1568
- message: "Publish aborted: The document has changed elsewhere. Please try again."
1569
- });
1570
- const newPublishedFromDraft = { ...strengthenOnPublish(workingDraft), _id: publishedId }, mutations = [
1571
- { delete: { id: draftId } },
1572
- { createOrReplace: newPublishedFromDraft }
1573
- ];
1574
- if (working[draftId] && !checkGrant(grants.update, working[draftId]))
1575
- throw new PermissionActionError({
1576
- documentId,
1577
- transactionId,
1578
- message: `Publish failed: You do not have permission to update the draft for "${documentId}".`
1579
- });
1580
- if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft))
1581
- throw new PermissionActionError({
1582
- documentId,
1583
- transactionId,
1584
- message: `Publish failed: You do not have permission to update the published version of "${documentId}".`
1585
- });
1586
- if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft))
1587
- throw new PermissionActionError({
1588
- documentId,
1589
- transactionId,
1590
- message: `Publish failed: You do not have permission to publish a new version of "${documentId}".`
1591
- });
1592
- base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1593
- actionType: "sanity.action.document.publish",
1594
- draftId,
1595
- publishedId
1596
- });
1597
- continue;
1598
- }
1599
- case "document.unpublish": {
1600
- const documentId = getId(action.documentId);
1601
- if (action.liveEdit || isReleasePerspective(action.perspective))
1602
- throw new ActionError({
1603
- documentId,
1604
- transactionId,
1605
- message: "Cannot unpublish this document. Unpublishing is not supported for liveEdit or version (release) documents."
1606
- });
1607
- const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1608
- if (!working[publishedId] && !base[publishedId])
1609
- throw new ActionError({
1610
- documentId,
1611
- transactionId,
1612
- message: `Cannot unpublish because the document "${documentId}" is not currently published.`
1613
- });
1614
- const sourceDoc = working[publishedId] ?? base[publishedId], newDraftFromPublished = { ...sourceDoc, _id: draftId }, mutations = [
1615
- { delete: { id: publishedId } },
1616
- { createIfNotExists: newDraftFromPublished }
1617
- ];
1618
- if (!checkGrant(grants.update, sourceDoc))
1619
- throw new PermissionActionError({
1620
- documentId,
1621
- transactionId,
1622
- message: `You do not have permission to unpublish the document "${documentId}".`
1623
- });
1624
- if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished))
1625
- throw new PermissionActionError({
1626
- documentId,
1627
- transactionId,
1628
- message: `You do not have permission to create a draft from the published version of "${documentId}".`
1629
- });
1630
- base = processMutations({
1631
- documents: base,
1632
- transactionId,
1633
- mutations: [
1634
- { delete: { id: publishedId } },
1635
- { createIfNotExists: { ...base[publishedId] ?? sourceDoc, _id: draftId } }
1636
- ],
1637
- timestamp
1638
- }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
1639
- actionType: "sanity.action.document.unpublish",
1640
- draftId,
1641
- publishedId
1642
- });
1643
- continue;
1644
- }
1645
- default:
1646
- throw new Error(
1647
- `Unknown action type: "${// @ts-expect-error invalid input
1648
- action.type}". Please contact support if this issue persists.`
1649
- );
1650
- }
1663
+ for (const action of actions) {
1664
+ const result = dispatch(action, {
1665
+ base,
1666
+ working,
1667
+ transactionId,
1668
+ timestamp,
1669
+ grants,
1670
+ outgoingActions,
1671
+ outgoingMutations
1672
+ });
1673
+ base = result.base, working = result.working;
1674
+ }
1651
1675
  const previousRevs = Object.fromEntries(
1652
1676
  Object.entries(initialWorking).map(([id, doc]) => [id, doc?._rev])
1653
1677
  );
@@ -1659,20 +1683,26 @@ function processActions({
1659
1683
  previousRevs
1660
1684
  };
1661
1685
  }
1662
- function strengthenOnPublish(draft) {
1663
- const isStrengthenReference = (value) => "_strengthenOnPublish" in value;
1664
- function strengthen(value) {
1665
- if (typeof value != "object" || !value) return value;
1666
- if (isStrengthenReference(value)) {
1667
- const { _strengthenOnPublish, _weak, ...rest } = value;
1668
- return {
1669
- ...rest,
1670
- ..._strengthenOnPublish.weak && { _weak: !0 }
1671
- };
1672
- }
1673
- return Array.isArray(value) ? value.map(strengthen) : Object.fromEntries(Object.entries(value).map(([k, v]) => [k, strengthen(v)]));
1686
+ function dispatch(action, ctx) {
1687
+ switch (action.type) {
1688
+ case "document.create":
1689
+ return handleCreate(action, ctx);
1690
+ case "document.delete":
1691
+ return handleDelete(action, ctx);
1692
+ case "document.discard":
1693
+ return handleDiscard(action, ctx);
1694
+ case "document.edit":
1695
+ return handleEdit(action, ctx);
1696
+ case "document.publish":
1697
+ return handlePublish(action, ctx);
1698
+ case "document.unpublish":
1699
+ return handleUnpublish(action, ctx);
1700
+ default:
1701
+ throw new Error(
1702
+ `Unknown action type: "${// @ts-expect-error invalid input
1703
+ action.type}". Please contact support if this issue persists.`
1704
+ );
1674
1705
  }
1675
- return strengthen(draft);
1676
1706
  }
1677
1707
  const EMPTY_REVISIONS = {};
1678
1708
  function queueTransaction(prev, transaction) {
@@ -1977,12 +2007,11 @@ function getDocumentEvents(outgoing) {
1977
2007
  )
1978
2008
  );
1979
2009
  }
1980
- const API_VERSION$1 = "v2025-05-06";
2010
+ const API_VERSION$3 = "v2025-05-06";
1981
2011
  function createSharedListener(instance, resource) {
1982
2012
  const dispose$ = new Subject(), events$ = getClientState(instance, {
1983
- apiVersion: API_VERSION$1,
1984
- // TODO: remove in v3 when we're ready for everything to be queried via resource
1985
- resource: resource && !isDatasetResource(resource) ? resource : void 0
2013
+ apiVersion: API_VERSION$3,
2014
+ resource
1986
2015
  }).observable.pipe(
1987
2016
  switchMap(
1988
2017
  (client) => (
@@ -2019,9 +2048,8 @@ function createSharedListener(instance, resource) {
2019
2048
  function createFetchDocument(instance, resource) {
2020
2049
  return function(documentId) {
2021
2050
  return getClientState(instance, {
2022
- apiVersion: API_VERSION$1,
2023
- // TODO: remove in v3 when we're ready for everything to be queried via resource
2024
- resource: resource && !isDatasetResource(resource) ? resource : void 0
2051
+ apiVersion: API_VERSION$3,
2052
+ resource
2025
2053
  }).observable.pipe(
2026
2054
  switchMap((client) => createDocumentLoaderFromClient(client)(documentId)),
2027
2055
  map$1((result) => {
@@ -2185,9 +2213,8 @@ const _resolveDocument = bindActionByResource(
2185
2213
  distinctUntilChanged(),
2186
2214
  withLatestFrom(
2187
2215
  getClientState(instance, {
2188
- apiVersion: API_VERSION$2,
2189
- // TODO: remove in v3 when we're ready for everything to be queried via resource
2190
- resource: resource && !isDatasetResource(resource) ? resource : void 0
2216
+ apiVersion: API_VERSION$4,
2217
+ resource
2191
2218
  }).observable
2192
2219
  ),
2193
2220
  concatMap(([outgoing, client]) => {
@@ -2263,8 +2290,7 @@ const _resolveDocument = bindActionByResource(
2263
2290
  state,
2264
2291
  key: { resource }
2265
2292
  }) => {
2266
- const clientOptions = { apiVersion: API_VERSION$2 };
2267
- resource && !isDatasetResource(resource) && (clientOptions.resource = resource);
2293
+ const clientOptions = { apiVersion: API_VERSION$4, resource };
2268
2294
  let uri;
2269
2295
  if (resource && isDatasetResource(resource))
2270
2296
  uri = `/projects/${resource.projectId}/datasets/${resource.dataset}/acl`;
@@ -2385,7 +2411,75 @@ const favorites = createFetcherStore({
2385
2411
  })
2386
2412
  );
2387
2413
  }
2388
- }), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, usersStore = defineStore({
2414
+ }), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, API_VERSION$2 = "v2025-02-19";
2415
+ function resolveOrganizationId(options) {
2416
+ const organizationId = options?.organizationId;
2417
+ if (!organizationId)
2418
+ throw new Error("An organizationId is required to use the organization API.");
2419
+ return organizationId;
2420
+ }
2421
+ function normalizeOrganizationOptions$1(options) {
2422
+ return {
2423
+ includeMembers: options?.includeMembers ?? !1,
2424
+ includeFeatures: options?.includeFeatures ?? !1
2425
+ };
2426
+ }
2427
+ function getOrganizationCacheKey(_instance, options) {
2428
+ const organizationId = resolveOrganizationId(options), { includeMembers, includeFeatures } = normalizeOrganizationOptions$1(options);
2429
+ return `organization:${organizationId}${includeMembers ? ":members" : ""}${includeFeatures ? ":features" : ""}`;
2430
+ }
2431
+ const organization = createFetcherStore({
2432
+ name: "Organization",
2433
+ getKey: getOrganizationCacheKey,
2434
+ fetcher: (instance) => (options) => {
2435
+ const organizationId = resolveOrganizationId(options);
2436
+ return getClientState(instance, {
2437
+ apiVersion: API_VERSION$2,
2438
+ scope: "global"
2439
+ }).observable.pipe(
2440
+ switchMap((client) => {
2441
+ const normalized = normalizeOrganizationOptions$1(options), query = Object.fromEntries(
2442
+ Object.entries(normalized).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
2443
+ );
2444
+ return client.observable.request({
2445
+ uri: `/organizations/${organizationId}`,
2446
+ query,
2447
+ tag: "organization.get"
2448
+ });
2449
+ })
2450
+ );
2451
+ }
2452
+ }), getOrganizationState = organization.getState, resolveOrganization = organization.resolveState, API_VERSION$1 = "v2025-02-19";
2453
+ function normalizeOrganizationOptions(options) {
2454
+ return {
2455
+ includeImplicitMemberships: options?.includeImplicitMemberships ?? !1,
2456
+ includeMembers: options?.includeMembers ?? !1,
2457
+ includeFeatures: options?.includeFeatures ?? !1
2458
+ };
2459
+ }
2460
+ function getOrganizationsCacheKey(_instance, options) {
2461
+ const { includeMembers, includeFeatures, includeImplicitMemberships } = normalizeOrganizationOptions(options);
2462
+ return `organizations${includeMembers ? ":members" : ""}${includeFeatures ? ":features" : ""}${includeImplicitMemberships ? ":implicit" : ""}`;
2463
+ }
2464
+ const organizations = createFetcherStore({
2465
+ name: "Organizations",
2466
+ getKey: getOrganizationsCacheKey,
2467
+ fetcher: (instance) => (options) => getClientState(instance, {
2468
+ apiVersion: API_VERSION$1,
2469
+ scope: "global"
2470
+ }).observable.pipe(
2471
+ switchMap((client) => {
2472
+ const normalized = normalizeOrganizationOptions(options), query = Object.fromEntries(
2473
+ Object.entries(normalized).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
2474
+ );
2475
+ return client.observable.request({
2476
+ uri: "/organizations",
2477
+ query,
2478
+ tag: "organizations.get"
2479
+ });
2480
+ })
2481
+ )
2482
+ }), getOrganizationsState = organizations.getState, resolveOrganizations = organizations.resolveState, usersStore = defineStore({
2389
2483
  name: "UsersStore",
2390
2484
  getInitialState: () => ({ users: {} }),
2391
2485
  initialize: (context) => {
@@ -2451,7 +2545,7 @@ const favorites = createFetcherStore({
2451
2545
  );
2452
2546
  const scope = userId.startsWith("g") ? "global" : void 0, client = getClient(instance, {
2453
2547
  scope,
2454
- apiVersion: API_VERSION$6
2548
+ apiVersion: API_VERSION$8
2455
2549
  }), resourceType2 = options.resourceType || "project", resourceId = resourceType2 === "organization" ? options.organizationId : options.projectId;
2456
2550
  return resourceId ? client.observable.request({
2457
2551
  method: "GET",
@@ -2471,7 +2565,7 @@ const favorites = createFetcherStore({
2471
2565
  filter$1((i) => typeof i == "string")
2472
2566
  ), resource$ = resourceType === "project" ? projectId ? of({ type: "project", id: projectId }) : throwError(() => new Error("Project ID required for this API.")) : organizationId$.pipe(map$1((id) => ({ type: "organization", id }))), client$ = getClientState(instance, {
2473
2567
  scope: "global",
2474
- apiVersion: API_VERSION$6
2568
+ apiVersion: API_VERSION$8
2475
2569
  }).observable, loadMore$ = state.observable.pipe(
2476
2570
  map$1((s) => s.users[group$.key]?.lastLoadMoreRequest),
2477
2571
  distinctUntilChanged()
@@ -2656,7 +2750,7 @@ const handleIncomingMessage = (event) => {
2656
2750
  }) : getClient(instance, {
2657
2751
  apiVersion: PRESENCE_API_VERSION,
2658
2752
  resource
2659
- }), token$ = getTokenState(instance).observable.pipe(distinctUntilChanged()), [incomingEvents$, dispatch] = createBifurTransport({
2753
+ }), token$ = getTokenState(instance).observable.pipe(distinctUntilChanged()), [incomingEvents$, dispatch2] = createBifurTransport({
2660
2754
  client,
2661
2755
  token$,
2662
2756
  sessionId
@@ -2677,7 +2771,7 @@ const handleIncomingMessage = (event) => {
2677
2771
  return newLocations.delete(event.sessionId), { ...prevState, locations: newLocations };
2678
2772
  }));
2679
2773
  })
2680
- ), dispatch({ type: "rollCall" }).subscribe(), isCanvasResource(resource)) {
2774
+ ), dispatch2({ type: "rollCall" }).subscribe(), isCanvasResource(resource)) {
2681
2775
  const globalClient = getClient(instance, { apiVersion: PRESENCE_API_VERSION });
2682
2776
  subscription.add(
2683
2777
  globalClient.observable.request({
@@ -2689,7 +2783,7 @@ const handleIncomingMessage = (event) => {
2689
2783
  );
2690
2784
  }
2691
2785
  return () => {
2692
- dispatch({ type: "disconnect" }).subscribe(), subscription.unsubscribe();
2786
+ dispatch2({ type: "disconnect" }).subscribe(), subscription.unsubscribe();
2693
2787
  };
2694
2788
  }
2695
2789
  }), selectLocations = (state) => state.locations, selectUsers = (state) => state.users, selectPresence = createSelector(
@@ -2876,8 +2970,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
2876
2970
  params,
2877
2971
  tag: PROJECTION_TAG,
2878
2972
  perspective,
2879
- // temporary guard here until we're ready for everything to be queried via global API
2880
- ...resource && !isDatasetResource(resource) ? { resource } : {}
2973
+ resource
2881
2974
  }), subscription = defer(() => getCurrent() === void 0 ? from(
2882
2975
  resolveQuery(instance, {
2883
2976
  query,
@@ -2885,8 +2978,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
2885
2978
  tag: PROJECTION_TAG,
2886
2979
  signal: controller.signal,
2887
2980
  perspective,
2888
- // temporary guard here until we're ready for everything to be queried via global API in v3
2889
- ...resource && !isDatasetResource(resource) ? { resource } : {}
2981
+ resource
2890
2982
  })
2891
2983
  ).pipe(switchMap(() => observable)) : observable).pipe(filter$1((result) => result !== void 0)).subscribe(observer);
2892
2984
  return () => {
@@ -2898,8 +2990,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
2898
2990
  params: statusParams,
2899
2991
  tag: PROJECTION_TAG,
2900
2992
  perspective: "raw",
2901
- // temporary guard here until we're ready for everything to be queried via global API
2902
- ...resource && !isDatasetResource(resource) ? { resource } : {}
2993
+ resource
2903
2994
  }), subscription = defer(() => getCurrent() === void 0 ? from(
2904
2995
  resolveQuery(instance, {
2905
2996
  query: statusQuery,
@@ -2907,8 +2998,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
2907
2998
  tag: PROJECTION_TAG,
2908
2999
  signal: controller.signal,
2909
3000
  perspective: "raw",
2910
- // temporary guard here until we're ready for everything to be queried via global API
2911
- ...resource && !isDatasetResource(resource) ? { resource } : {}
3001
+ resource
2912
3002
  })
2913
3003
  ).pipe(switchMap(() => observable)) : observable).pipe(filter$1((result) => result !== void 0)).subscribe(observer);
2914
3004
  return () => {
@@ -3074,23 +3164,34 @@ async function resolvePreview(instance, options) {
3074
3164
  isPending: projectionResult.isPending
3075
3165
  } : { data: null, isPending: projectionResult.isPending };
3076
3166
  }
3077
- const API_VERSION = "v2025-02-19", projects = createFetcherStore({
3167
+ const API_VERSION = "v2025-02-19";
3168
+ function normalizeProjectsOptions(options) {
3169
+ return {
3170
+ organizationId: options?.organizationId,
3171
+ includeMembers: options?.includeMembers ?? !1,
3172
+ includeFeatures: options?.includeFeatures ?? !0,
3173
+ onlyExplicitMembership: options?.onlyExplicitMembership ?? !1
3174
+ };
3175
+ }
3176
+ function getProjectsCacheKey(_instance, options) {
3177
+ const { organizationId, includeMembers, includeFeatures, onlyExplicitMembership } = normalizeProjectsOptions(options);
3178
+ return `projects${organizationId ? `:org:${organizationId}` : ""}${includeMembers ? ":members" : ""}${includeFeatures ? ":features" : ""}${onlyExplicitMembership ? ":explicit" : ""}`;
3179
+ }
3180
+ const projects = createFetcherStore({
3078
3181
  name: "Projects",
3079
- getKey: (_instance, options) => {
3080
- const orgKey = options?.organizationId ? `:org:${options.organizationId}` : "", membersKey = options?.includeMembers === !1 ? ":no-members" : "";
3081
- return `projects${orgKey}${membersKey}`;
3082
- },
3182
+ getKey: getProjectsCacheKey,
3083
3183
  fetcher: (instance) => (options) => getClientState(instance, {
3084
3184
  apiVersion: API_VERSION,
3085
- scope: "global",
3086
- requestTagPrefix: "sanity.sdk.projects"
3185
+ scope: "global"
3087
3186
  }).observable.pipe(
3088
3187
  switchMap((client) => {
3089
- const organizationId = options?.organizationId;
3090
- return client.observable.projects.list({
3091
- // client method has a type that expects false | undefined
3092
- includeMembers: options?.includeMembers ? void 0 : !1,
3093
- organizationId
3188
+ const normalized = normalizeProjectsOptions(options), query = Object.fromEntries(
3189
+ Object.entries(normalized).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
3190
+ );
3191
+ return client.observable.request({
3192
+ uri: "/projects",
3193
+ query,
3194
+ tag: "projects.get"
3094
3195
  });
3095
3196
  })
3096
3197
  )
@@ -3203,6 +3304,8 @@ export {
3203
3304
  getOrCreateChannel,
3204
3305
  getOrCreateController,
3205
3306
  getOrCreateNode,
3307
+ getOrganizationState,
3308
+ getOrganizationsState,
3206
3309
  getPathDepth,
3207
3310
  getPermissionsState,
3208
3311
  getPerspectiveState,
@@ -3240,6 +3343,8 @@ export {
3240
3343
  resolveDatasets,
3241
3344
  resolveDocument,
3242
3345
  resolveFavoritesState,
3346
+ resolveOrganization,
3347
+ resolveOrganizations,
3243
3348
  resolvePermissions,
3244
3349
  resolvePreview,
3245
3350
  resolveProject,