@sanity/sdk 3.1.0 → 3.2.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/_exports/_internal.d.ts +52 -21
- package/dist/_exports/_internal.d.ts.map +1 -1
- package/dist/_exports/_internal.js +10 -9
- package/dist/_exports/_internal.js.map +1 -1
- package/dist/_exports/agent.d.ts +7 -7
- package/dist/_exports/agent.d.ts.map +1 -1
- package/dist/_exports/agent.js +1 -1
- package/dist/_exports/comlink.d.ts +9 -9
- package/dist/_exports/comlink.d.ts.map +1 -1
- package/dist/_exports/comlink.js +3 -2
- package/dist/_exports/comlink.js.map +1 -1
- package/dist/_exports/dashboard.d.ts +2 -0
- package/dist/_exports/dashboard.js +2 -0
- package/dist/{authStore-C-OEkGaM.d.ts → authStore-BO2vch3I.d.ts} +516 -63
- package/dist/authStore-BO2vch3I.d.ts.map +1 -0
- package/dist/{clientStore-gUALQ0qW.js → clientStore-BI4D8HhJ.js} +124 -7
- package/dist/clientStore-BI4D8HhJ.js.map +1 -0
- package/dist/{createSanityInstance-DCePpBYW.d.ts → createSanityInstance-BQIqyGLX.d.ts} +16 -1
- package/dist/createSanityInstance-BQIqyGLX.d.ts.map +1 -0
- package/dist/{object-BwynGPRZ.js → createStateSourceAction-DdAhEfnZ.js} +2 -82
- package/dist/createStateSourceAction-DdAhEfnZ.js.map +1 -0
- package/dist/defineProperty-Bho9Ngsi.js +31 -0
- package/dist/{getNodeState-E0hjqFOo.js → getNodeState-B4nG0sjm.js} +3 -2
- package/dist/{getNodeState-E0hjqFOo.js.map → getNodeState-B4nG0sjm.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +335 -51
- package/dist/index.js.map +1 -1
- package/dist/object-CxXlSVg7.js +83 -0
- package/dist/object-CxXlSVg7.js.map +1 -0
- package/dist/topicStore-Ct7IFNtY.js +565 -0
- package/dist/topicStore-Ct7IFNtY.js.map +1 -0
- package/dist/topicStore-D0WqhQGF.d.ts +435 -0
- package/dist/topicStore-D0WqhQGF.d.ts.map +1 -0
- package/dist/{version-C90rNWaX.js → version-BcRmCiYi.js} +6 -6
- package/dist/{version-C90rNWaX.js.map → version-BcRmCiYi.js.map} +1 -1
- package/package.json +19 -18
- package/src/_exports/_internal.ts +12 -0
- package/src/_exports/dashboard.ts +36 -0
- package/src/_exports/index.ts +17 -1
- package/src/applications/applications.test-d.ts +28 -4
- package/src/applications/applications.ts +39 -14
- package/src/auth/authMode.test.ts +24 -0
- package/src/auth/authMode.ts +8 -3
- package/src/auth/authStore.ts +12 -0
- package/src/auth/authStrategy.ts +2 -0
- package/src/auth/logout.test.ts +45 -0
- package/src/auth/logout.ts +1 -0
- package/src/auth/oauth/oauthActions.test.ts +457 -0
- package/src/auth/oauth/oauthActions.ts +389 -0
- package/src/auth/oauth/oauthAuth.test.ts +206 -0
- package/src/auth/oauth/oauthAuth.ts +168 -0
- package/src/auth/oauth/pkce.test.ts +44 -0
- package/src/auth/oauth/pkce.ts +60 -0
- package/src/auth/oauth/types.ts +12 -0
- package/src/config/authConfig.ts +18 -0
- package/src/dashboard/messageBus/__fixtures__/test-topics.ts +18 -0
- package/src/dashboard/messageBus/bus.test.ts +1033 -0
- package/src/dashboard/messageBus/bus.ts +1246 -0
- package/src/dashboard/messageBus/store.test.ts +142 -0
- package/src/dashboard/messageBus/store.ts +74 -0
- package/src/dashboard/messageBus/topicStore.test.ts +172 -0
- package/src/dashboard/messageBus/topicStore.ts +184 -0
- package/src/dashboard/messageBus/topics.test.ts +71 -0
- package/src/dashboard/messageBus/topics.ts +260 -0
- package/src/document/actions.ts +3 -3
- package/src/document/applyDocumentActions.ts +3 -3
- package/src/document/documentStore.ts +12 -12
- package/src/document/processMutations.ts +58 -22
- package/src/installations/installations.test-d.ts +3 -3
- package/src/installations/installations.ts +2 -19
- package/src/projection/getProjectionState.ts +2 -2
- package/src/projection/resolveProjection.ts +2 -2
- package/src/query/queryStore.ts +3 -3
- package/src/typegen/defineProjection.test.ts +17 -0
- package/src/typegen/defineProjection.ts +19 -0
- package/src/typegen/groqCompat.ts +122 -0
- package/src/typegen/resolve.ts +37 -0
- package/src/utils/createGroqSearchFilter.test.ts +8 -0
- package/src/utils/createGroqSearchFilter.ts +6 -3
- package/dist/authStore-C-OEkGaM.d.ts.map +0 -1
- package/dist/clientStore-gUALQ0qW.js.map +0 -1
- package/dist/createSanityInstance-DCePpBYW.d.ts.map +0 -1
- package/dist/object-BwynGPRZ.js.map +0 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import {type CurrentUser} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
import {type Application, type ApplicationInclude} from '../../applications/applications'
|
|
4
|
+
import {type OrganizationBase} from '../../organization/organization'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Identifies a module federation expose and the manifest that serves it.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export interface RemoteModuleRef {
|
|
11
|
+
readonly entry: string
|
|
12
|
+
readonly moduleId: string
|
|
13
|
+
readonly version: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Application types that can receive configuration modules.
|
|
18
|
+
*
|
|
19
|
+
* The dashboard supplies this value over the message bus, so any string is accepted; known
|
|
20
|
+
* types are listed for autocomplete. `& {}` keeps the literal from collapsing into `string`.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export type ApplicationConfigAppType = 'media-library' | (string & {})
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Identifies a configuration module for an application or application type.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export interface ApplicationConfig extends RemoteModuleRef {
|
|
30
|
+
readonly appId?: Application['id']
|
|
31
|
+
readonly appType: ApplicationConfigAppType
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Declares a topic that stores and replays its current value.
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export type StateTopicDef<T> = {kind: 'state'; value: T}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Declares a topic that delivers events and an optional reply.
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export type EventTopicDef<P, R = never> = {
|
|
45
|
+
kind: 'event'
|
|
46
|
+
payload: P
|
|
47
|
+
reply?: R
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Represents a successful topic value or a failed topic operation.
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export type TopicResult<T> = {ok: true; value: T} | {ok: false}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Identifies a dashboard application and a route within it.
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export type NavigationTarget = {
|
|
61
|
+
/** The application ID, or `null` for dashboard-level routes. */
|
|
62
|
+
appId: Application['id'] | null
|
|
63
|
+
/** The route path, including its query string and fragment. */
|
|
64
|
+
path: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Describes the current dashboard location and an active navigation.
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
71
|
+
export type NavigationLocation = NavigationTarget & {
|
|
72
|
+
/** The active navigation, or `null` when navigation is idle. */
|
|
73
|
+
transition: {
|
|
74
|
+
/** Whether the navigation pushes or replaces browser history. */
|
|
75
|
+
navigationType: 'push' | 'replace'
|
|
76
|
+
/** The requested destination. */
|
|
77
|
+
to: NavigationTarget
|
|
78
|
+
} | null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Declares the topics provided by the dashboard.
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
85
|
+
export interface DashboardTopics {
|
|
86
|
+
/** The available application configuration modules. */
|
|
87
|
+
'applications.config': StateTopicDef<ApplicationConfig[] | null>
|
|
88
|
+
/** The foreground application ID, or `null` on dashboard-level routes. */
|
|
89
|
+
'applications.foreground': StateTopicDef<Application['id'] | null>
|
|
90
|
+
/** The dashboard applications available to the current user. */
|
|
91
|
+
'applications.list': StateTopicDef<TopicResult<Application<ApplicationInclude>[]> | null>
|
|
92
|
+
/**
|
|
93
|
+
* The session token for the reading connection, or `null` while signed out. The host
|
|
94
|
+
* writes it to each connection separately, so one application never sees another's token.
|
|
95
|
+
*/
|
|
96
|
+
'auth.token': StateTopicDef<string | null>
|
|
97
|
+
/** Requests a dashboard session token. */
|
|
98
|
+
'auth.token.refresh': EventTopicDef<void, string>
|
|
99
|
+
/** The current dashboard location and active navigation. */
|
|
100
|
+
'navigation.location': StateTopicDef<NavigationLocation | null>
|
|
101
|
+
/**
|
|
102
|
+
* Requests navigation and replies when the location commits.
|
|
103
|
+
*
|
|
104
|
+
* `ok: false` reasons:
|
|
105
|
+
* - `not-navigable`: the URL cannot be handled by a dashboard application
|
|
106
|
+
* - `interrupted`: another navigation superseded the request
|
|
107
|
+
* - `failed`: the router rejected or did not commit the request
|
|
108
|
+
*/
|
|
109
|
+
'navigation.location.update': EventTopicDef<
|
|
110
|
+
{
|
|
111
|
+
url: string
|
|
112
|
+
history?: 'push' | 'replace'
|
|
113
|
+
},
|
|
114
|
+
{ok: true} | {ok: false; reason: 'not-navigable' | 'interrupted' | 'failed'}
|
|
115
|
+
>
|
|
116
|
+
/** The current organization, or `null` without an active organization. */
|
|
117
|
+
'organizations.current': StateTopicDef<Pick<OrganizationBase, 'id' | 'name' | 'slug'> | null>
|
|
118
|
+
/** The open panel, its application, display mode, and optional width in pixels. */
|
|
119
|
+
'panels.mode': StateTopicDef<TopicResult<
|
|
120
|
+
| {appId: string; name: string; mode: 'aside'; size?: number}
|
|
121
|
+
| {appId: string; name: string; mode: 'full'}
|
|
122
|
+
| null
|
|
123
|
+
> | null>
|
|
124
|
+
/** Opens, updates, resizes, or closes an application's panel. */
|
|
125
|
+
'panels.mode.set': EventTopicDef<
|
|
126
|
+
{name: string; mode: 'aside' | 'full'} | {name: string; size: number} | null
|
|
127
|
+
>
|
|
128
|
+
/** The resolved dashboard color scheme. */
|
|
129
|
+
'preferences.color-scheme': StateTopicDef<'light' | 'dark'>
|
|
130
|
+
/** Whether the dashboard dock is pinned open. */
|
|
131
|
+
'preferences.dock-locked': StateTopicDef<boolean>
|
|
132
|
+
/** The signed-in user, or `null` while signed out. */
|
|
133
|
+
'users.current': StateTopicDef<Pick<CurrentUser, 'id' | 'name' | 'email' | 'profileImage'> | null>
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Declares every topic available through the message bus.
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- Declaration merging extends the SDK manifest.
|
|
141
|
+
export interface Topics extends DashboardTopics {}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Every declared topic name.
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
export type TopicName = keyof Topics
|
|
148
|
+
|
|
149
|
+
type StateTopicsOf<T> = {
|
|
150
|
+
[K in keyof T]: T[K] extends {kind: 'state'} ? K : never
|
|
151
|
+
}[keyof T]
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Names of all declared state topics.
|
|
155
|
+
* @public
|
|
156
|
+
*/
|
|
157
|
+
export type StateTopic = StateTopicsOf<Topics>
|
|
158
|
+
|
|
159
|
+
type TopicOwnership = {readonly type: 'same_app'} | {readonly type: 'any_app'}
|
|
160
|
+
|
|
161
|
+
// State is only ever written by the host, one connection at a time, so it carries no ownership.
|
|
162
|
+
type TopicManifestEntry<T> = T extends {kind: 'state'; value: infer V}
|
|
163
|
+
? {readonly kind: 'state'; readonly seed: V | undefined}
|
|
164
|
+
: {readonly kind: 'event'; readonly ownership: TopicOwnership}
|
|
165
|
+
|
|
166
|
+
// The value a connection's copy of the topic starts with; `undefined` means unpublished.
|
|
167
|
+
const stateTopic = <const V>(seed: V) => ({kind: 'state', seed}) as const
|
|
168
|
+
|
|
169
|
+
// `same_app` restricts responding to the application that installed the bus.
|
|
170
|
+
const dashboardEvent = {kind: 'event', ownership: {type: 'same_app'}} as const
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Defines the runtime kind, ownership, and initial value of dashboard topics.
|
|
174
|
+
* @internal
|
|
175
|
+
*/
|
|
176
|
+
export const DASHBOARD_TOPIC_MANIFEST: {
|
|
177
|
+
readonly [K in keyof DashboardTopics]: TopicManifestEntry<DashboardTopics[K]>
|
|
178
|
+
} = {
|
|
179
|
+
'applications.config': stateTopic(undefined),
|
|
180
|
+
'applications.foreground': stateTopic(undefined),
|
|
181
|
+
'applications.list': stateTopic(undefined),
|
|
182
|
+
'auth.token': stateTopic(undefined),
|
|
183
|
+
'auth.token.refresh': dashboardEvent,
|
|
184
|
+
'navigation.location': stateTopic(undefined),
|
|
185
|
+
'navigation.location.update': dashboardEvent,
|
|
186
|
+
'organizations.current': stateTopic(undefined),
|
|
187
|
+
'panels.mode': stateTopic({ok: true, value: null}),
|
|
188
|
+
'panels.mode.set': dashboardEvent,
|
|
189
|
+
'preferences.color-scheme': stateTopic(undefined),
|
|
190
|
+
'preferences.dock-locked': stateTopic(undefined),
|
|
191
|
+
'users.current': stateTopic(undefined),
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Defines the runtime manifest accepted from any message bus version.
|
|
196
|
+
* @internal
|
|
197
|
+
*/
|
|
198
|
+
export type TopicManifest = Readonly<
|
|
199
|
+
Record<
|
|
200
|
+
string,
|
|
201
|
+
| {readonly kind: 'state'; readonly seed: unknown}
|
|
202
|
+
| {readonly kind: 'event'; readonly ownership: TopicOwnership}
|
|
203
|
+
>
|
|
204
|
+
>
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Names of all declared event topics.
|
|
208
|
+
* @public
|
|
209
|
+
*/
|
|
210
|
+
export type EventTopic = {
|
|
211
|
+
[K in TopicName]: Topics[K] extends {kind: 'event'} ? K : never
|
|
212
|
+
}[TopicName]
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The value type of a state topic.
|
|
216
|
+
* @public
|
|
217
|
+
*/
|
|
218
|
+
export type ValueOf<K extends StateTopic> = Topics[K] extends StateTopicDef<infer T> ? T : never
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The payload type of an event topic.
|
|
222
|
+
* @public
|
|
223
|
+
*/
|
|
224
|
+
export type PayloadOf<K extends EventTopic> =
|
|
225
|
+
Topics[K] extends EventTopicDef<infer P, infer _R> ? P : never
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The reply type of an event topic (`never` if it declares none).
|
|
229
|
+
* @public
|
|
230
|
+
*/
|
|
231
|
+
export type ReplyOf<K extends EventTopic> =
|
|
232
|
+
Topics[K] extends EventTopicDef<infer _P, infer R> ? R : never
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Converts a topic value between 2 adjacent versions.
|
|
236
|
+
* @internal
|
|
237
|
+
*/
|
|
238
|
+
export interface TopicMigration {
|
|
239
|
+
/** The older version. */
|
|
240
|
+
readonly from: number
|
|
241
|
+
/** The newer version. */
|
|
242
|
+
readonly to: number
|
|
243
|
+
/** Converts an older state value or event payload to the newer version. */
|
|
244
|
+
up(older: unknown): unknown
|
|
245
|
+
/** Converts a newer state value or event payload to the older version. */
|
|
246
|
+
down(newer: unknown): unknown
|
|
247
|
+
/** Converts event replies between these versions. */
|
|
248
|
+
readonly reply?: {
|
|
249
|
+
/** Converts an older reply to the newer version. */
|
|
250
|
+
up(older: unknown): unknown
|
|
251
|
+
/** Converts a newer reply to the older version. */
|
|
252
|
+
down(newer: unknown): unknown
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Defines the bundled migration chain for each topic.
|
|
258
|
+
* @internal
|
|
259
|
+
*/
|
|
260
|
+
export const topicMigrations: Partial<Record<TopicName, readonly TopicMigration[]>> = {}
|
package/src/document/actions.ts
CHANGED
|
@@ -2,13 +2,13 @@ import {type ReleaseDocument} from '@sanity/client'
|
|
|
2
2
|
import {SanityEncoder} from '@sanity/mutate'
|
|
3
3
|
import {type PatchMutation as SanityMutatePatchMutation} from '@sanity/mutate/_unstable_store'
|
|
4
4
|
import {type PatchMutation, type PatchOperations} from '@sanity/types'
|
|
5
|
-
import {type SanityDocument} from 'groq'
|
|
6
5
|
|
|
7
6
|
import {
|
|
8
7
|
type DocumentHandle,
|
|
9
8
|
type DocumentTypeHandle,
|
|
10
9
|
type ReleaseHandle,
|
|
11
10
|
} from '../config/sanityConfig'
|
|
11
|
+
import {type ResolveDocument} from '../typegen/resolve'
|
|
12
12
|
import {getEffectiveDocumentId} from './util'
|
|
13
13
|
|
|
14
14
|
const isSanityMutatePatch = (value: unknown): value is SanityMutatePatchMutation => {
|
|
@@ -37,7 +37,7 @@ export interface CreateDocumentAction<
|
|
|
37
37
|
*/
|
|
38
38
|
initialValue?: Partial<
|
|
39
39
|
Omit<
|
|
40
|
-
|
|
40
|
+
ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`>,
|
|
41
41
|
'_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'
|
|
42
42
|
>
|
|
43
43
|
>
|
|
@@ -166,7 +166,7 @@ export function createDocument<
|
|
|
166
166
|
doc: DocumentTypeHandle<TDocumentType, TDataset, TProjectId>,
|
|
167
167
|
initialValue?: Partial<
|
|
168
168
|
Omit<
|
|
169
|
-
|
|
169
|
+
ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`>,
|
|
170
170
|
'_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'
|
|
171
171
|
>
|
|
172
172
|
>,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {type SanityDocument} from 'groq'
|
|
2
1
|
import {distinctUntilChanged, filter, first, firstValueFrom, map, race} from 'rxjs'
|
|
3
2
|
|
|
4
3
|
import {type DocumentResource} from '../config/sanityConfig'
|
|
5
4
|
import {bindActionByResource} from '../store/createActionBinder'
|
|
6
5
|
import {type SanityInstance} from '../store/createSanityInstance'
|
|
7
6
|
import {type StoreContext} from '../store/defineStore'
|
|
7
|
+
import {type ResolveDocument} from '../typegen/resolve'
|
|
8
8
|
import {randomUuid} from '../utils/ids'
|
|
9
9
|
import {type Action} from './actions'
|
|
10
10
|
import {documentStore, type DocumentStoreState} from './documentStore'
|
|
@@ -14,7 +14,7 @@ import {type AppliedTransaction, type QueuedTransaction, queueTransaction} from
|
|
|
14
14
|
import {normalizeActionsForResource} from './resourceRules'
|
|
15
15
|
|
|
16
16
|
/** @beta */
|
|
17
|
-
export interface ActionsResult<TDocument extends
|
|
17
|
+
export interface ActionsResult<TDocument extends ResolveDocument = ResolveDocument> {
|
|
18
18
|
transactionId: string
|
|
19
19
|
documents: DocumentSet<TDocument>
|
|
20
20
|
previous: DocumentSet<TDocument>
|
|
@@ -56,7 +56,7 @@ export function applyDocumentActions<
|
|
|
56
56
|
>(
|
|
57
57
|
instance: SanityInstance,
|
|
58
58
|
options: ApplyDocumentActionsOptions,
|
|
59
|
-
): Promise<ActionsResult<
|
|
59
|
+
): Promise<ActionsResult<ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`>>>
|
|
60
60
|
/** @beta */
|
|
61
61
|
export function applyDocumentActions(
|
|
62
62
|
instance: SanityInstance,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {type Action, ClientError, CorsOriginError, type Mutation} from '@sanity/client'
|
|
2
2
|
import {DocumentId, getDraftId, getPublishedId, getVersionId} from '@sanity/id-utils'
|
|
3
3
|
import {jsonMatch} from '@sanity/json-match'
|
|
4
|
-
import {type SanityDocument} from 'groq'
|
|
5
4
|
import {type ExprNode} from 'groq-js'
|
|
6
5
|
import {
|
|
7
6
|
catchError,
|
|
@@ -46,6 +45,7 @@ import {
|
|
|
46
45
|
import {type SanityInstance} from '../store/createSanityInstance'
|
|
47
46
|
import {createStateSourceAction, type StateSource} from '../store/createStateSourceAction'
|
|
48
47
|
import {defineStore, type StoreContext} from '../store/defineStore'
|
|
48
|
+
import {type ResolveDocument} from '../typegen/resolve'
|
|
49
49
|
import {type DocumentAction} from './actions'
|
|
50
50
|
import {
|
|
51
51
|
ACL_RETRY_BASE_DELAY,
|
|
@@ -98,7 +98,7 @@ export interface DocumentStoreState {
|
|
|
98
98
|
identity?: string
|
|
99
99
|
error?: unknown
|
|
100
100
|
sharedListener: SharedListener
|
|
101
|
-
fetchDocument: (documentId: string) => Observable<
|
|
101
|
+
fetchDocument: (documentId: string) => Observable<ResolveDocument | null>
|
|
102
102
|
events: Subject<DocumentEvent>
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -108,12 +108,12 @@ export interface DocumentState {
|
|
|
108
108
|
* the "remote" local copy that matches the server. represents the last known
|
|
109
109
|
* server state. this gets updated every time we confirm remote patches
|
|
110
110
|
*/
|
|
111
|
-
remote?:
|
|
111
|
+
remote?: ResolveDocument | null
|
|
112
112
|
/**
|
|
113
113
|
* the current ephemeral working copy that includes local optimistic changes
|
|
114
114
|
* that have not yet been confirmed by the server
|
|
115
115
|
*/
|
|
116
|
-
local?:
|
|
116
|
+
local?: ResolveDocument | null
|
|
117
117
|
/**
|
|
118
118
|
* the revision that our remote document is at
|
|
119
119
|
*/
|
|
@@ -194,7 +194,7 @@ export function getDocumentState<
|
|
|
194
194
|
>(
|
|
195
195
|
instance: SanityInstance,
|
|
196
196
|
options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>,
|
|
197
|
-
): StateSource<
|
|
197
|
+
): StateSource<ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`> | undefined | null>
|
|
198
198
|
|
|
199
199
|
/** @beta */
|
|
200
200
|
export function getDocumentState<
|
|
@@ -206,7 +206,7 @@ export function getDocumentState<
|
|
|
206
206
|
instance: SanityInstance,
|
|
207
207
|
options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
|
|
208
208
|
): StateSource<
|
|
209
|
-
JsonMatch<
|
|
209
|
+
JsonMatch<ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`>, TPath> | undefined
|
|
210
210
|
>
|
|
211
211
|
|
|
212
212
|
/** @beta */
|
|
@@ -229,12 +229,12 @@ const _getDocumentState = bindActionByResource(
|
|
|
229
229
|
const {documentId: docId, path, liveEdit, perspective} = options
|
|
230
230
|
const documentId = DocumentId(docId)
|
|
231
231
|
if (error) throw error
|
|
232
|
-
let document:
|
|
232
|
+
let document: ResolveDocument | null | undefined
|
|
233
233
|
|
|
234
234
|
if (liveEdit) {
|
|
235
235
|
document = documentStates[documentId]?.local
|
|
236
236
|
} else {
|
|
237
|
-
let version:
|
|
237
|
+
let version: ResolveDocument | null | undefined
|
|
238
238
|
if (isReleasePerspective(perspective)) {
|
|
239
239
|
const versionId = getVersionId(documentId, perspective.releaseName)
|
|
240
240
|
version = documentStates[versionId]?.local
|
|
@@ -267,16 +267,16 @@ export function resolveDocument<
|
|
|
267
267
|
>(
|
|
268
268
|
instance: SanityInstance,
|
|
269
269
|
docHandle: DocumentHandle<TDocumentType, TDataset, TProjectId>,
|
|
270
|
-
): Promise<
|
|
270
|
+
): Promise<ResolveDocument<TDocumentType, `${TProjectId}.${TDataset}`> | null>
|
|
271
271
|
/** @beta */
|
|
272
|
-
export function resolveDocument<TData extends
|
|
272
|
+
export function resolveDocument<TData extends ResolveDocument>(
|
|
273
273
|
instance: SanityInstance,
|
|
274
274
|
docHandle: DocumentHandle<string, string, string>,
|
|
275
275
|
): Promise<TData | null>
|
|
276
276
|
/** @beta */
|
|
277
277
|
export function resolveDocument(
|
|
278
278
|
...args: Parameters<typeof _resolveDocument>
|
|
279
|
-
): Promise<
|
|
279
|
+
): Promise<ResolveDocument | null> {
|
|
280
280
|
return _resolveDocument(...args)
|
|
281
281
|
}
|
|
282
282
|
const _resolveDocument = bindActionByResource(
|
|
@@ -287,7 +287,7 @@ const _resolveDocument = bindActionByResource(
|
|
|
287
287
|
...docHandle,
|
|
288
288
|
path: undefined,
|
|
289
289
|
}).observable.pipe(filter((i) => i !== undefined)),
|
|
290
|
-
) as Promise<
|
|
290
|
+
) as Promise<ResolveDocument | null>
|
|
291
291
|
},
|
|
292
292
|
)
|
|
293
293
|
|
|
@@ -18,10 +18,9 @@ import {
|
|
|
18
18
|
} from './patchOperations'
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* Documents that don't exist have a `null` value.
|
|
21
|
+
* Maps document IDs to documents, using `null` for documents that do not exist.
|
|
22
|
+
*
|
|
23
|
+
* @beta
|
|
25
24
|
*/
|
|
26
25
|
export type DocumentSet<TDocument extends SanityDocument = SanityDocument> = {
|
|
27
26
|
[TDocumentId in string]?: TDocument | null
|
|
@@ -29,10 +28,29 @@ export type DocumentSet<TDocument extends SanityDocument = SanityDocument> = {
|
|
|
29
28
|
|
|
30
29
|
type SupportedPatchOperation = Exclude<keyof PatchOperations, 'merge'>
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Exposes the patch operations used by {@link processMutations}.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* Property order determines execution order in {@link processMutations}:
|
|
36
|
+
* `ifRevisionID`, `set`, `setIfMissing`, `unset`, `inc`, `dec`, `insert`,
|
|
37
|
+
* then `diffMatchPatch`. Reordering the properties changes mutation results.
|
|
38
|
+
* Freezes the collection to prevent callers from replacing the functions
|
|
39
|
+
* used by the SDK's mutation evaluator.
|
|
40
|
+
*
|
|
41
|
+
* @see https://www.sanity.io/docs/http-mutations#5b4db1396e56
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const document = {items: [{_key: 'a', title: 'Before'}]}
|
|
46
|
+
* const updated = patchOperations.set<typeof document>(document, {
|
|
47
|
+
* 'items[_key=="a"].title': 'After',
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export const patchOperations = Object.freeze({
|
|
36
54
|
ifRevisionID,
|
|
37
55
|
set,
|
|
38
56
|
setIfMissing,
|
|
@@ -46,7 +64,7 @@ const patchOperations = {
|
|
|
46
64
|
input: unknown,
|
|
47
65
|
pathExpressions: NonNullable<PatchOperations[K]>,
|
|
48
66
|
) => unknown
|
|
49
|
-
}
|
|
67
|
+
})
|
|
50
68
|
|
|
51
69
|
/**
|
|
52
70
|
* Implements ID generation:
|
|
@@ -69,7 +87,12 @@ export function getId(id?: string): string {
|
|
|
69
87
|
return id
|
|
70
88
|
}
|
|
71
89
|
|
|
72
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Configures {@link processMutations}.
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
export interface ProcessMutationsOptions {
|
|
73
96
|
/**
|
|
74
97
|
* The transaction ID that will become the next `_rev` for documents mutated
|
|
75
98
|
* by the given mutations.
|
|
@@ -84,8 +107,8 @@ interface ProcessMutationsOptions {
|
|
|
84
107
|
*/
|
|
85
108
|
mutations: Mutation[]
|
|
86
109
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
110
|
+
* Supplies the default `_createdAt` and `_updatedAt` timestamps.
|
|
111
|
+
* Uses the current time when omitted or empty.
|
|
89
112
|
*/
|
|
90
113
|
timestamp?: string
|
|
91
114
|
}
|
|
@@ -108,18 +131,31 @@ export function getDocumentIds(selection: MutationSelection): string[] {
|
|
|
108
131
|
}
|
|
109
132
|
|
|
110
133
|
/**
|
|
111
|
-
* Applies
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
134
|
+
* Applies mutations to an in-memory set of Sanity documents.
|
|
135
|
+
* Deleted documents remain in the returned set with a value of `null`.
|
|
136
|
+
*
|
|
137
|
+
* Include every document affected by `mutations` in `documents`, using `null`
|
|
138
|
+
* for documents that do not exist.
|
|
139
|
+
*
|
|
140
|
+
* Returns `documents` itself when `mutations` is empty. Otherwise, returns a
|
|
141
|
+
* shallow copy of that object. The result can reuse document objects and
|
|
142
|
+
* nested objects from `documents`. Mutating a reused object through the
|
|
143
|
+
* result also changes the input.
|
|
144
|
+
*
|
|
145
|
+
* Sets `_rev` to `transactionId` on created, replaced, and patched documents.
|
|
146
|
+
* Uses `timestamp` for timestamps unless the mutation preserves them.
|
|
147
|
+
* Ignores `merge` patches; `inc` and `dec` skip values that are not numbers.
|
|
148
|
+
* Generates document IDs when omitted or ending in `.`.
|
|
149
|
+
* Patch operations can generate missing array keys.
|
|
150
|
+
*
|
|
151
|
+
* Does not persist documents or run Content Lake's server validation.
|
|
117
152
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
153
|
+
* @throws If a selection uses a query, a `create` targets an existing document,
|
|
154
|
+
* or a `patch` targets a document that does not exist.
|
|
155
|
+
* @throws If a patch operation fails, including a revision check failure or
|
|
156
|
+
* `diffMatchPatch` applied to a value other than a string or `undefined`.
|
|
120
157
|
*
|
|
121
|
-
*
|
|
122
|
-
* and `_createdAt` timestamps.
|
|
158
|
+
* @internal
|
|
123
159
|
*/
|
|
124
160
|
export function processMutations({
|
|
125
161
|
documents,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {expectTypeOf, test} from 'vitest'
|
|
2
2
|
|
|
3
|
+
import {type ApplicationInterface} from '../applications/applications'
|
|
3
4
|
import {type SanityInstance} from '../store/createSanityInstance'
|
|
4
5
|
import {type StateSource} from '../store/createStateSourceAction'
|
|
5
6
|
import {type FetcherSnapshot} from '../store/fetcherStore'
|
|
@@ -10,7 +11,6 @@ import {
|
|
|
10
11
|
type InstallationActiveConfig,
|
|
11
12
|
type InstallationBase,
|
|
12
13
|
type InstallationInclude,
|
|
13
|
-
type InstallationInterface,
|
|
14
14
|
installations,
|
|
15
15
|
type InstallationsResponse,
|
|
16
16
|
} from './installations'
|
|
@@ -40,7 +40,7 @@ test('Installation — each token adds its top-level field, required, others abs
|
|
|
40
40
|
Extract<keyof Installation<'access'>, 'activeConfig' | 'interfaces'>
|
|
41
41
|
>().toEqualTypeOf<never>()
|
|
42
42
|
|
|
43
|
-
expectTypeOf<Installation<'interfaces'>['interfaces']>().toEqualTypeOf<
|
|
43
|
+
expectTypeOf<Installation<'interfaces'>['interfaces']>().toEqualTypeOf<ApplicationInterface[]>()
|
|
44
44
|
expectTypeOf<
|
|
45
45
|
Installation<'activeConfig'>['activeConfig']
|
|
46
46
|
>().toEqualTypeOf<InstallationActiveConfig | null>()
|
|
@@ -49,7 +49,7 @@ test('Installation — each token adds its top-level field, required, others abs
|
|
|
49
49
|
test('Installation — multiple tokens add each field', () => {
|
|
50
50
|
type Both = Installation<'access' | 'interfaces'>
|
|
51
51
|
expectTypeOf<Both['access']>().toEqualTypeOf<InstallationAccess[]>()
|
|
52
|
-
expectTypeOf<Both['interfaces']>().toEqualTypeOf<
|
|
52
|
+
expectTypeOf<Both['interfaces']>().toEqualTypeOf<ApplicationInterface[]>()
|
|
53
53
|
expectTypeOf<Extract<keyof Both, 'activeConfig'>>().toEqualTypeOf<never>()
|
|
54
54
|
})
|
|
55
55
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {switchMap} from 'rxjs'
|
|
2
2
|
|
|
3
|
+
import {type ApplicationInterface} from '../applications/applications'
|
|
3
4
|
import {getClientState} from '../client/clientStore'
|
|
4
5
|
import {defineFetcher} from '../store/fetcherStore'
|
|
5
6
|
import {buildQuery} from '../utils/buildQuery'
|
|
@@ -29,24 +30,6 @@ export interface InstallationAccess {
|
|
|
29
30
|
resourceId: string
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* An interface exposed by an installation, embedded when `interfaces` is
|
|
34
|
-
* included.
|
|
35
|
-
*
|
|
36
|
-
* @see https://www.sanity.io/docs/http-reference/applications-api
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
39
|
-
export interface InstallationInterface {
|
|
40
|
-
id: string
|
|
41
|
-
type: 'app' | 'worker' | 'asset_source' | 'panel'
|
|
42
|
-
name: string
|
|
43
|
-
title: string
|
|
44
|
-
version: string
|
|
45
|
-
/** Module federation module ID; resolved from the host mf-manifest at runtime */
|
|
46
|
-
moduleId: string
|
|
47
|
-
metadata: {group?: string; priority?: number} | null
|
|
48
|
-
}
|
|
49
|
-
|
|
50
33
|
/**
|
|
51
34
|
* The active config of an installation, embedded when `activeConfig` is
|
|
52
35
|
* included. `null` when nothing is deployed.
|
|
@@ -104,7 +87,7 @@ export type Installation<Include extends InstallationInclude = never> = Installa
|
|
|
104
87
|
{activeConfig: InstallationActiveConfig | null}
|
|
105
88
|
> &
|
|
106
89
|
Included<InstallationInclude, 'access', Include, {access: InstallationAccess[]}> &
|
|
107
|
-
Included<InstallationInclude, 'interfaces', Include, {interfaces:
|
|
90
|
+
Included<InstallationInclude, 'interfaces', Include, {interfaces: ApplicationInterface[]}>
|
|
108
91
|
|
|
109
92
|
/**
|
|
110
93
|
* Options for listing an organization's installations.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {DocumentId, getPublishedId} from '@sanity/id-utils'
|
|
2
|
-
import {type SanityProjectionResult} from 'groq'
|
|
3
2
|
|
|
4
3
|
import {type DocumentHandle} from '../config/sanityConfig'
|
|
5
4
|
import {bindActionByResourceAndPerspective} from '../store/createActionBinder'
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
type SelectorContext,
|
|
10
9
|
type StateSource,
|
|
11
10
|
} from '../store/createStateSourceAction'
|
|
11
|
+
import {type ResolveProjectionResult} from '../typegen/resolve'
|
|
12
12
|
import {hashString} from '../utils/hashString'
|
|
13
13
|
import {randomId} from '../utils/ids'
|
|
14
14
|
import {omitProperty} from '../utils/object'
|
|
@@ -39,7 +39,7 @@ export function getProjectionState<
|
|
|
39
39
|
options: ProjectionOptions<TProjection, TDocumentType, TDataset, TProjectId>,
|
|
40
40
|
): StateSource<
|
|
41
41
|
| ProjectionValuePending<
|
|
42
|
-
|
|
42
|
+
ResolveProjectionResult<TProjection, TDocumentType, `${TProjectId}.${TDataset}`>
|
|
43
43
|
>
|
|
44
44
|
| undefined
|
|
45
45
|
>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {type SanityProjectionResult} from 'groq'
|
|
2
1
|
import {filter, firstValueFrom} from 'rxjs'
|
|
3
2
|
|
|
4
3
|
import {bindActionByResourceAndPerspective} from '../store/createActionBinder'
|
|
5
4
|
import {type SanityInstance} from '../store/createSanityInstance'
|
|
5
|
+
import {type ResolveProjectionResult} from '../typegen/resolve'
|
|
6
6
|
import {getProjectionState, type ProjectionOptions} from './getProjectionState'
|
|
7
7
|
import {projectionStore} from './projectionStore'
|
|
8
8
|
import {type ProjectionValuePending} from './types'
|
|
@@ -18,7 +18,7 @@ export function resolveProjection<
|
|
|
18
18
|
options: ProjectionOptions<TProjection, TDocumentType, TDataset, TProjectId>,
|
|
19
19
|
): Promise<
|
|
20
20
|
ProjectionValuePending<
|
|
21
|
-
|
|
21
|
+
ResolveProjectionResult<TProjection, TDocumentType, `${TProjectId}.${TDataset}`>
|
|
22
22
|
>
|
|
23
23
|
>
|
|
24
24
|
|