@sanity/sdk 2.11.1 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks-dts/utils.d.ts +175 -19
- package/dist/_chunks-es/_internal.js +41 -26
- package/dist/_chunks-es/_internal.js.map +1 -1
- package/dist/_chunks-es/createGroqSearchFilter.js +15 -4
- package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
- package/dist/_chunks-es/telemetryManager.js +25 -19
- package/dist/_chunks-es/telemetryManager.js.map +1 -1
- package/dist/_chunks-es/version.js +1 -1
- package/dist/_exports/_internal.d.ts +27 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +465 -131
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/_exports/index.ts +23 -2
- package/src/config/sanityConfig.ts +12 -0
- package/src/document/actions.test.ts +112 -1
- package/src/document/actions.ts +148 -1
- package/src/document/applyDocumentActions.test.ts +24 -0
- package/src/document/applyDocumentActions.ts +17 -5
- package/src/document/documentConstants.ts +7 -0
- package/src/document/documentStore.test.ts +69 -0
- package/src/document/documentStore.ts +42 -10
- package/src/document/events.test.ts +57 -2
- package/src/document/events.ts +43 -24
- package/src/document/listen.ts +1 -1
- package/src/document/permissions.test.ts +79 -0
- package/src/document/permissions.ts +8 -7
- package/src/document/processActions/create.ts +7 -4
- package/src/document/processActions/delete.ts +4 -4
- package/src/document/processActions/discard.ts +2 -2
- package/src/document/processActions/edit.ts +13 -47
- package/src/document/processActions/processActions.ts +53 -3
- package/src/document/processActions/publish.ts +4 -4
- package/src/document/processActions/releaseArchive.ts +77 -0
- package/src/document/processActions/releaseCreate.ts +59 -0
- package/src/document/processActions/releaseDelete.ts +65 -0
- package/src/document/processActions/releaseEdit.ts +37 -0
- package/src/document/processActions/releasePublish.ts +45 -0
- package/src/document/processActions/releaseSchedule.ts +87 -0
- package/src/document/processActions/releaseUtil.ts +31 -0
- package/src/document/processActions/shared.ts +108 -4
- package/src/document/processActions/unpublish.ts +3 -3
- package/src/document/processActions.test.ts +423 -1
- package/src/document/reducers.ts +44 -8
- package/src/document/resourceRules.test.ts +178 -0
- package/src/document/resourceRules.ts +117 -0
- package/src/releases/getPerspectiveState.test.ts +1 -1
- package/src/releases/releasesStore.test.ts +50 -1
- package/src/releases/releasesStore.ts +41 -18
- package/src/releases/utils/sortReleases.test.ts +2 -2
- package/src/releases/utils/sortReleases.ts +1 -1
- package/src/telemetry/environment.test.ts +119 -0
- package/src/telemetry/environment.ts +92 -0
- package/src/telemetry/{__telemetry__/sdk.telemetry.ts → events.ts} +9 -9
- package/src/telemetry/initTelemetry.test.ts +240 -16
- package/src/telemetry/initTelemetry.ts +39 -16
- package/src/telemetry/telemetryManager.test.ts +129 -65
- package/src/telemetry/telemetryManager.ts +41 -29
- package/src/telemetry/devMode.test.ts +0 -60
- package/src/telemetry/devMode.ts +0 -41
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, getAuthState, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType,
|
|
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, 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, 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, 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";
|
|
@@ -519,7 +519,7 @@ const handleAuthCallback = bindActionGlobally(
|
|
|
519
519
|
status: nodeEntry.status
|
|
520
520
|
} : void 0),
|
|
521
521
|
onSubscribe: ({ state, instance }, nodeInput) => {
|
|
522
|
-
const nodeName = nodeInput.name, subscriberId = Symbol("comlink-node-subscriber");
|
|
522
|
+
const nodeName = nodeInput.name, subscriberId = /* @__PURE__ */ Symbol("comlink-node-subscriber");
|
|
523
523
|
getOrCreateNode(instance, nodeInput);
|
|
524
524
|
let subs = state.get().subscriptions.get(nodeName);
|
|
525
525
|
return subs || (subs = /* @__PURE__ */ new Set(), state.get().subscriptions.set(nodeName, subs)), subs.add(subscriberId), () => {
|
|
@@ -642,7 +642,47 @@ function discardDocument(doc) {
|
|
|
642
642
|
documentId: effectiveDocumentId
|
|
643
643
|
};
|
|
644
644
|
}
|
|
645
|
-
|
|
645
|
+
function createRelease(handle, metadata = { releaseType: "undecided" }) {
|
|
646
|
+
return { type: "release.create", ...handle, metadata };
|
|
647
|
+
}
|
|
648
|
+
function editRelease(handle, patch) {
|
|
649
|
+
return { type: "release.edit", ...handle, patch };
|
|
650
|
+
}
|
|
651
|
+
function publishRelease(handle) {
|
|
652
|
+
return { type: "release.publish", ...handle };
|
|
653
|
+
}
|
|
654
|
+
function scheduleRelease(handle, publishAt) {
|
|
655
|
+
return { type: "release.schedule", ...handle, publishAt };
|
|
656
|
+
}
|
|
657
|
+
function unscheduleRelease(handle) {
|
|
658
|
+
return { type: "release.unschedule", ...handle };
|
|
659
|
+
}
|
|
660
|
+
function archiveRelease(handle) {
|
|
661
|
+
return { type: "release.archive", ...handle };
|
|
662
|
+
}
|
|
663
|
+
function unarchiveRelease(handle) {
|
|
664
|
+
return { type: "release.unarchive", ...handle };
|
|
665
|
+
}
|
|
666
|
+
function deleteRelease(handle) {
|
|
667
|
+
return { type: "release.delete", ...handle };
|
|
668
|
+
}
|
|
669
|
+
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
|
+
function getReleaseDocumentId(releaseId) {
|
|
671
|
+
return `${RELEASE_DOCUMENTS_PATH}.${releaseId}`;
|
|
672
|
+
}
|
|
673
|
+
const RELEASE_ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
674
|
+
"release.create",
|
|
675
|
+
"release.edit",
|
|
676
|
+
"release.publish",
|
|
677
|
+
"release.schedule",
|
|
678
|
+
"release.unschedule",
|
|
679
|
+
"release.archive",
|
|
680
|
+
"release.unarchive",
|
|
681
|
+
"release.delete"
|
|
682
|
+
]);
|
|
683
|
+
function isReleaseAction(action) {
|
|
684
|
+
return RELEASE_ACTION_TYPES.has(action.type);
|
|
685
|
+
}
|
|
646
686
|
function generateArrayKey(length = 12) {
|
|
647
687
|
const numBytes = Math.ceil(length / 2), bytes = crypto.getRandomValues(new Uint8Array(numBytes));
|
|
648
688
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
@@ -1146,6 +1186,52 @@ class MultiKeyWeakMap {
|
|
|
1146
1186
|
this.#setDeep(arrangedKeys, this.#rootMap, value);
|
|
1147
1187
|
}
|
|
1148
1188
|
}
|
|
1189
|
+
function checkGrant(grantExpr, document, identity) {
|
|
1190
|
+
const value = evaluateSync(grantExpr, { params: { document }, identity });
|
|
1191
|
+
return value.type === "boolean" && value.data;
|
|
1192
|
+
}
|
|
1193
|
+
class ActionError extends Error {
|
|
1194
|
+
documentId;
|
|
1195
|
+
transactionId;
|
|
1196
|
+
constructor(options) {
|
|
1197
|
+
super(options.message), Object.assign(this, options);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
class PermissionActionError extends ActionError {
|
|
1201
|
+
}
|
|
1202
|
+
function applySingleDocPatch({
|
|
1203
|
+
base: initialBase,
|
|
1204
|
+
working: initialWorking,
|
|
1205
|
+
documentId,
|
|
1206
|
+
patches,
|
|
1207
|
+
transactionId,
|
|
1208
|
+
timestamp,
|
|
1209
|
+
grants,
|
|
1210
|
+
identity,
|
|
1211
|
+
notFoundMessage = "Cannot edit document because it does not exist.",
|
|
1212
|
+
permissionMessage = `You do not have permission to edit document "${documentId}".`
|
|
1213
|
+
}) {
|
|
1214
|
+
let base = initialBase, working = initialWorking;
|
|
1215
|
+
const userPatches = patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
|
|
1216
|
+
if (!userPatches?.length)
|
|
1217
|
+
return { base, working, diffedPatches: [], workingMutations: [] };
|
|
1218
|
+
if (!working[documentId] || !base[documentId])
|
|
1219
|
+
throw new ActionError({ documentId, transactionId, message: notFoundMessage });
|
|
1220
|
+
const baseBefore = base[documentId];
|
|
1221
|
+
base = processMutations({ documents: base, transactionId, mutations: userPatches, timestamp });
|
|
1222
|
+
const baseAfter = base[documentId], diffedPatches = diffValue(baseBefore, baseAfter), workingBefore = working[documentId];
|
|
1223
|
+
if (!checkGrant(grants.update, workingBefore, identity))
|
|
1224
|
+
throw new PermissionActionError({ documentId, transactionId, message: permissionMessage });
|
|
1225
|
+
const workingMutations = diffedPatches.map((patch) => ({
|
|
1226
|
+
patch: { id: documentId, ...patch }
|
|
1227
|
+
}));
|
|
1228
|
+
return working = processMutations({
|
|
1229
|
+
documents: working,
|
|
1230
|
+
transactionId,
|
|
1231
|
+
mutations: workingMutations,
|
|
1232
|
+
timestamp
|
|
1233
|
+
}), { base, working, diffedPatches, workingMutations };
|
|
1234
|
+
}
|
|
1149
1235
|
function createGrantsLookup(datasetAcl) {
|
|
1150
1236
|
const filtersByGrant = {
|
|
1151
1237
|
create: /* @__PURE__ */ new Set(),
|
|
@@ -1156,7 +1242,7 @@ function createGrantsLookup(datasetAcl) {
|
|
|
1156
1242
|
for (const entry of datasetAcl)
|
|
1157
1243
|
for (const grant of entry.permissions) {
|
|
1158
1244
|
const set2 = filtersByGrant[grant];
|
|
1159
|
-
set2.add(entry.filter), filtersByGrant[grant] = set2;
|
|
1245
|
+
set2 && (set2.add(entry.filter), filtersByGrant[grant] = set2);
|
|
1160
1246
|
}
|
|
1161
1247
|
return Object.fromEntries(
|
|
1162
1248
|
Object.entries(filtersByGrant).map(([grant, filters]) => {
|
|
@@ -1206,22 +1292,18 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
|
|
|
1206
1292
|
const normalizedActions = Array.isArray(actions) ? actions : [actions], actionsKey = JSON.stringify(normalizedActions);
|
|
1207
1293
|
return nestedCache.get(actionsKey) || (nestedCache.set(actionsKey, normalizedActions), normalizedActions);
|
|
1208
1294
|
}
|
|
1209
|
-
);
|
|
1210
|
-
function checkGrant$1(grantExpr, document) {
|
|
1211
|
-
const value = evaluateSync(grantExpr, { params: { document } });
|
|
1212
|
-
return value.type === "boolean" && value.data;
|
|
1213
|
-
}
|
|
1214
|
-
const enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
|
|
1295
|
+
), enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
|
|
1215
1296
|
function calculatePermissions(...args) {
|
|
1216
1297
|
return _calculatePermissions(...args);
|
|
1217
1298
|
}
|
|
1218
1299
|
const _calculatePermissions = createSelector(
|
|
1219
1300
|
[
|
|
1220
1301
|
({ state: { grants } }) => grants,
|
|
1302
|
+
({ state: { identity } }) => identity,
|
|
1221
1303
|
documentsSelector,
|
|
1222
1304
|
memoizedActionsSelector
|
|
1223
1305
|
],
|
|
1224
|
-
(grants, documents, actions) => {
|
|
1306
|
+
(grants, identity, documents, actions) => {
|
|
1225
1307
|
if (!documents || !grants || !actions) return;
|
|
1226
1308
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString(), reasons = [];
|
|
1227
1309
|
try {
|
|
@@ -1231,7 +1313,8 @@ const _calculatePermissions = createSelector(
|
|
|
1231
1313
|
working: documents,
|
|
1232
1314
|
base: documents,
|
|
1233
1315
|
timestamp,
|
|
1234
|
-
grants
|
|
1316
|
+
grants,
|
|
1317
|
+
identity
|
|
1235
1318
|
});
|
|
1236
1319
|
} catch (error) {
|
|
1237
1320
|
if (error instanceof PermissionActionError)
|
|
@@ -1253,7 +1336,7 @@ const _calculatePermissions = createSelector(
|
|
|
1253
1336
|
if (action.type === "document.edit" && !action.patches?.length) {
|
|
1254
1337
|
const docId = action.documentId;
|
|
1255
1338
|
let doc;
|
|
1256
|
-
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
|
|
1339
|
+
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({
|
|
1257
1340
|
type: "access",
|
|
1258
1341
|
message: `You are not allowed to edit the document with ID "${docId}".`,
|
|
1259
1342
|
documentId: docId
|
|
@@ -1277,21 +1360,8 @@ const _calculatePermissions = createSelector(
|
|
|
1277
1360
|
};
|
|
1278
1361
|
}
|
|
1279
1362
|
);
|
|
1280
|
-
function checkGrant(grantExpr, document) {
|
|
1281
|
-
const value = evaluateSync(grantExpr, { params: { document } });
|
|
1282
|
-
return value.type === "boolean" && value.data;
|
|
1283
|
-
}
|
|
1284
|
-
class ActionError extends Error {
|
|
1285
|
-
documentId;
|
|
1286
|
-
transactionId;
|
|
1287
|
-
constructor(options) {
|
|
1288
|
-
super(options.message), Object.assign(this, options);
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
class PermissionActionError extends ActionError {
|
|
1292
|
-
}
|
|
1293
1363
|
function handleCreate(action, ctx) {
|
|
1294
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1364
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1295
1365
|
let { base, working } = ctx;
|
|
1296
1366
|
const documentId = getId(action.documentId);
|
|
1297
1367
|
if (action.liveEdit) {
|
|
@@ -1316,7 +1386,7 @@ function handleCreate(action, ctx) {
|
|
|
1316
1386
|
transactionId,
|
|
1317
1387
|
mutations: mutations2,
|
|
1318
1388
|
timestamp
|
|
1319
|
-
}), !checkGrant(grants.create, working[documentId]))
|
|
1389
|
+
}), !checkGrant(grants.create, working[documentId], identity))
|
|
1320
1390
|
throw new PermissionActionError({
|
|
1321
1391
|
documentId,
|
|
1322
1392
|
transactionId,
|
|
@@ -1354,13 +1424,13 @@ function handleCreate(action, ctx) {
|
|
|
1354
1424
|
transactionId,
|
|
1355
1425
|
mutations,
|
|
1356
1426
|
timestamp
|
|
1357
|
-
}), versionId && !checkGrant(grants.create, working[versionId]))
|
|
1427
|
+
}), versionId && !checkGrant(grants.create, working[versionId], identity))
|
|
1358
1428
|
throw new PermissionActionError({
|
|
1359
1429
|
documentId,
|
|
1360
1430
|
transactionId,
|
|
1361
1431
|
message: `You do not have permission to create a release version for document "${documentId}".`
|
|
1362
1432
|
});
|
|
1363
|
-
if (!versionId && !checkGrant(grants.create, working[draftId]))
|
|
1433
|
+
if (!versionId && !checkGrant(grants.create, working[draftId], identity))
|
|
1364
1434
|
throw new PermissionActionError({
|
|
1365
1435
|
documentId,
|
|
1366
1436
|
transactionId,
|
|
@@ -1373,7 +1443,7 @@ function handleCreate(action, ctx) {
|
|
|
1373
1443
|
}), { base, working };
|
|
1374
1444
|
}
|
|
1375
1445
|
function handleDelete(action, ctx) {
|
|
1376
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1446
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1377
1447
|
let { base, working } = ctx;
|
|
1378
1448
|
const documentId = action.documentId;
|
|
1379
1449
|
if (isReleasePerspective(action.perspective))
|
|
@@ -1389,7 +1459,7 @@ function handleDelete(action, ctx) {
|
|
|
1389
1459
|
transactionId,
|
|
1390
1460
|
message: "The document you are trying to delete does not exist."
|
|
1391
1461
|
});
|
|
1392
|
-
if (!checkGrant(grants.update, working[documentId]))
|
|
1462
|
+
if (!checkGrant(grants.update, working[documentId], identity))
|
|
1393
1463
|
throw new PermissionActionError({
|
|
1394
1464
|
documentId,
|
|
1395
1465
|
transactionId,
|
|
@@ -1405,7 +1475,7 @@ function handleDelete(action, ctx) {
|
|
|
1405
1475
|
transactionId,
|
|
1406
1476
|
message: working[draftId] ? "Cannot delete a document without a published version." : "The document you are trying to delete does not exist."
|
|
1407
1477
|
});
|
|
1408
|
-
const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId]), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId]);
|
|
1478
|
+
const cantDeleteDraft = working[draftId] && !checkGrant(grants.update, working[draftId], identity), cantDeletePublished = working[publishedId] && !checkGrant(grants.update, working[publishedId], identity);
|
|
1409
1479
|
if (cantDeleteDraft || cantDeletePublished)
|
|
1410
1480
|
throw new PermissionActionError({
|
|
1411
1481
|
documentId,
|
|
@@ -1420,7 +1490,7 @@ function handleDelete(action, ctx) {
|
|
|
1420
1490
|
}), { base, working };
|
|
1421
1491
|
}
|
|
1422
1492
|
function handleDiscard(action, ctx) {
|
|
1423
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1493
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1424
1494
|
let { base, working } = ctx;
|
|
1425
1495
|
const documentId = getId(action.documentId);
|
|
1426
1496
|
if (action.liveEdit)
|
|
@@ -1436,7 +1506,7 @@ function handleDiscard(action, ctx) {
|
|
|
1436
1506
|
transactionId,
|
|
1437
1507
|
message: `There is no draft or version available to discard for document "${documentId}".`
|
|
1438
1508
|
});
|
|
1439
|
-
if (!checkGrant(grants.update, working[versionId]))
|
|
1509
|
+
if (!checkGrant(grants.update, working[versionId], identity))
|
|
1440
1510
|
throw new PermissionActionError({
|
|
1441
1511
|
documentId,
|
|
1442
1512
|
transactionId,
|
|
@@ -1448,39 +1518,21 @@ function handleDiscard(action, ctx) {
|
|
|
1448
1518
|
}), { base, working };
|
|
1449
1519
|
}
|
|
1450
1520
|
function handleEdit(action, ctx) {
|
|
1451
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1521
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1452
1522
|
let { base, working } = ctx;
|
|
1453
1523
|
const documentId = getId(action.documentId);
|
|
1454
1524
|
if (action.liveEdit) {
|
|
1455
|
-
const
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
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,
|
|
1525
|
+
const result = applySingleDocPatch({
|
|
1526
|
+
base,
|
|
1527
|
+
working,
|
|
1528
|
+
documentId,
|
|
1529
|
+
patches: action.patches,
|
|
1480
1530
|
transactionId,
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1531
|
+
timestamp,
|
|
1532
|
+
grants,
|
|
1533
|
+
identity
|
|
1534
|
+
});
|
|
1535
|
+
return outgoingMutations.push(...result.workingMutations), { base: result.base, working: result.working };
|
|
1484
1536
|
}
|
|
1485
1537
|
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
1538
|
patch: { id: patchDocumentId, ...patch }
|
|
@@ -1511,7 +1563,7 @@ function handleEdit(action, ctx) {
|
|
|
1511
1563
|
const baseAfter = base[patchDocumentId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
|
|
1512
1564
|
if (!isReleasePerspective(action.perspective) && !working[draftId] && working[publishedId]) {
|
|
1513
1565
|
const newDraftFromPublished = { ...working[publishedId], _id: draftId };
|
|
1514
|
-
if (!checkGrant(grants.create, newDraftFromPublished))
|
|
1566
|
+
if (!checkGrant(grants.create, newDraftFromPublished, identity))
|
|
1515
1567
|
throw new PermissionActionError({
|
|
1516
1568
|
documentId,
|
|
1517
1569
|
transactionId,
|
|
@@ -1520,7 +1572,7 @@ function handleEdit(action, ctx) {
|
|
|
1520
1572
|
workingMutations.push({ create: newDraftFromPublished });
|
|
1521
1573
|
}
|
|
1522
1574
|
const workingBefore = working[patchDocumentId] ?? working[publishedId];
|
|
1523
|
-
if (!checkGrant(grants.update, workingBefore))
|
|
1575
|
+
if (!checkGrant(grants.update, workingBefore, identity))
|
|
1524
1576
|
throw new PermissionActionError({
|
|
1525
1577
|
documentId,
|
|
1526
1578
|
transactionId,
|
|
@@ -1541,7 +1593,7 @@ function handleEdit(action, ctx) {
|
|
|
1541
1593
|
), { base, working };
|
|
1542
1594
|
}
|
|
1543
1595
|
function handlePublish(action, ctx) {
|
|
1544
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1596
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1545
1597
|
let { base, working } = ctx;
|
|
1546
1598
|
const documentId = getId(action.documentId);
|
|
1547
1599
|
if (action.liveEdit || isReleasePerspective(action.perspective))
|
|
@@ -1564,19 +1616,19 @@ function handlePublish(action, ctx) {
|
|
|
1564
1616
|
message: "Publish aborted: The document has changed elsewhere. Please try again."
|
|
1565
1617
|
});
|
|
1566
1618
|
const newPublishedFromDraft = { ...strengthenOnPublish(workingDraft), _id: publishedId }, mutations = [{ delete: { id: draftId } }, { createOrReplace: newPublishedFromDraft }];
|
|
1567
|
-
if (working[draftId] && !checkGrant(grants.update, working[draftId]))
|
|
1619
|
+
if (working[draftId] && !checkGrant(grants.update, working[draftId], identity))
|
|
1568
1620
|
throw new PermissionActionError({
|
|
1569
1621
|
documentId,
|
|
1570
1622
|
transactionId,
|
|
1571
1623
|
message: `Publish failed: You do not have permission to update the draft for "${documentId}".`
|
|
1572
1624
|
});
|
|
1573
|
-
if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft))
|
|
1625
|
+
if (working[publishedId] && !checkGrant(grants.update, newPublishedFromDraft, identity))
|
|
1574
1626
|
throw new PermissionActionError({
|
|
1575
1627
|
documentId,
|
|
1576
1628
|
transactionId,
|
|
1577
1629
|
message: `Publish failed: You do not have permission to update the published version of "${documentId}".`
|
|
1578
1630
|
});
|
|
1579
|
-
if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft))
|
|
1631
|
+
if (!working[publishedId] && !checkGrant(grants.create, newPublishedFromDraft, identity))
|
|
1580
1632
|
throw new PermissionActionError({
|
|
1581
1633
|
documentId,
|
|
1582
1634
|
transactionId,
|
|
@@ -1603,8 +1655,191 @@ function strengthenOnPublish(draft) {
|
|
|
1603
1655
|
}
|
|
1604
1656
|
return strengthen(draft);
|
|
1605
1657
|
}
|
|
1658
|
+
function handleReleaseArchive(action, ctx) {
|
|
1659
|
+
const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1660
|
+
if (!existing)
|
|
1661
|
+
throw new ActionError({
|
|
1662
|
+
documentId: releaseDocumentId,
|
|
1663
|
+
transactionId,
|
|
1664
|
+
message: `Cannot archive release "${action.releaseId}" because it does not exist.`
|
|
1665
|
+
});
|
|
1666
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1667
|
+
throw new PermissionActionError({
|
|
1668
|
+
documentId: releaseDocumentId,
|
|
1669
|
+
transactionId,
|
|
1670
|
+
message: `You do not have permission to archive release "${action.releaseId}".`
|
|
1671
|
+
});
|
|
1672
|
+
return outgoingActions.push({
|
|
1673
|
+
actionType: "sanity.action.release.archive",
|
|
1674
|
+
releaseId: action.releaseId
|
|
1675
|
+
}), { base, working };
|
|
1676
|
+
}
|
|
1677
|
+
function handleReleaseUnarchive(action, ctx) {
|
|
1678
|
+
const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1679
|
+
if (!existing)
|
|
1680
|
+
throw new ActionError({
|
|
1681
|
+
documentId: releaseDocumentId,
|
|
1682
|
+
transactionId,
|
|
1683
|
+
message: `Cannot unarchive release "${action.releaseId}" because it does not exist.`
|
|
1684
|
+
});
|
|
1685
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1686
|
+
throw new PermissionActionError({
|
|
1687
|
+
documentId: releaseDocumentId,
|
|
1688
|
+
transactionId,
|
|
1689
|
+
message: `You do not have permission to unarchive release "${action.releaseId}".`
|
|
1690
|
+
});
|
|
1691
|
+
return outgoingActions.push({
|
|
1692
|
+
actionType: "sanity.action.release.unarchive",
|
|
1693
|
+
releaseId: action.releaseId
|
|
1694
|
+
}), { base, working };
|
|
1695
|
+
}
|
|
1696
|
+
function handleReleaseCreate(action, ctx) {
|
|
1697
|
+
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx;
|
|
1698
|
+
let { base, working } = ctx;
|
|
1699
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId);
|
|
1700
|
+
if (working[releaseDocumentId] || base[releaseDocumentId])
|
|
1701
|
+
throw new ActionError({
|
|
1702
|
+
documentId: releaseDocumentId,
|
|
1703
|
+
transactionId,
|
|
1704
|
+
message: `A release with id "${action.releaseId}" already exists.`
|
|
1705
|
+
});
|
|
1706
|
+
const mutations = [{ create: {
|
|
1707
|
+
_id: releaseDocumentId,
|
|
1708
|
+
_type: "system.release",
|
|
1709
|
+
name: action.releaseId,
|
|
1710
|
+
state: "active",
|
|
1711
|
+
metadata: action.metadata
|
|
1712
|
+
} }];
|
|
1713
|
+
if (base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), !checkGrant(grants.create, working[releaseDocumentId], identity))
|
|
1714
|
+
throw new PermissionActionError({
|
|
1715
|
+
documentId: releaseDocumentId,
|
|
1716
|
+
transactionId,
|
|
1717
|
+
message: `You do not have permission to create release "${action.releaseId}".`
|
|
1718
|
+
});
|
|
1719
|
+
return outgoingMutations.push(...mutations), outgoingActions.push({
|
|
1720
|
+
actionType: "sanity.action.release.create",
|
|
1721
|
+
releaseId: action.releaseId,
|
|
1722
|
+
metadata: action.metadata
|
|
1723
|
+
}), { base, working };
|
|
1724
|
+
}
|
|
1725
|
+
const DELETABLE_STATES = /* @__PURE__ */ new Set(["archived", "published"]);
|
|
1726
|
+
function handleReleaseDelete(action, ctx) {
|
|
1727
|
+
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx;
|
|
1728
|
+
let { base, working } = ctx;
|
|
1729
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1730
|
+
if (!existing)
|
|
1731
|
+
throw new ActionError({
|
|
1732
|
+
documentId: releaseDocumentId,
|
|
1733
|
+
transactionId,
|
|
1734
|
+
message: `Cannot delete release "${action.releaseId}" because it does not exist.`
|
|
1735
|
+
});
|
|
1736
|
+
const state = existing.state;
|
|
1737
|
+
if (state && typeof state == "string" && !DELETABLE_STATES.has(state))
|
|
1738
|
+
throw new ActionError({
|
|
1739
|
+
documentId: releaseDocumentId,
|
|
1740
|
+
transactionId,
|
|
1741
|
+
message: `Cannot delete release "${action.releaseId}" while it is "${state}". Archive it first.`
|
|
1742
|
+
});
|
|
1743
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1744
|
+
throw new PermissionActionError({
|
|
1745
|
+
documentId: releaseDocumentId,
|
|
1746
|
+
transactionId,
|
|
1747
|
+
message: `You do not have permission to delete release "${action.releaseId}".`
|
|
1748
|
+
});
|
|
1749
|
+
const mutations = [{ delete: { id: releaseDocumentId } }];
|
|
1750
|
+
return base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
|
|
1751
|
+
actionType: "sanity.action.release.delete",
|
|
1752
|
+
releaseId: action.releaseId
|
|
1753
|
+
}), { base, working };
|
|
1754
|
+
}
|
|
1755
|
+
function handleReleaseEdit(action, ctx) {
|
|
1756
|
+
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity } = ctx, { base, working } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), result = applySingleDocPatch({
|
|
1757
|
+
base,
|
|
1758
|
+
working,
|
|
1759
|
+
documentId: releaseDocumentId,
|
|
1760
|
+
patches: [action.patch],
|
|
1761
|
+
transactionId,
|
|
1762
|
+
timestamp,
|
|
1763
|
+
grants,
|
|
1764
|
+
identity,
|
|
1765
|
+
notFoundMessage: `Cannot edit release "${action.releaseId}" because it does not exist.`,
|
|
1766
|
+
permissionMessage: `You do not have permission to edit release "${action.releaseId}".`
|
|
1767
|
+
});
|
|
1768
|
+
return outgoingMutations.push(...result.workingMutations), outgoingActions.push(
|
|
1769
|
+
...result.diffedPatches.map((patch) => ({
|
|
1770
|
+
actionType: "sanity.action.release.edit",
|
|
1771
|
+
releaseId: action.releaseId,
|
|
1772
|
+
patch
|
|
1773
|
+
}))
|
|
1774
|
+
), { base: result.base, working: result.working };
|
|
1775
|
+
}
|
|
1776
|
+
function handleReleasePublish(action, ctx) {
|
|
1777
|
+
const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1778
|
+
if (!existing)
|
|
1779
|
+
throw new ActionError({
|
|
1780
|
+
documentId: releaseDocumentId,
|
|
1781
|
+
transactionId,
|
|
1782
|
+
message: `Cannot publish release "${action.releaseId}" because it does not exist.`
|
|
1783
|
+
});
|
|
1784
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1785
|
+
throw new PermissionActionError({
|
|
1786
|
+
documentId: releaseDocumentId,
|
|
1787
|
+
transactionId,
|
|
1788
|
+
message: `You do not have permission to publish release "${action.releaseId}".`
|
|
1789
|
+
});
|
|
1790
|
+
return outgoingActions.push({
|
|
1791
|
+
actionType: "sanity.action.release.publish",
|
|
1792
|
+
releaseId: action.releaseId
|
|
1793
|
+
}), { base, working };
|
|
1794
|
+
}
|
|
1795
|
+
function handleReleaseSchedule(action, ctx) {
|
|
1796
|
+
const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId);
|
|
1797
|
+
if (Number.isNaN(Date.parse(action.publishAt)))
|
|
1798
|
+
throw new ActionError({
|
|
1799
|
+
documentId: releaseDocumentId,
|
|
1800
|
+
transactionId,
|
|
1801
|
+
message: `Cannot schedule release "${action.releaseId}": "publishAt" must be a valid ISO 8601 timestamp (received "${action.publishAt}").`
|
|
1802
|
+
});
|
|
1803
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1804
|
+
if (!existing)
|
|
1805
|
+
throw new ActionError({
|
|
1806
|
+
documentId: releaseDocumentId,
|
|
1807
|
+
transactionId,
|
|
1808
|
+
message: `Cannot schedule release "${action.releaseId}" because it does not exist.`
|
|
1809
|
+
});
|
|
1810
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1811
|
+
throw new PermissionActionError({
|
|
1812
|
+
documentId: releaseDocumentId,
|
|
1813
|
+
transactionId,
|
|
1814
|
+
message: `You do not have permission to schedule release "${action.releaseId}".`
|
|
1815
|
+
});
|
|
1816
|
+
return outgoingActions.push({
|
|
1817
|
+
actionType: "sanity.action.release.schedule",
|
|
1818
|
+
releaseId: action.releaseId,
|
|
1819
|
+
publishAt: action.publishAt
|
|
1820
|
+
}), { base, working };
|
|
1821
|
+
}
|
|
1822
|
+
function handleReleaseUnschedule(action, ctx) {
|
|
1823
|
+
const { base, working, grants, outgoingActions, transactionId, identity } = ctx, releaseDocumentId = getReleaseDocumentId(action.releaseId), existing = working[releaseDocumentId] ?? base[releaseDocumentId];
|
|
1824
|
+
if (!existing)
|
|
1825
|
+
throw new ActionError({
|
|
1826
|
+
documentId: releaseDocumentId,
|
|
1827
|
+
transactionId,
|
|
1828
|
+
message: `Cannot unschedule release "${action.releaseId}" because it does not exist.`
|
|
1829
|
+
});
|
|
1830
|
+
if (!checkGrant(grants.update, existing, identity))
|
|
1831
|
+
throw new PermissionActionError({
|
|
1832
|
+
documentId: releaseDocumentId,
|
|
1833
|
+
transactionId,
|
|
1834
|
+
message: `You do not have permission to unschedule release "${action.releaseId}".`
|
|
1835
|
+
});
|
|
1836
|
+
return outgoingActions.push({
|
|
1837
|
+
actionType: "sanity.action.release.unschedule",
|
|
1838
|
+
releaseId: action.releaseId
|
|
1839
|
+
}), { base, working };
|
|
1840
|
+
}
|
|
1606
1841
|
function handleUnpublish(action, ctx) {
|
|
1607
|
-
const { transactionId, timestamp, grants, outgoingActions, outgoingMutations } = ctx;
|
|
1842
|
+
const { transactionId, timestamp, grants, identity, outgoingActions, outgoingMutations } = ctx;
|
|
1608
1843
|
let { base, working } = ctx;
|
|
1609
1844
|
const documentId = getId(action.documentId);
|
|
1610
1845
|
if (action.liveEdit || isReleasePerspective(action.perspective))
|
|
@@ -1624,13 +1859,13 @@ function handleUnpublish(action, ctx) {
|
|
|
1624
1859
|
{ delete: { id: publishedId } },
|
|
1625
1860
|
{ createIfNotExists: newDraftFromPublished }
|
|
1626
1861
|
];
|
|
1627
|
-
if (!checkGrant(grants.update, sourceDoc))
|
|
1862
|
+
if (!checkGrant(grants.update, sourceDoc, identity))
|
|
1628
1863
|
throw new PermissionActionError({
|
|
1629
1864
|
documentId,
|
|
1630
1865
|
transactionId,
|
|
1631
1866
|
message: `You do not have permission to unpublish the document "${documentId}".`
|
|
1632
1867
|
});
|
|
1633
|
-
if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished))
|
|
1868
|
+
if (!working[draftId] && !checkGrant(grants.create, newDraftFromPublished, identity))
|
|
1634
1869
|
throw new PermissionActionError({
|
|
1635
1870
|
documentId,
|
|
1636
1871
|
transactionId,
|
|
@@ -1656,10 +1891,17 @@ function processActions({
|
|
|
1656
1891
|
working: initialWorking,
|
|
1657
1892
|
base: initialBase,
|
|
1658
1893
|
timestamp,
|
|
1659
|
-
grants
|
|
1894
|
+
grants,
|
|
1895
|
+
identity
|
|
1660
1896
|
}) {
|
|
1661
1897
|
let base = { ...initialBase }, working = { ...initialWorking };
|
|
1662
|
-
const outgoingActions = [], outgoingMutations = [];
|
|
1898
|
+
const outgoingActions = [], outgoingMutations = [], liveEditAction = actions.find((action) => !isReleaseAction(action) && action.liveEdit), otherAction = actions.find((action) => isReleaseAction(action) || !action.liveEdit);
|
|
1899
|
+
if (liveEditAction && otherAction)
|
|
1900
|
+
throw new ActionError({
|
|
1901
|
+
documentId: liveEditAction.documentId,
|
|
1902
|
+
transactionId,
|
|
1903
|
+
message: "Cannot combine liveEdit document actions with other actions in the same transaction. Submit them as separate transactions."
|
|
1904
|
+
});
|
|
1663
1905
|
for (const action of actions) {
|
|
1664
1906
|
const result = dispatch(action, {
|
|
1665
1907
|
base,
|
|
@@ -1667,6 +1909,7 @@ function processActions({
|
|
|
1667
1909
|
transactionId,
|
|
1668
1910
|
timestamp,
|
|
1669
1911
|
grants,
|
|
1912
|
+
identity,
|
|
1670
1913
|
outgoingActions,
|
|
1671
1914
|
outgoingMutations
|
|
1672
1915
|
});
|
|
@@ -1697,6 +1940,22 @@ function dispatch(action, ctx) {
|
|
|
1697
1940
|
return handlePublish(action, ctx);
|
|
1698
1941
|
case "document.unpublish":
|
|
1699
1942
|
return handleUnpublish(action, ctx);
|
|
1943
|
+
case "release.create":
|
|
1944
|
+
return handleReleaseCreate(action, ctx);
|
|
1945
|
+
case "release.edit":
|
|
1946
|
+
return handleReleaseEdit(action, ctx);
|
|
1947
|
+
case "release.publish":
|
|
1948
|
+
return handleReleasePublish(action, ctx);
|
|
1949
|
+
case "release.schedule":
|
|
1950
|
+
return handleReleaseSchedule(action, ctx);
|
|
1951
|
+
case "release.unschedule":
|
|
1952
|
+
return handleReleaseUnschedule(action, ctx);
|
|
1953
|
+
case "release.archive":
|
|
1954
|
+
return handleReleaseArchive(action, ctx);
|
|
1955
|
+
case "release.unarchive":
|
|
1956
|
+
return handleReleaseUnarchive(action, ctx);
|
|
1957
|
+
case "release.delete":
|
|
1958
|
+
return handleReleaseDelete(action, ctx);
|
|
1700
1959
|
default:
|
|
1701
1960
|
throw new Error(
|
|
1702
1961
|
`Unknown action type: "${// @ts-expect-error invalid input
|
|
@@ -1735,7 +1994,8 @@ function applyFirstQueuedTransaction(prev) {
|
|
|
1735
1994
|
working,
|
|
1736
1995
|
base: working,
|
|
1737
1996
|
timestamp,
|
|
1738
|
-
grants: prev.grants
|
|
1997
|
+
grants: prev.grants,
|
|
1998
|
+
identity: prev.identity
|
|
1739
1999
|
}), applied = {
|
|
1740
2000
|
...queued,
|
|
1741
2001
|
...result,
|
|
@@ -1779,29 +2039,31 @@ function batchAppliedTransactions([curr, ...rest]) {
|
|
|
1779
2039
|
};
|
|
1780
2040
|
if (!rest.length) return editAction;
|
|
1781
2041
|
const next = batchAppliedTransactions(rest);
|
|
1782
|
-
if (next)
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
2042
|
+
if (!next) return;
|
|
2043
|
+
if (next.disableBatching) return editAction;
|
|
2044
|
+
const nextFirst = next.actions[0], nextLiveEdit = nextFirst && "liveEdit" in nextFirst ? nextFirst.liveEdit : !1;
|
|
2045
|
+
return !!action.liveEdit != !!nextLiveEdit ? editAction : {
|
|
2046
|
+
disableBatching: !1,
|
|
2047
|
+
// Use the transactionId from the later (next) transaction.
|
|
2048
|
+
transactionId: next.transactionId,
|
|
2049
|
+
// Accumulate actions: current action first, then later ones.
|
|
2050
|
+
actions: [action, ...next.actions],
|
|
2051
|
+
// Merge outgoingActions in order.
|
|
2052
|
+
outgoingActions: [...curr.outgoingActions, ...next.outgoingActions],
|
|
2053
|
+
// Batched transaction IDs: preserve order by placing curr first.
|
|
2054
|
+
batchedTransactionIds: [curr.transactionId, ...next.batchedTransactionIds],
|
|
2055
|
+
// Merge outgoingMutations in order.
|
|
2056
|
+
outgoingMutations: [...curr.outgoingMutations, ...next.outgoingMutations],
|
|
2057
|
+
// Working state reflects the latest optimistic changes: later transactions override earlier.
|
|
2058
|
+
working: { ...curr.working, ...next.working },
|
|
2059
|
+
// Base state (base, previous, previousRevs) must reflect the original state.
|
|
2060
|
+
// Use curr values (the earliest transaction) to override later ones.
|
|
2061
|
+
previousRevs: { ...next.previousRevs, ...curr.previousRevs },
|
|
2062
|
+
previous: { ...next.previous, ...curr.previous },
|
|
2063
|
+
base: { ...next.base, ...curr.base },
|
|
2064
|
+
// Use the earliest timestamp from curr.
|
|
2065
|
+
timestamp: curr.timestamp ?? next.timestamp
|
|
2066
|
+
};
|
|
1805
2067
|
}
|
|
1806
2068
|
function transitionAppliedTransactionsToOutgoing(prev) {
|
|
1807
2069
|
if (prev.outgoing) return prev;
|
|
@@ -1855,7 +2117,7 @@ function revertOutgoingTransaction(prev) {
|
|
|
1855
2117
|
const nextApplied = [];
|
|
1856
2118
|
for (const t of prev.applied)
|
|
1857
2119
|
try {
|
|
1858
|
-
const next = processActions({ ...t, working, grants: prev.grants });
|
|
2120
|
+
const next = processActions({ ...t, working, grants: prev.grants, identity: prev.identity });
|
|
1859
2121
|
working = next.working, nextApplied.push({ ...t, ...next });
|
|
1860
2122
|
} catch (error) {
|
|
1861
2123
|
if (error instanceof ActionError) continue;
|
|
@@ -1902,7 +2164,7 @@ function applyRemoteDocument(prev, { document, documentId, previousRev, revision
|
|
|
1902
2164
|
const nextApplied = [];
|
|
1903
2165
|
for (const curr of prev.applied)
|
|
1904
2166
|
try {
|
|
1905
|
-
const next = processActions({ ...curr, working, grants: prev.grants });
|
|
2167
|
+
const next = processActions({ ...curr, working, grants: prev.grants, identity: prev.identity });
|
|
1906
2168
|
working = next.working, nextApplied.push({ ...curr, ...next });
|
|
1907
2169
|
} catch (error) {
|
|
1908
2170
|
if (error instanceof ActionError) {
|
|
@@ -1978,32 +2240,43 @@ function manageSubscriberIds({ state }, handles) {
|
|
|
1978
2240
|
}
|
|
1979
2241
|
function getDocumentIdsFromHandleLikes(handles) {
|
|
1980
2242
|
return handles.flatMap((handle) => {
|
|
2243
|
+
if ("type" in handle && isReleaseAction(handle))
|
|
2244
|
+
return [getReleaseDocumentId(handle.releaseId)];
|
|
1981
2245
|
const idsForDocument = [];
|
|
1982
2246
|
return handle.documentId ? handle.liveEdit ? [handle.documentId] : (isReleasePerspective(handle.perspective) && idsForDocument.push(
|
|
1983
2247
|
getVersionId(DocumentId(handle.documentId), handle.perspective.releaseName)
|
|
1984
2248
|
), idsForDocument.push(getPublishedId(DocumentId(handle.documentId))), idsForDocument.push(getDraftId(DocumentId(handle.documentId))), idsForDocument) : [];
|
|
1985
2249
|
});
|
|
1986
2250
|
}
|
|
2251
|
+
const actionMap = {
|
|
2252
|
+
"document.create": "created",
|
|
2253
|
+
"document.delete": "deleted",
|
|
2254
|
+
"document.discard": "discarded",
|
|
2255
|
+
"document.edit": "edited",
|
|
2256
|
+
"document.publish": "published",
|
|
2257
|
+
"document.unpublish": "unpublished",
|
|
2258
|
+
"release.create": "created",
|
|
2259
|
+
"release.edit": "edited",
|
|
2260
|
+
"release.delete": "deleted"
|
|
2261
|
+
};
|
|
1987
2262
|
function getDocumentEvents(outgoing) {
|
|
1988
|
-
const documentIdsByAction =
|
|
1989
|
-
|
|
1990
|
-
(
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
([actionType, documentIds]) => Array.from(documentIds).map(
|
|
2006
|
-
(documentId) => ({ type: actionMap[actionType], documentId, outgoing })
|
|
2263
|
+
const documentIdsByAction = outgoing.actions.reduce(
|
|
2264
|
+
(acc, action) => {
|
|
2265
|
+
if (!(action.type in actionMap)) return acc;
|
|
2266
|
+
const documentId = isReleaseAction(action) ? getReleaseDocumentId(action.releaseId) : action.documentId;
|
|
2267
|
+
if (!documentId) return acc;
|
|
2268
|
+
const type = action.type, ids = acc[type] ?? /* @__PURE__ */ new Set();
|
|
2269
|
+
return ids.add(documentId), acc[type] = ids, acc;
|
|
2270
|
+
},
|
|
2271
|
+
{}
|
|
2272
|
+
);
|
|
2273
|
+
return Object.entries(documentIdsByAction).flatMap(
|
|
2274
|
+
([actionType, documentIds]) => Array.from(documentIds ?? []).map(
|
|
2275
|
+
(documentId) => ({
|
|
2276
|
+
type: actionMap[actionType],
|
|
2277
|
+
documentId,
|
|
2278
|
+
outgoing
|
|
2279
|
+
})
|
|
2007
2280
|
)
|
|
2008
2281
|
);
|
|
2009
2282
|
}
|
|
@@ -2079,7 +2352,8 @@ const documentStore = defineStore({
|
|
|
2079
2352
|
subscribeToQueuedAndApplyNextTransaction(context),
|
|
2080
2353
|
subscribeToSubscriptionsAndListenToDocuments(context),
|
|
2081
2354
|
subscribeToAppliedAndSubmitNextTransaction(context),
|
|
2082
|
-
subscribeToClientAndFetchDatasetAcl(context)
|
|
2355
|
+
subscribeToClientAndFetchDatasetAcl(context),
|
|
2356
|
+
subscribeToCurrentUserAndSetIdentity(context)
|
|
2083
2357
|
];
|
|
2084
2358
|
return () => {
|
|
2085
2359
|
sharedListener.dispose(), subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
@@ -2227,7 +2501,7 @@ const _resolveDocument = bindActionByResource(
|
|
|
2227
2501
|
result,
|
|
2228
2502
|
outgoing
|
|
2229
2503
|
}));
|
|
2230
|
-
return outgoing.actions.some((action) => action.liveEdit) ? client.observable.mutate(outgoing.outgoingMutations, {
|
|
2504
|
+
return outgoing.actions.some((action) => !isReleaseAction(action) && action.liveEdit) ? client.observable.mutate(outgoing.outgoingMutations, {
|
|
2231
2505
|
transactionId: outgoing.transactionId,
|
|
2232
2506
|
visibility: "async",
|
|
2233
2507
|
returnDocuments: !1,
|
|
@@ -2272,8 +2546,15 @@ const _resolveDocument = bindActionByResource(
|
|
|
2272
2546
|
mergeMap$1(
|
|
2273
2547
|
(group) => group.pipe(
|
|
2274
2548
|
switchMap((e) => e.add ? listen(context, e.id).pipe(
|
|
2275
|
-
|
|
2276
|
-
|
|
2549
|
+
retry({
|
|
2550
|
+
delay: (error, retryCount) => {
|
|
2551
|
+
if (!(error instanceof OutOfSyncError)) return throwError(() => error);
|
|
2552
|
+
const backoff = Math.min(
|
|
2553
|
+
OUT_OF_SYNC_RETRY_BASE_DELAY * 2 ** (retryCount - 1),
|
|
2554
|
+
OUT_OF_SYNC_RETRY_MAX_DELAY
|
|
2555
|
+
);
|
|
2556
|
+
return timer(backoff);
|
|
2557
|
+
}
|
|
2277
2558
|
}),
|
|
2278
2559
|
tap$1(
|
|
2279
2560
|
(remote) => state.set(
|
|
@@ -2312,15 +2593,58 @@ const _resolveDocument = bindActionByResource(
|
|
|
2312
2593
|
).subscribe({
|
|
2313
2594
|
error: (error) => state.set("setError", { error })
|
|
2314
2595
|
});
|
|
2315
|
-
}
|
|
2596
|
+
}, subscribeToCurrentUserAndSetIdentity = ({
|
|
2597
|
+
instance,
|
|
2598
|
+
state
|
|
2599
|
+
}) => getCurrentUserState(instance).observable.subscribe({
|
|
2600
|
+
next: (currentUser) => state.set("setIdentity", { identity: currentUser?.id }),
|
|
2601
|
+
// A transient identity-fetch failure (network blip, expired token, or a
|
|
2602
|
+
// normal logout/re-login transition) should not brick all document
|
|
2603
|
+
// operations. Reset the identity to `undefined` and keep going — GROQ's
|
|
2604
|
+
// `identity()` then evaluates to null, matching the unauthenticated state.
|
|
2605
|
+
error: () => state.set("setIdentity", { identity: void 0 })
|
|
2606
|
+
}), MEDIA_LIBRARY_DRAFTED_TYPES = /* @__PURE__ */ new Set(["sanity.asset"]);
|
|
2607
|
+
function getEffectiveDocumentModel(resource, documentType) {
|
|
2608
|
+
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 };
|
|
2609
|
+
}
|
|
2610
|
+
function describeResource(resource) {
|
|
2611
|
+
return resource && isCanvasResource(resource) ? "Canvas" : resource && isMediaLibraryResource(resource) ? "Media Library" : "this resource";
|
|
2612
|
+
}
|
|
2613
|
+
function normalizeActionsForResource(actions, resource) {
|
|
2614
|
+
const stripped = [], normalized = actions.map((action) => {
|
|
2615
|
+
if (action.type !== "document.edit") return action;
|
|
2616
|
+
const { liveEdit: forcedLiveEdit, supportsReleases } = getEffectiveDocumentModel(
|
|
2617
|
+
resource,
|
|
2618
|
+
action.documentType
|
|
2619
|
+
), shouldRemovePerspective = isReleasePerspective(action.perspective) && !supportsReleases, shouldForceLiveEdit = forcedLiveEdit === !0 && !action.liveEdit;
|
|
2620
|
+
if (!shouldRemovePerspective && !shouldForceLiveEdit) return action;
|
|
2621
|
+
const corrected = { ...action };
|
|
2622
|
+
return shouldForceLiveEdit && (corrected.liveEdit = !0), shouldRemovePerspective && (corrected.perspective = void 0), corrected.documentId = getEffectiveDocumentId({
|
|
2623
|
+
...corrected,
|
|
2624
|
+
documentId: getPublishedId(DocumentId(corrected.documentId))
|
|
2625
|
+
}), shouldRemovePerspective && stripped.push({ documentType: action.documentType, documentId: corrected.documentId }), corrected;
|
|
2626
|
+
});
|
|
2627
|
+
if (stripped.length > 0) {
|
|
2628
|
+
const docs = stripped.map((e) => `${e.documentType} (${e.documentId})`).join(", ");
|
|
2629
|
+
console.warn(
|
|
2630
|
+
`[sanity-sdk] ${describeResource(resource)} does not support release perspectives \u2014 falling back to the standard editing path for: ${docs}`
|
|
2631
|
+
);
|
|
2632
|
+
}
|
|
2633
|
+
return normalized;
|
|
2634
|
+
}
|
|
2316
2635
|
function applyDocumentActions(...args) {
|
|
2317
2636
|
return boundApplyDocumentActions(...args);
|
|
2318
2637
|
}
|
|
2319
2638
|
const boundApplyDocumentActions = bindActionByResource(documentStore, _applyDocumentActions);
|
|
2320
|
-
async function _applyDocumentActions({ state }, {
|
|
2321
|
-
|
|
2639
|
+
async function _applyDocumentActions({ state }, {
|
|
2640
|
+
actions,
|
|
2641
|
+
resource,
|
|
2642
|
+
transactionId = crypto.randomUUID(),
|
|
2643
|
+
disableBatching
|
|
2644
|
+
}) {
|
|
2645
|
+
const { events } = state.get(), normalizedActions = normalizeActionsForResource(actions, resource), transaction = {
|
|
2322
2646
|
transactionId,
|
|
2323
|
-
actions,
|
|
2647
|
+
actions: normalizedActions,
|
|
2324
2648
|
...disableBatching && { disableBatching }
|
|
2325
2649
|
}, fatalError$ = state.observable.pipe(
|
|
2326
2650
|
map$1((s) => s.error),
|
|
@@ -3270,6 +3594,7 @@ export {
|
|
|
3270
3594
|
agentTransform,
|
|
3271
3595
|
agentTranslate,
|
|
3272
3596
|
applyDocumentActions,
|
|
3597
|
+
archiveRelease,
|
|
3273
3598
|
configureLogging,
|
|
3274
3599
|
createDatasetHandle,
|
|
3275
3600
|
createDocument,
|
|
@@ -3277,13 +3602,17 @@ export {
|
|
|
3277
3602
|
createDocumentTypeHandle,
|
|
3278
3603
|
createGroqSearchFilter,
|
|
3279
3604
|
createProjectHandle,
|
|
3605
|
+
createRelease,
|
|
3280
3606
|
createSanityInstance,
|
|
3281
3607
|
defineIntent,
|
|
3282
3608
|
deleteDocument,
|
|
3609
|
+
deleteRelease,
|
|
3283
3610
|
destroyController,
|
|
3284
3611
|
discardDocument,
|
|
3285
3612
|
editDocument,
|
|
3613
|
+
editRelease,
|
|
3286
3614
|
getActiveReleasesState,
|
|
3615
|
+
getAllReleasesState,
|
|
3287
3616
|
getAuthState,
|
|
3288
3617
|
getClient,
|
|
3289
3618
|
getClientErrorApiBody,
|
|
@@ -3316,6 +3645,7 @@ export {
|
|
|
3316
3645
|
getProjectsState,
|
|
3317
3646
|
getQueryKey,
|
|
3318
3647
|
getQueryState,
|
|
3648
|
+
getReleaseDocumentId,
|
|
3319
3649
|
getTokenState,
|
|
3320
3650
|
getUserState,
|
|
3321
3651
|
getUsersKey,
|
|
@@ -3338,6 +3668,7 @@ export {
|
|
|
3338
3668
|
parseQueryKey,
|
|
3339
3669
|
parseUsersKey,
|
|
3340
3670
|
publishDocument,
|
|
3671
|
+
publishRelease,
|
|
3341
3672
|
releaseChannel,
|
|
3342
3673
|
releaseNode,
|
|
3343
3674
|
resolveDatasets,
|
|
@@ -3353,11 +3684,14 @@ export {
|
|
|
3353
3684
|
resolveQuery,
|
|
3354
3685
|
resolveUser,
|
|
3355
3686
|
resolveUsers,
|
|
3687
|
+
scheduleRelease,
|
|
3356
3688
|
setAuthToken,
|
|
3357
3689
|
slicePath2 as slicePath,
|
|
3358
3690
|
stringifyPath2 as stringifyPath,
|
|
3359
3691
|
subscribeDocumentEvents,
|
|
3360
3692
|
transformProjectionToPreview,
|
|
3361
|
-
|
|
3693
|
+
unarchiveRelease,
|
|
3694
|
+
unpublishDocument,
|
|
3695
|
+
unscheduleRelease
|
|
3362
3696
|
};
|
|
3363
3697
|
//# sourceMappingURL=index.js.map
|