@sanity/sdk 3.0.0-rc.0 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks-dts/createGroqSearchFilter.d.ts +1147 -0
- package/dist/_chunks-dts/createGroqSearchFilter.d.ts.map +1 -0
- package/dist/_chunks-es/_internal.js +134 -0
- package/dist/_chunks-es/_internal.js.map +1 -0
- package/dist/_chunks-es/createGroqSearchFilter.js +1864 -0
- package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -0
- package/dist/_chunks-es/telemetryManager.js +93 -0
- package/dist/_chunks-es/telemetryManager.js.map +1 -0
- package/dist/_exports/_internal.d.ts +95 -0
- package/dist/_exports/_internal.d.ts.map +1 -0
- package/dist/_exports/_internal.js +24 -0
- package/dist/_exports/_internal.js.map +1 -0
- package/dist/index.d.ts +1079 -1076
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1967 -2302
- package/dist/index.js.map +1 -1
- package/package.json +48 -47
- package/src/_exports/_internal.ts +26 -0
- package/src/_exports/index.ts +120 -11
- package/src/access/checkPermissions.test.ts +55 -0
- package/src/access/checkPermissions.ts +54 -0
- package/src/agent/agentActions.test.ts +16 -60
- package/src/agent/agentActions.ts +25 -38
- package/src/applications/applications.test-d.ts +83 -0
- package/src/applications/applications.test.ts +130 -0
- package/src/applications/applications.ts +364 -0
- package/src/applications/userApplications.test.ts +126 -0
- package/src/applications/userApplications.ts +261 -0
- package/src/auth/authLogger.ts +30 -0
- package/src/auth/authMode.test.ts +25 -0
- package/src/auth/authMode.ts +6 -3
- package/src/auth/authStore.test.ts +194 -13
- package/src/auth/authStore.ts +59 -26
- package/src/auth/getOrganizationVerificationState.test.ts +18 -17
- package/src/auth/getOrganizationVerificationState.ts +4 -4
- package/src/auth/handleAuthCallback.test.ts +35 -1
- package/src/auth/handleAuthCallback.ts +25 -6
- package/src/auth/logout.test.ts +75 -2
- package/src/auth/logout.ts +23 -4
- package/src/auth/refreshStampedToken.test.ts +219 -469
- package/src/auth/refreshStampedToken.ts +79 -195
- package/src/auth/studioAuth.ts +1 -1
- package/src/auth/studioModeAuth.ts +2 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +146 -13
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +37 -6
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +2 -0
- package/src/client/clientStore.test.ts +62 -37
- package/src/client/clientStore.ts +45 -75
- package/src/client/liveEvents.test.ts +151 -0
- package/src/client/liveEvents.ts +107 -0
- package/src/comlink/controller/actions/destroyController.test.ts +4 -1
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +4 -1
- package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
- package/src/comlink/controller/actions/getOrCreateController.test.ts +4 -1
- package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
- package/src/comlink/controller/comlinkControllerStore.test.ts +4 -1
- package/src/comlink/node/actions/getOrCreateNode.test.ts +9 -3
- package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
- package/src/comlink/node/actions/releaseNode.test.ts +7 -4
- package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
- package/src/comlink/node/getNodeState.test.ts +1 -1
- package/src/comlink/node/getNodeState.ts +2 -1
- package/src/config/__tests__/handles.test.ts +18 -12
- package/src/config/handles.ts +25 -7
- package/src/config/sanityConfig.ts +109 -79
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +10 -4
- package/src/document/actions.test.ts +115 -33
- package/src/document/actions.ts +212 -15
- package/src/document/applyDocumentActions.test.ts +38 -12
- package/src/document/applyDocumentActions.ts +30 -9
- package/src/document/documentConstants.ts +7 -0
- package/src/document/documentStore.concurrency.test.ts +1306 -0
- package/src/document/documentStore.test.ts +673 -278
- package/src/document/documentStore.ts +162 -71
- package/src/document/events.test.ts +57 -2
- package/src/document/events.ts +82 -26
- package/src/document/listen.test.ts +56 -0
- package/src/document/listen.ts +74 -21
- package/src/document/listenerEventOperators.test.ts +311 -0
- package/src/document/listenerEventOperators.ts +217 -0
- package/src/document/patchOperations.test.ts +49 -2
- package/src/document/patchOperations.ts +50 -0
- package/src/document/permissions.test.ts +105 -60
- package/src/document/permissions.ts +44 -19
- package/src/document/processActions/create.ts +138 -0
- package/src/document/processActions/delete.ts +100 -0
- package/src/document/processActions/discard.ts +63 -0
- package/src/document/processActions/edit.ts +154 -0
- package/src/document/processActions/processActions.ts +218 -0
- package/src/document/processActions/publish.ts +120 -0
- 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 +308 -0
- package/src/document/processActions/unpublish.ts +85 -0
- package/src/document/processActions.test.ts +1129 -121
- package/src/document/reducers.test.ts +639 -64
- package/src/document/reducers.ts +187 -48
- package/src/document/resourceRules.test.ts +178 -0
- package/src/document/resourceRules.ts +117 -0
- package/src/document/sharedListener.test.ts +16 -14
- package/src/document/sharedListener.ts +24 -8
- package/src/document/util.ts +14 -0
- package/src/favorites/favorites.test.ts +5 -6
- package/src/installations/installations.test-d.ts +68 -0
- package/src/installations/installations.test.ts +62 -0
- package/src/installations/installations.ts +202 -0
- package/src/organization/organization.test-d.ts +36 -0
- package/src/organization/organization.test.ts +138 -0
- package/src/organization/organization.ts +138 -0
- package/src/organizations/organizations.test-d.ts +56 -0
- package/src/organizations/organizations.test.ts +150 -0
- package/src/organizations/organizations.ts +107 -0
- package/src/presence/bifurTransport.test.ts +46 -6
- package/src/presence/bifurTransport.ts +19 -2
- package/src/presence/presenceStore.test.ts +94 -23
- package/src/presence/presenceStore.ts +85 -29
- package/src/preview/getPreviewState.test.ts +137 -0
- package/src/preview/getPreviewState.ts +69 -0
- package/src/preview/previewProjectionUtils.test.ts +9 -22
- package/src/preview/previewProjectionUtils.ts +7 -3
- package/src/preview/resolvePreview.test.ts +64 -0
- package/src/preview/resolvePreview.ts +43 -0
- package/src/preview/types.ts +10 -0
- package/src/project/project.test-d.ts +37 -0
- package/src/project/project.test.ts +157 -12
- package/src/project/project.ts +138 -25
- package/src/projection/getProjectionState.test.ts +18 -20
- package/src/projection/getProjectionState.ts +23 -3
- package/src/projection/projectionQuery.ts +5 -5
- package/src/projection/projectionStore.test.ts +1 -1
- package/src/projection/resolveProjection.test.ts +1 -2
- package/src/projection/resolveProjection.ts +16 -0
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
- package/src/projection/subscribeToStateAndFetchBatches.ts +32 -23
- package/src/projection/types.ts +8 -0
- package/src/projects/projects.test-d.ts +32 -0
- package/src/projects/projects.test.ts +108 -42
- package/src/projects/projects.ts +63 -27
- package/src/query/queryStore.test.ts +259 -123
- package/src/query/queryStore.ts +78 -63
- package/src/query/reducers.test.ts +0 -42
- package/src/query/reducers.ts +2 -18
- package/src/releases/getPerspectiveState.test.ts +17 -23
- package/src/releases/getPerspectiveState.ts +8 -20
- package/src/releases/observeReleases.test.ts +127 -0
- package/src/releases/observeReleases.ts +102 -0
- package/src/releases/releasesStore.test.ts +100 -53
- package/src/releases/releasesStore.ts +69 -44
- package/src/releases/utils/sortReleases.test.ts +38 -2
- package/src/releases/utils/sortReleases.ts +15 -10
- package/src/store/createActionBinder.test.ts +87 -90
- package/src/store/createActionBinder.ts +79 -25
- package/src/store/createSanityInstance.test.ts +83 -13
- package/src/store/createSanityInstance.ts +77 -2
- package/src/store/createStateSourceAction.test.ts +64 -2
- package/src/store/createStateSourceAction.ts +39 -44
- package/src/store/createStoreInstance.test.ts +4 -2
- package/src/store/fetcherStore.test-d.ts +121 -0
- package/src/store/fetcherStore.test.ts +299 -0
- package/src/store/fetcherStore.ts +801 -0
- package/src/telemetry/environment.test.ts +119 -0
- package/src/telemetry/environment.ts +92 -0
- package/src/telemetry/events.ts +42 -0
- package/src/telemetry/initTelemetry.test.ts +432 -0
- package/src/telemetry/initTelemetry.ts +218 -0
- package/src/telemetry/telemetryManager.test.ts +327 -0
- package/src/telemetry/telemetryManager.ts +199 -0
- package/src/users/reducers.test.ts +6 -1
- package/src/users/reducers.ts +5 -6
- package/src/users/types.ts +4 -4
- package/src/users/usersStore.test.ts +16 -12
- package/src/users/usersStore.ts +5 -1
- package/src/utils/buildQuery.test.ts +14 -0
- package/src/utils/buildQuery.ts +17 -0
- package/src/utils/createFetcherStore.test.ts +7 -5
- package/src/utils/createFetcherStore.ts +8 -5
- package/src/utils/getStagingApiHost.test.ts +21 -0
- package/src/utils/getStagingApiHost.ts +14 -0
- package/src/utils/ids.test.ts +1 -29
- package/src/utils/ids.ts +0 -10
- package/src/utils/includeShape.ts +36 -0
- package/src/utils/isImportError.test.ts +72 -0
- package/src/utils/isImportError.ts +34 -0
- package/src/utils/logger.test.ts +12 -0
- package/src/utils/logger.ts +8 -3
- package/src/utils/object.test.ts +95 -0
- package/src/utils/object.ts +142 -0
- package/src/utils/setCleanupTimeout.ts +37 -0
- package/src/document/processActions.ts +0 -707
- package/src/utils/defineIntent.test.ts +0 -477
- package/src/utils/defineIntent.ts +0 -244
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {type ArchiveReleaseAction, type UnarchiveReleaseAction} from '../actions'
|
|
2
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
3
|
+
import {
|
|
4
|
+
ActionError,
|
|
5
|
+
type ActionHandlerContext,
|
|
6
|
+
type ActionHandlerResult,
|
|
7
|
+
checkGrant,
|
|
8
|
+
PermissionActionError,
|
|
9
|
+
} from './shared'
|
|
10
|
+
|
|
11
|
+
export function handleReleaseArchive(
|
|
12
|
+
action: ArchiveReleaseAction,
|
|
13
|
+
ctx: ActionHandlerContext,
|
|
14
|
+
): ActionHandlerResult {
|
|
15
|
+
const {base, working, grants, outgoingActions, transactionId, identity} = ctx
|
|
16
|
+
|
|
17
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
18
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
19
|
+
if (!existing) {
|
|
20
|
+
throw new ActionError({
|
|
21
|
+
documentId: releaseDocumentId,
|
|
22
|
+
transactionId,
|
|
23
|
+
message: `Cannot archive release "${action.releaseId}" because it does not exist.`,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
28
|
+
throw new PermissionActionError({
|
|
29
|
+
documentId: releaseDocumentId,
|
|
30
|
+
transactionId,
|
|
31
|
+
message: `You do not have permission to archive release "${action.releaseId}".`,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Archiving deletes every version document in the release server-side.
|
|
36
|
+
// Although technically we could search through the document store for all related
|
|
37
|
+
// version documents, for now it's simpler to just let the server handle it.
|
|
38
|
+
// (Those local documents will be eventually updated by the listener.)
|
|
39
|
+
outgoingActions.push({
|
|
40
|
+
actionType: 'sanity.action.release.archive',
|
|
41
|
+
releaseId: action.releaseId,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return {base, working}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function handleReleaseUnarchive(
|
|
48
|
+
action: UnarchiveReleaseAction,
|
|
49
|
+
ctx: ActionHandlerContext,
|
|
50
|
+
): ActionHandlerResult {
|
|
51
|
+
const {base, working, grants, outgoingActions, transactionId, identity} = ctx
|
|
52
|
+
|
|
53
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
54
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
55
|
+
if (!existing) {
|
|
56
|
+
throw new ActionError({
|
|
57
|
+
documentId: releaseDocumentId,
|
|
58
|
+
transactionId,
|
|
59
|
+
message: `Cannot unarchive release "${action.releaseId}" because it does not exist.`,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
64
|
+
throw new PermissionActionError({
|
|
65
|
+
documentId: releaseDocumentId,
|
|
66
|
+
transactionId,
|
|
67
|
+
message: `You do not have permission to unarchive release "${action.releaseId}".`,
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
outgoingActions.push({
|
|
72
|
+
actionType: 'sanity.action.release.unarchive',
|
|
73
|
+
releaseId: action.releaseId,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
return {base, working}
|
|
77
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {type Mutation, type SanityDocument} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
import {type CreateReleaseAction} from '../actions'
|
|
4
|
+
import {processMutations} from '../processMutations'
|
|
5
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
6
|
+
import {
|
|
7
|
+
ActionError,
|
|
8
|
+
type ActionHandlerContext,
|
|
9
|
+
type ActionHandlerResult,
|
|
10
|
+
checkGrant,
|
|
11
|
+
PermissionActionError,
|
|
12
|
+
} from './shared'
|
|
13
|
+
|
|
14
|
+
export function handleReleaseCreate(
|
|
15
|
+
action: CreateReleaseAction,
|
|
16
|
+
ctx: ActionHandlerContext,
|
|
17
|
+
): ActionHandlerResult {
|
|
18
|
+
const {transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity} = ctx
|
|
19
|
+
let {base, working} = ctx
|
|
20
|
+
|
|
21
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
22
|
+
|
|
23
|
+
if (working[releaseDocumentId] || base[releaseDocumentId]) {
|
|
24
|
+
throw new ActionError({
|
|
25
|
+
documentId: releaseDocumentId,
|
|
26
|
+
transactionId,
|
|
27
|
+
message: `A release with id "${action.releaseId}" already exists.`,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
// Optimistic local release doc
|
|
31
|
+
const releaseDoc = {
|
|
32
|
+
_id: releaseDocumentId,
|
|
33
|
+
_type: 'system.release',
|
|
34
|
+
name: action.releaseId,
|
|
35
|
+
state: 'active',
|
|
36
|
+
metadata: action.metadata,
|
|
37
|
+
}
|
|
38
|
+
const mutations: Mutation[] = [{create: releaseDoc}]
|
|
39
|
+
|
|
40
|
+
base = processMutations({documents: base, transactionId, mutations, timestamp})
|
|
41
|
+
working = processMutations({documents: working, transactionId, mutations, timestamp})
|
|
42
|
+
|
|
43
|
+
if (!checkGrant(grants.create, working[releaseDocumentId] as SanityDocument, identity)) {
|
|
44
|
+
throw new PermissionActionError({
|
|
45
|
+
documentId: releaseDocumentId,
|
|
46
|
+
transactionId,
|
|
47
|
+
message: `You do not have permission to create release "${action.releaseId}".`,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
outgoingMutations.push(...mutations)
|
|
52
|
+
outgoingActions.push({
|
|
53
|
+
actionType: 'sanity.action.release.create',
|
|
54
|
+
releaseId: action.releaseId,
|
|
55
|
+
metadata: action.metadata,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
return {base, working}
|
|
59
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {type Mutation} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
import {type DeleteReleaseAction} from '../actions'
|
|
4
|
+
import {processMutations} from '../processMutations'
|
|
5
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
6
|
+
import {
|
|
7
|
+
ActionError,
|
|
8
|
+
type ActionHandlerContext,
|
|
9
|
+
type ActionHandlerResult,
|
|
10
|
+
checkGrant,
|
|
11
|
+
PermissionActionError,
|
|
12
|
+
} from './shared'
|
|
13
|
+
|
|
14
|
+
// you can only delete archived or published releases
|
|
15
|
+
// https://www.sanity.io/docs/content-lake/dispatch-actions#k22ab37420f3c
|
|
16
|
+
const DELETABLE_STATES = new Set(['archived', 'published'])
|
|
17
|
+
|
|
18
|
+
export function handleReleaseDelete(
|
|
19
|
+
action: DeleteReleaseAction,
|
|
20
|
+
ctx: ActionHandlerContext,
|
|
21
|
+
): ActionHandlerResult {
|
|
22
|
+
const {transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity} = ctx
|
|
23
|
+
let {base, working} = ctx
|
|
24
|
+
|
|
25
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
26
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
27
|
+
|
|
28
|
+
if (!existing) {
|
|
29
|
+
throw new ActionError({
|
|
30
|
+
documentId: releaseDocumentId,
|
|
31
|
+
transactionId,
|
|
32
|
+
message: `Cannot delete release "${action.releaseId}" because it does not exist.`,
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const state = existing['state']
|
|
37
|
+
if (state && typeof state === 'string' && !DELETABLE_STATES.has(state)) {
|
|
38
|
+
throw new ActionError({
|
|
39
|
+
documentId: releaseDocumentId,
|
|
40
|
+
transactionId,
|
|
41
|
+
message: `Cannot delete release "${action.releaseId}" while it is "${state}". Archive it first.`,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
46
|
+
throw new PermissionActionError({
|
|
47
|
+
documentId: releaseDocumentId,
|
|
48
|
+
transactionId,
|
|
49
|
+
message: `You do not have permission to delete release "${action.releaseId}".`,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const mutations: Mutation[] = [{delete: {id: releaseDocumentId}}]
|
|
54
|
+
|
|
55
|
+
base = processMutations({documents: base, transactionId, mutations, timestamp})
|
|
56
|
+
working = processMutations({documents: working, transactionId, mutations, timestamp})
|
|
57
|
+
|
|
58
|
+
outgoingMutations.push(...mutations)
|
|
59
|
+
outgoingActions.push({
|
|
60
|
+
actionType: 'sanity.action.release.delete',
|
|
61
|
+
releaseId: action.releaseId,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
return {base, working}
|
|
65
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {type EditReleaseAction} from '../actions'
|
|
2
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
3
|
+
import {type ActionHandlerContext, type ActionHandlerResult, applySingleDocPatch} from './shared'
|
|
4
|
+
|
|
5
|
+
export function handleReleaseEdit(
|
|
6
|
+
action: EditReleaseAction,
|
|
7
|
+
ctx: ActionHandlerContext,
|
|
8
|
+
): ActionHandlerResult {
|
|
9
|
+
const {transactionId, timestamp, grants, outgoingActions, outgoingMutations, identity} = ctx
|
|
10
|
+
const {base, working} = ctx
|
|
11
|
+
|
|
12
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
13
|
+
|
|
14
|
+
const result = applySingleDocPatch({
|
|
15
|
+
base,
|
|
16
|
+
working,
|
|
17
|
+
documentId: releaseDocumentId,
|
|
18
|
+
patches: [action.patch],
|
|
19
|
+
transactionId,
|
|
20
|
+
timestamp,
|
|
21
|
+
grants,
|
|
22
|
+
identity,
|
|
23
|
+
notFoundMessage: `Cannot edit release "${action.releaseId}" because it does not exist.`,
|
|
24
|
+
permissionMessage: `You do not have permission to edit release "${action.releaseId}".`,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
outgoingMutations.push(...result.workingMutations)
|
|
28
|
+
outgoingActions.push(
|
|
29
|
+
...result.diffedPatches.map((patch) => ({
|
|
30
|
+
actionType: 'sanity.action.release.edit' as const,
|
|
31
|
+
releaseId: action.releaseId,
|
|
32
|
+
patch,
|
|
33
|
+
})),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return {base: result.base, working: result.working}
|
|
37
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {type PublishReleaseAction} from '../actions'
|
|
2
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
3
|
+
import {
|
|
4
|
+
ActionError,
|
|
5
|
+
type ActionHandlerContext,
|
|
6
|
+
type ActionHandlerResult,
|
|
7
|
+
checkGrant,
|
|
8
|
+
PermissionActionError,
|
|
9
|
+
} from './shared'
|
|
10
|
+
|
|
11
|
+
export function handleReleasePublish(
|
|
12
|
+
action: PublishReleaseAction,
|
|
13
|
+
ctx: ActionHandlerContext,
|
|
14
|
+
): ActionHandlerResult {
|
|
15
|
+
const {base, working, grants, outgoingActions, transactionId, identity} = ctx
|
|
16
|
+
|
|
17
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
18
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
19
|
+
if (!existing) {
|
|
20
|
+
throw new ActionError({
|
|
21
|
+
documentId: releaseDocumentId,
|
|
22
|
+
transactionId,
|
|
23
|
+
message: `Cannot publish release "${action.releaseId}" because it does not exist.`,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
28
|
+
throw new PermissionActionError({
|
|
29
|
+
documentId: releaseDocumentId,
|
|
30
|
+
transactionId,
|
|
31
|
+
message: `You do not have permission to publish release "${action.releaseId}".`,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// a release publish cascades to every version document in the release
|
|
36
|
+
// although technically we could search through the document store for all related
|
|
37
|
+
// version documents, for now it's simpler to just let the server handle it.
|
|
38
|
+
// (Those local documents will be eventually updated by the listener.)
|
|
39
|
+
outgoingActions.push({
|
|
40
|
+
actionType: 'sanity.action.release.publish',
|
|
41
|
+
releaseId: action.releaseId,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return {base, working}
|
|
45
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {type ScheduleReleaseAction, type UnscheduleReleaseAction} from '../actions'
|
|
2
|
+
import {getReleaseDocumentId} from './releaseUtil'
|
|
3
|
+
import {
|
|
4
|
+
ActionError,
|
|
5
|
+
type ActionHandlerContext,
|
|
6
|
+
type ActionHandlerResult,
|
|
7
|
+
checkGrant,
|
|
8
|
+
PermissionActionError,
|
|
9
|
+
} from './shared'
|
|
10
|
+
|
|
11
|
+
export function handleReleaseSchedule(
|
|
12
|
+
action: ScheduleReleaseAction,
|
|
13
|
+
ctx: ActionHandlerContext,
|
|
14
|
+
): ActionHandlerResult {
|
|
15
|
+
const {base, working, grants, outgoingActions, transactionId, identity} = ctx
|
|
16
|
+
|
|
17
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
18
|
+
|
|
19
|
+
if (Number.isNaN(Date.parse(action.publishAt))) {
|
|
20
|
+
throw new ActionError({
|
|
21
|
+
documentId: releaseDocumentId,
|
|
22
|
+
transactionId,
|
|
23
|
+
message: `Cannot schedule release "${action.releaseId}": "publishAt" must be a valid ISO 8601 timestamp (received "${action.publishAt}").`,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
28
|
+
if (!existing) {
|
|
29
|
+
throw new ActionError({
|
|
30
|
+
documentId: releaseDocumentId,
|
|
31
|
+
transactionId,
|
|
32
|
+
message: `Cannot schedule release "${action.releaseId}" because it does not exist.`,
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
37
|
+
throw new PermissionActionError({
|
|
38
|
+
documentId: releaseDocumentId,
|
|
39
|
+
transactionId,
|
|
40
|
+
message: `You do not have permission to schedule release "${action.releaseId}".`,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Scheduling flips `state` to 'scheduled' and locks version documents
|
|
45
|
+
// server-side. We don't model the lock locally yet — local edits to those
|
|
46
|
+
// version docs will be rejected at submit time. The listener will sync the
|
|
47
|
+
// updated release state.
|
|
48
|
+
outgoingActions.push({
|
|
49
|
+
actionType: 'sanity.action.release.schedule',
|
|
50
|
+
releaseId: action.releaseId,
|
|
51
|
+
publishAt: action.publishAt,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return {base, working}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function handleReleaseUnschedule(
|
|
58
|
+
action: UnscheduleReleaseAction,
|
|
59
|
+
ctx: ActionHandlerContext,
|
|
60
|
+
): ActionHandlerResult {
|
|
61
|
+
const {base, working, grants, outgoingActions, transactionId, identity} = ctx
|
|
62
|
+
|
|
63
|
+
const releaseDocumentId = getReleaseDocumentId(action.releaseId)
|
|
64
|
+
const existing = working[releaseDocumentId] ?? base[releaseDocumentId]
|
|
65
|
+
if (!existing) {
|
|
66
|
+
throw new ActionError({
|
|
67
|
+
documentId: releaseDocumentId,
|
|
68
|
+
transactionId,
|
|
69
|
+
message: `Cannot unschedule release "${action.releaseId}" because it does not exist.`,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!checkGrant(grants.update, existing, identity)) {
|
|
74
|
+
throw new PermissionActionError({
|
|
75
|
+
documentId: releaseDocumentId,
|
|
76
|
+
transactionId,
|
|
77
|
+
message: `You do not have permission to unschedule release "${action.releaseId}".`,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
outgoingActions.push({
|
|
82
|
+
actionType: 'sanity.action.release.unschedule',
|
|
83
|
+
releaseId: action.releaseId,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return {base, working}
|
|
87
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {type Action, type ReleaseAction} from '../actions'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Path prefix shared by every release document. Matches studio's
|
|
5
|
+
* `RELEASE_DOCUMENTS_PATH` constant.
|
|
6
|
+
*/
|
|
7
|
+
const RELEASE_DOCUMENTS_PATH = '_.releases'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns the full release document ID for the given release name.
|
|
11
|
+
* e.g. `getReleaseDocumentId('my-release') === '_.releases.my-release'`
|
|
12
|
+
* @beta
|
|
13
|
+
*/
|
|
14
|
+
export function getReleaseDocumentId(releaseId: string): string {
|
|
15
|
+
return `${RELEASE_DOCUMENTS_PATH}.${releaseId}`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const RELEASE_ACTION_TYPES = new Set([
|
|
19
|
+
'release.create',
|
|
20
|
+
'release.edit',
|
|
21
|
+
'release.publish',
|
|
22
|
+
'release.schedule',
|
|
23
|
+
'release.unschedule',
|
|
24
|
+
'release.archive',
|
|
25
|
+
'release.unarchive',
|
|
26
|
+
'release.delete',
|
|
27
|
+
])
|
|
28
|
+
|
|
29
|
+
export function isReleaseAction(action: Action): action is ReleaseAction {
|
|
30
|
+
return RELEASE_ACTION_TYPES.has(action.type)
|
|
31
|
+
}
|