@sanity/sdk 3.0.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 +72 -19
- package/dist/_exports/_internal.d.ts.map +1 -1
- package/dist/_exports/_internal.js +130 -11
- 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 +2 -2
- package/dist/_exports/dashboard.d.ts +2 -0
- package/dist/_exports/dashboard.js +2 -0
- package/dist/{authStore-C0o1NOxW.d.ts → authStore-BO2vch3I.d.ts} +516 -63
- package/dist/authStore-BO2vch3I.d.ts.map +1 -0
- package/dist/{authStore-CtE9bLHW.js → clientStore-BI4D8HhJ.js} +390 -15
- package/dist/clientStore-BI4D8HhJ.js.map +1 -0
- package/dist/{createSanityInstance-DUI1bGIg.d.ts → createSanityInstance-BQIqyGLX.d.ts} +17 -2
- package/dist/createSanityInstance-BQIqyGLX.d.ts.map +1 -0
- package/dist/{createStateSourceAction-BOKtqFNm.js → createStateSourceAction-DdAhEfnZ.js} +7 -3
- package/dist/createStateSourceAction-DdAhEfnZ.js.map +1 -0
- package/dist/defineProperty-Bho9Ngsi.js +31 -0
- package/dist/{getNodeState-CR3__B2D.js → getNodeState-B4nG0sjm.js} +2 -2
- package/dist/{getNodeState-CR3__B2D.js.map → getNodeState-B4nG0sjm.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +370 -90
- package/dist/index.js.map +1 -1
- 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/{queryStore-C7yMHPUI.js → version-BcRmCiYi.js} +48 -16
- package/dist/version-BcRmCiYi.js.map +1 -0
- package/package.json +19 -18
- package/src/_exports/_internal.ts +13 -0
- package/src/_exports/dashboard.ts +36 -0
- package/src/_exports/index.ts +17 -1
- package/src/access/checkPermissions.test.ts +1 -1
- package/src/access/checkPermissions.ts +1 -1
- package/src/applications/applications.test-d.ts +28 -4
- package/src/applications/applications.test.ts +4 -4
- package/src/applications/applications.ts +43 -18
- 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/handleAuthCallback.test.ts +2 -2
- package/src/auth/handleAuthCallback.ts +1 -1
- package/src/auth/logout.test.ts +46 -1
- package/src/auth/logout.ts +2 -1
- 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/auth/refreshStampedToken.ts +1 -1
- package/src/auth/studioModeAuth.test.ts +1 -1
- package/src/auth/studioModeAuth.ts +1 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +2 -2
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +1 -1
- package/src/comments/addonDatasetStore.test.ts +2 -2
- package/src/comments/addonDatasetStore.ts +2 -2
- package/src/comments/commentActions.ts +6 -5
- package/src/comments/commentsStore.ts +4 -4
- 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 +5 -9
- package/src/document/documentStore.concurrency.test.ts +2 -1
- package/src/document/documentStore.test.ts +19 -18
- package/src/document/documentStore.ts +17 -17
- package/src/document/permissions.ts +2 -1
- package/src/document/processActions.test.ts +2 -1
- package/src/document/processMutations.ts +61 -24
- package/src/document/reducers.ts +2 -2
- package/src/installations/installations.test-d.ts +3 -3
- package/src/installations/installations.test.ts +2 -2
- package/src/installations/installations.ts +4 -21
- package/src/organization/organization.test.ts +2 -2
- package/src/organization/organization.ts +1 -1
- package/src/organizations/organizations.test.ts +2 -2
- package/src/organizations/organizations.ts +1 -1
- package/src/presence/presenceStore.test.ts +15 -22
- package/src/presence/presenceStore.ts +3 -2
- package/src/project/project.test.ts +3 -3
- package/src/project/project.ts +1 -1
- package/src/projection/getProjectionState.test.ts +6 -4
- package/src/projection/getProjectionState.ts +4 -4
- package/src/projection/resolveProjection.ts +2 -2
- package/src/projects/projects.test.ts +2 -2
- package/src/projects/projects.ts +1 -1
- package/src/query/queryStore.ts +6 -6
- package/src/store/createSanityInstance.test.ts +1 -1
- package/src/store/createSanityInstance.ts +4 -4
- package/src/store/createStoreInstance.test.ts +0 -5
- package/src/telemetry/telemetryManager.test.ts +1 -1
- package/src/telemetry/telemetryManager.ts +2 -2
- 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/users/usersStore.test.ts +1 -1
- package/src/users/usersStore.ts +5 -5
- package/src/utils/createGroqSearchFilter.test.ts +8 -0
- package/src/utils/createGroqSearchFilter.ts +6 -3
- package/src/utils/ids.test.ts +40 -15
- package/src/utils/ids.ts +47 -2
- package/dist/authStore-C0o1NOxW.d.ts.map +0 -1
- package/dist/authStore-CtE9bLHW.js.map +0 -1
- package/dist/clientStore-BtE2-q2i.js +0 -90
- package/dist/clientStore-BtE2-q2i.js.map +0 -1
- package/dist/createSanityInstance-DUI1bGIg.d.ts.map +0 -1
- package/dist/createStateSourceAction-BOKtqFNm.js.map +0 -1
- package/dist/getEnv-D5RGkQLu.js +0 -8
- package/dist/getEnv-D5RGkQLu.js.map +0 -1
- package/dist/logger-DAtJb5RQ.js +0 -173
- package/dist/logger-DAtJb5RQ.js.map +0 -1
- package/dist/queryStore-C7yMHPUI.js.map +0 -1
- package/dist/rolldown-runtime-vyAXikos.js +0 -9
- package/dist/telemetryManager-UIEiMtC0.js +0 -127
- package/dist/telemetryManager-UIEiMtC0.js.map +0 -1
- package/dist/version-D8RP_Q59.js +0 -9
- package/dist/version-D8RP_Q59.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { C as REQUEST_TAG_PREFIX, S as DEFAULT_API_VERSION, _ as getDefaultLocation, a as getCurrentUserState, b as AuthStateType, c as getLoginUrlState, d as createLoggedInAuthState, f as getAuthCode, i as getAuthState, l as getTokenState, o as getDashboardOrganizationId, p as getCleanedUrl, s as getIsInDashboardState, t as authStore, u as setAuthToken, v as getTokenFromLocation, w as getAuthLogger } from "./authStore-CtE9bLHW.js";
|
|
1
|
+
import { D as getAuthLogger, E as REQUEST_TAG_PREFIX, O as configureLogging$1, S as AuthStateType, T as DEFAULT_BASE, b as getTokenFromLocation, c as getDashboardOrganizationId, d as getTokenState, f as setAuthToken, h as getCleanedUrl, i as authStore, k as createLogger, l as getIsInDashboardState, m as getAuthCode, n as getClient, o as getAuthState, p as createLoggedInAuthState, r as getClientState, s as getCurrentUserState, u as getLoginUrlState, w as DEFAULT_API_VERSION, y as getDefaultLocation } from "./clientStore-BI4D8HhJ.js";
|
|
2
|
+
import { c as isReleasePerspective, d as isMediaLibraryResource, i as bindActionGlobally, l as isCanvasResource, n as bindActionByResource, o as defineStore, r as bindActionByResourceAndPerspective, t as createStateSourceAction, u as isDatasetResource } from "./createStateSourceAction-DdAhEfnZ.js";
|
|
3
|
+
import { A as clearPendingTransaction, B as assertDatasetResource, C as getCommentsState, D as toCommentsKeyParts, E as resolveComments, F as rollbackCommentUpdate, G as defineMutation, H as provisionAddonDataset, I as setCommentCreateError, K as randomId, L as setPendingTransaction, M as receiveComment, N as removeCommentById, O as addComment, P as restoreComments, R as normalizeComment, T as resolveCommentThreads, U as COMMENTS_API_VERSION, V as getAddonDatasetState, W as defineFetcher, _ as updateLastLoadMoreRequest, a as resolveQuery, b as commentsStore, c as getAllReleasesState, d as getUsersKey, f as initializeRequest, g as setUsersError, h as setUsersData, j as getCommentsKey, k as applyCommentUpdate, l as addSubscription, m as removeSubscription, o as getPerspectiveState, p as parseUsersKey, q as randomUuid, r as getQueryState, s as getActiveReleasesState, t as CORE_SDK_VERSION, u as cancelRequest, v as PROJECT_API_VERSION, x as getCommentThreadsState, y as USERS_STATE_CLEAR_DELAY, z as toCommentFieldPath } from "./version-BcRmCiYi.js";
|
|
5
4
|
import { r as omitProperty, t as isDeepEqual } from "./object-CxXlSVg7.js";
|
|
6
|
-
import { n as getClient, r as getClientState } from "./clientStore-BtE2-q2i.js";
|
|
7
5
|
import { n as setCleanupTimeout } from "./setCleanupTimeout-BiM6q1KF.js";
|
|
8
|
-
import { t as
|
|
9
|
-
import { t as
|
|
6
|
+
import { t as _defineProperty } from "./defineProperty-Bho9Ngsi.js";
|
|
7
|
+
import { t as getNodeState } from "./getNodeState-B4nG0sjm.js";
|
|
10
8
|
import { ClientError, CorsOriginError } from "@sanity/client";
|
|
11
9
|
import { EMPTY, NEVER, Observable, Subject, Subscription, auditTime, catchError, combineLatest, concat, concatMap, debounceTime, defer, distinctUntilChanged, filter, first, firstValueFrom, from, fromEvent, groupBy, map, merge, mergeMap, of, pairwise, partition, race, retry, share, shareReplay, skip, startWith, switchMap, take, takeUntil, tap, throttle, throwError, timer, withLatestFrom } from "rxjs";
|
|
12
10
|
import { isKeySegment, isKeyedObject } from "@sanity/types";
|
|
@@ -14,7 +12,6 @@ import { DocumentId, getDraftId, getPublishedId, getVersionId, isDraftId, isPubl
|
|
|
14
12
|
import { getIndexForKey, getIndexForKey as getIndexForKey$1, getPathDepth, joinPaths, jsonMatch, jsonMatch as jsonMatch$1, slicePath, slicePath as slicePath$1, stringifyPath, stringifyPath as stringifyPath$1 } from "@sanity/json-match";
|
|
15
13
|
import { SanityEncoder } from "@sanity/mutate";
|
|
16
14
|
import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
|
|
17
|
-
import "groq";
|
|
18
15
|
import { evaluateSync, parse } from "groq-js";
|
|
19
16
|
import { catchError as catchError$1, distinctUntilChanged as distinctUntilChanged$1, map as map$1, mergeMap as mergeMap$1, retry as retry$1, scan, share as share$1, switchMap as switchMap$1 } from "rxjs/operators";
|
|
20
17
|
import { applyPatches, parsePatch } from "@sanity/diff-match-patch";
|
|
@@ -30,7 +27,7 @@ import { fromUrl } from "@sanity/bifur-client";
|
|
|
30
27
|
* @public
|
|
31
28
|
*/
|
|
32
29
|
function createSanityInstance(config = {}) {
|
|
33
|
-
let instanceId =
|
|
30
|
+
let instanceId = randomId(16), disposeListeners = /* @__PURE__ */ new Map(), disposed = { current: !1 }, instanceContext = {
|
|
34
31
|
instanceId,
|
|
35
32
|
projectId: config.projectId,
|
|
36
33
|
dataset: config.dataset
|
|
@@ -63,7 +60,7 @@ function createSanityInstance(config = {}) {
|
|
|
63
60
|
}), disposed.current = !0, disposeListeners.forEach((listener) => listener()), disposeListeners.clear(), logger.info("Instance disposed");
|
|
64
61
|
},
|
|
65
62
|
onDispose: (cb) => {
|
|
66
|
-
let listenerId =
|
|
63
|
+
let listenerId = randomId(16);
|
|
67
64
|
return disposeListeners.set(listenerId, cb), () => {
|
|
68
65
|
disposeListeners.delete(listenerId);
|
|
69
66
|
};
|
|
@@ -77,7 +74,7 @@ const checkPermissions = defineFetcher({
|
|
|
77
74
|
apiVersion: "v2025-07-11",
|
|
78
75
|
scope: "global"
|
|
79
76
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
80
|
-
|
|
77
|
+
url: `/access/${resourceType}/${resourceId}/user-permissions/me/check`,
|
|
81
78
|
query: { permissions },
|
|
82
79
|
tag: "access.check"
|
|
83
80
|
}).pipe(map((response) => response.data)))),
|
|
@@ -121,7 +118,7 @@ const applications = defineFetcher({
|
|
|
121
118
|
apiVersion: "vX",
|
|
122
119
|
scope: "global"
|
|
123
120
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
124
|
-
|
|
121
|
+
url: "/applications",
|
|
125
122
|
query: buildQuery({
|
|
126
123
|
organizationId: options.organizationId,
|
|
127
124
|
type: options.type,
|
|
@@ -145,7 +142,7 @@ const applications = defineFetcher({
|
|
|
145
142
|
apiVersion: "vX",
|
|
146
143
|
scope: "global"
|
|
147
144
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
148
|
-
|
|
145
|
+
url: `/applications/${applicationId}`,
|
|
149
146
|
query: buildQuery({ include: serializeInclude$1(options?.include) }),
|
|
150
147
|
tag: "applications.get"
|
|
151
148
|
}))),
|
|
@@ -159,7 +156,7 @@ const applications = defineFetcher({
|
|
|
159
156
|
apiVersion: "vX",
|
|
160
157
|
scope: "global"
|
|
161
158
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
162
|
-
|
|
159
|
+
url: `/applications/${applicationId}`,
|
|
163
160
|
method: "PATCH",
|
|
164
161
|
body,
|
|
165
162
|
tag: "applications.update"
|
|
@@ -177,7 +174,7 @@ const applications = defineFetcher({
|
|
|
177
174
|
apiVersion: "vX",
|
|
178
175
|
scope: "global"
|
|
179
176
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
180
|
-
|
|
177
|
+
url: `/applications/${applicationId}`,
|
|
181
178
|
method: "DELETE",
|
|
182
179
|
tag: "applications.delete"
|
|
183
180
|
}))),
|
|
@@ -222,7 +219,7 @@ const projects = defineFetcher({
|
|
|
222
219
|
apiVersion: "v2025-02-19",
|
|
223
220
|
scope: "global"
|
|
224
221
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
225
|
-
|
|
222
|
+
url: "/projects",
|
|
226
223
|
query: buildQuery(normalizeProjectsOptions(options)),
|
|
227
224
|
tag: "projects.list"
|
|
228
225
|
}))),
|
|
@@ -265,7 +262,7 @@ const project = defineFetcher({
|
|
|
265
262
|
apiVersion: "v2025-02-19",
|
|
266
263
|
scope: "global"
|
|
267
264
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
268
|
-
|
|
265
|
+
url: `/projects/${resolveProjectId$1(instance, options)}`,
|
|
269
266
|
query: buildQuery(normalizeProjectOptions(options)),
|
|
270
267
|
tag: "projects.get"
|
|
271
268
|
}))),
|
|
@@ -345,7 +342,7 @@ const handleAuthCallback = bindActionGlobally(authStore, async ({ state, instanc
|
|
|
345
342
|
logger.debug("Fetching token from auth endpoint");
|
|
346
343
|
let { token } = await client.request({
|
|
347
344
|
method: "GET",
|
|
348
|
-
|
|
345
|
+
url: "/auth/fetch",
|
|
349
346
|
query: { sid: authCode },
|
|
350
347
|
tag: "fetch-token"
|
|
351
348
|
});
|
|
@@ -383,7 +380,7 @@ const handleAuthCallback = bindActionGlobally(authStore, async ({ state, instanc
|
|
|
383
380
|
useCdn: !1
|
|
384
381
|
});
|
|
385
382
|
logger.debug("Calling logout endpoint"), await client.request({
|
|
386
|
-
|
|
383
|
+
url: "/auth/logout",
|
|
387
384
|
method: "POST",
|
|
388
385
|
tag: "logout"
|
|
389
386
|
});
|
|
@@ -391,12 +388,273 @@ const handleAuthCallback = bindActionGlobally(authStore, async ({ state, instanc
|
|
|
391
388
|
} catch (error) {
|
|
392
389
|
throw logger.error("Logout request failed", { error }), error;
|
|
393
390
|
} finally {
|
|
394
|
-
logger.info("User logged out, clearing stored tokens"), state.set("logoutSuccess", {
|
|
391
|
+
logger.info("User logged out, clearing stored tokens"), state.set("logoutSuccess", {
|
|
392
|
+
authState: {
|
|
393
|
+
type: "logged-out",
|
|
394
|
+
isDestroyingSession: !1
|
|
395
|
+
},
|
|
396
|
+
oauthTokens: void 0
|
|
397
|
+
}), storageArea?.removeItem(storageKey), storageArea?.removeItem(`${storageKey}_last_refresh`);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
/**
|
|
401
|
+
* Encodes a byte array as a base64url string (RFC 4648 §5) with no padding,
|
|
402
|
+
* as required for PKCE `code_verifier`/`code_challenge` values.
|
|
403
|
+
*
|
|
404
|
+
* @internal
|
|
405
|
+
*/
|
|
406
|
+
function base64UrlEncode(bytes) {
|
|
407
|
+
let binary = "";
|
|
408
|
+
for (let byte of bytes) binary += String.fromCharCode(byte);
|
|
409
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
410
|
+
}
|
|
411
|
+
function randomString() {
|
|
412
|
+
let bytes = /* @__PURE__ */ new Uint8Array(32);
|
|
413
|
+
return crypto.getRandomValues(bytes), base64UrlEncode(bytes);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Generates a PKCE `code_verifier`
|
|
417
|
+
*
|
|
418
|
+
* @internal
|
|
419
|
+
*/
|
|
420
|
+
function generateCodeVerifier() {
|
|
421
|
+
return randomString();
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Generates the `state` parameter used to defend against CSRF on the OAuth
|
|
425
|
+
* callback.
|
|
426
|
+
*
|
|
427
|
+
* @internal
|
|
428
|
+
*/
|
|
429
|
+
function generateState() {
|
|
430
|
+
return randomString();
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Derives the PKCE `code_challenge` from a `code_verifier` using
|
|
434
|
+
* `base64url(sha256(verifier))` (the `S256` method).
|
|
435
|
+
*
|
|
436
|
+
* @internal
|
|
437
|
+
*/
|
|
438
|
+
async function generateCodeChallenge(codeVerifier) {
|
|
439
|
+
let data = new TextEncoder().encode(codeVerifier), digest = await crypto.subtle.digest("SHA-256", data);
|
|
440
|
+
return base64UrlEncode(new Uint8Array(digest));
|
|
441
|
+
}
|
|
442
|
+
/** sessionStorage key for the PKCE `code_verifier`. */
|
|
443
|
+
const OAUTH_VERIFIER_KEY = "__sanity_oauth_verifier", OAUTH_STATE_KEY = "__sanity_oauth_state";
|
|
444
|
+
/** Builds the RFC 8707 resource indicator for an organisation. */
|
|
445
|
+
function getResourceIndicator(organizationId) {
|
|
446
|
+
return `urn:io.sanity:organization:${organizationId}`;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Serialises tokens for storage, converting `expiresAt` to an ISO string.
|
|
450
|
+
*
|
|
451
|
+
* @internal
|
|
452
|
+
*/
|
|
453
|
+
function serializeTokens(tokens) {
|
|
454
|
+
return JSON.stringify({
|
|
455
|
+
accessToken: tokens.accessToken,
|
|
456
|
+
tokenType: tokens.tokenType,
|
|
457
|
+
expiresIn: tokens.expiresIn,
|
|
458
|
+
expiresAt: tokens.expiresAt.toISOString(),
|
|
459
|
+
...tokens.refreshToken !== void 0 && { refreshToken: tokens.refreshToken }
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Reads the store options, throwing when the instance was not configured for
|
|
464
|
+
* OAuth.
|
|
465
|
+
*/
|
|
466
|
+
function getOAuthOptions(state) {
|
|
467
|
+
let { options } = state;
|
|
468
|
+
if (!options.oauth) throw Error("OAuth is not configured on this instance (missing `auth.oauth`).");
|
|
469
|
+
return options;
|
|
470
|
+
}
|
|
471
|
+
/** Creates a client for the (unauthenticated) public OAuth token/revoke calls. */
|
|
472
|
+
function createOAuthClient(options) {
|
|
473
|
+
return options.clientFactory({
|
|
474
|
+
apiVersion: "v1",
|
|
475
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
476
|
+
useProjectHostname: !1,
|
|
477
|
+
useCdn: !1,
|
|
478
|
+
...options.apiHost && { apiHost: options.apiHost }
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
/** Converts a token endpoint response to the {@link OAuthTokens} shape. */
|
|
482
|
+
function toOAuthTokens(response) {
|
|
483
|
+
return {
|
|
484
|
+
accessToken: response.access_token,
|
|
485
|
+
tokenType: "bearer",
|
|
486
|
+
expiresIn: response.expires_in,
|
|
487
|
+
expiresAt: new Date(Date.now() + response.expires_in * 1e3),
|
|
488
|
+
...response.refresh_token !== void 0 && { refreshToken: response.refresh_token }
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Starts the OAuth authorization-code + PKCE flow: generates a `code_verifier`,
|
|
493
|
+
* `code_challenge` and `state`, persists the verifier and state to
|
|
494
|
+
* `sessionStorage`, then navigates the browser to the authorize endpoint.
|
|
495
|
+
*
|
|
496
|
+
* @public
|
|
497
|
+
*/
|
|
498
|
+
const startOAuthAuthorization = bindActionGlobally(authStore, async ({ state, instance }) => {
|
|
499
|
+
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), codeVerifier = generateCodeVerifier(), oauthState = generateState(), codeChallenge = await generateCodeChallenge(codeVerifier), session = typeof sessionStorage < "u" ? sessionStorage : void 0;
|
|
500
|
+
session?.setItem(OAUTH_VERIFIER_KEY, codeVerifier), session?.setItem(OAUTH_STATE_KEY, oauthState);
|
|
501
|
+
let authorizeUrl = new URL("/v1/auth/oauth/authorize", options.apiHost ?? "https://api.sanity.io");
|
|
502
|
+
authorizeUrl.searchParams.set("response_type", "code"), authorizeUrl.searchParams.set("client_id", options.oauth.clientId), authorizeUrl.searchParams.set("redirect_uri", options.oauth.redirectUri), authorizeUrl.searchParams.set("state", oauthState), authorizeUrl.searchParams.set("code_challenge", codeChallenge), authorizeUrl.searchParams.set("code_challenge_method", "S256"), authorizeUrl.searchParams.append("resource", getResourceIndicator(options.oauth.organizationId)), logger.info("Starting OAuth authorization"), typeof window < "u" && typeof window.location?.assign == "function" && window.location.assign(authorizeUrl.toString());
|
|
503
|
+
}), handleOAuthCallback = bindActionGlobally(authStore, async ({ state, instance }, locationHref = getDefaultLocation()) => {
|
|
504
|
+
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), { authState } = state.get();
|
|
505
|
+
if (authState.type === "logging-in" && authState.isExchangingToken) return logger.debug("Skipping OAuth callback - token exchange already in progress"), !1;
|
|
506
|
+
let callbackUrl = new URL(locationHref, DEFAULT_BASE), code = callbackUrl.searchParams.get("code"), returnedState = callbackUrl.searchParams.get("state"), error = callbackUrl.searchParams.get("error"), errorDescription = callbackUrl.searchParams.get("error_description"), session = typeof sessionStorage < "u" ? sessionStorage : void 0, cleanedUrlObj = new URL(locationHref, DEFAULT_BASE);
|
|
507
|
+
for (let param of [
|
|
508
|
+
"code",
|
|
509
|
+
"state",
|
|
510
|
+
"error",
|
|
511
|
+
"error_description"
|
|
512
|
+
]) cleanedUrlObj.searchParams.delete(param);
|
|
513
|
+
let cleanedUrl = cleanedUrlObj.toString();
|
|
514
|
+
if (error) return logger.warn("OAuth callback returned an error", {
|
|
515
|
+
error,
|
|
516
|
+
errorDescription
|
|
517
|
+
}), clearOAuthArtifacts(session), state.set("oauthCallbackError", { authState: {
|
|
518
|
+
type: "error",
|
|
519
|
+
error: Error(errorDescription ? `${error}: ${errorDescription}` : error)
|
|
520
|
+
} }), cleanedUrl;
|
|
521
|
+
if (!code) return logger.debug("No OAuth code found in callback URL"), !1;
|
|
522
|
+
let storedState = session?.getItem("__sanity_oauth_state") ?? null;
|
|
523
|
+
if (!returnedState || !storedState || returnedState !== storedState) return logger.error("OAuth state mismatch — rejecting callback"), clearOAuthArtifacts(session), state.set("oauthStateMismatch", { authState: {
|
|
524
|
+
type: "error",
|
|
525
|
+
error: /* @__PURE__ */ Error("OAuth state mismatch")
|
|
526
|
+
} }), cleanedUrl;
|
|
527
|
+
let codeVerifier = session?.getItem("__sanity_oauth_verifier") ?? null;
|
|
528
|
+
if (!codeVerifier) return logger.error("OAuth code verifier missing — cannot exchange code"), clearOAuthArtifacts(session), state.set("oauthVerifierMissing", { authState: {
|
|
529
|
+
type: "error",
|
|
530
|
+
error: /* @__PURE__ */ Error("OAuth code verifier missing")
|
|
531
|
+
} }), cleanedUrl;
|
|
532
|
+
logger.info("Exchanging OAuth code for tokens"), state.set("oauthExchange", { authState: {
|
|
533
|
+
type: "logging-in",
|
|
534
|
+
isExchangingToken: !0
|
|
535
|
+
} });
|
|
536
|
+
try {
|
|
537
|
+
let client = createOAuthClient(options), params = new URLSearchParams({
|
|
538
|
+
grant_type: "authorization_code",
|
|
539
|
+
code,
|
|
540
|
+
code_verifier: codeVerifier,
|
|
541
|
+
redirect_uri: options.oauth.redirectUri,
|
|
542
|
+
client_id: options.oauth.clientId,
|
|
543
|
+
resource: getResourceIndicator(options.oauth.organizationId)
|
|
544
|
+
}), tokens = toOAuthTokens(await client.request({
|
|
545
|
+
method: "POST",
|
|
546
|
+
url: "/auth/oauth/token",
|
|
547
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
548
|
+
body: params.toString(),
|
|
549
|
+
tag: "oauth.token"
|
|
550
|
+
}));
|
|
551
|
+
return options.storageArea?.setItem(options.storageKey, serializeTokens(tokens)), clearOAuthArtifacts(session), logger.info("OAuth tokens obtained, user logged in"), state.set("oauthLoggedIn", {
|
|
552
|
+
authState: createLoggedInAuthState(tokens.accessToken, null),
|
|
553
|
+
oauthTokens: tokens
|
|
554
|
+
}), cleanedUrl;
|
|
555
|
+
} catch (exchangeError) {
|
|
556
|
+
return logger.error("Failed to exchange OAuth code for tokens", { error: exchangeError }), clearOAuthArtifacts(session), state.set("oauthExchangeError", { authState: {
|
|
557
|
+
type: "error",
|
|
558
|
+
error: exchangeError
|
|
559
|
+
} }), cleanedUrl;
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
/**
|
|
563
|
+
* A refresh failure is unrecoverable only when the token endpoint rejects the
|
|
564
|
+
* refresh token itself (a 4xx). Rate-limit (429) and request-timeout (408)
|
|
565
|
+
* responses, 5xx errors and network failures are transient, so the session is
|
|
566
|
+
* kept intact for the caller to retry rather than forcing a logout.
|
|
567
|
+
*/
|
|
568
|
+
function isUnrecoverableRefreshError(error) {
|
|
569
|
+
return error instanceof ClientError && error.statusCode !== 408 && error.statusCode !== 429;
|
|
570
|
+
}
|
|
571
|
+
let refreshInFlight = null;
|
|
572
|
+
/**
|
|
573
|
+
* Refreshes the OAuth tokens using the `refresh_token` grant. Concurrent
|
|
574
|
+
* callers share a single in-flight request. An unrecoverable failure (a 4xx
|
|
575
|
+
* rejecting the refresh token) clears the tokens and transitions to
|
|
576
|
+
* `LOGGED_OUT`; transient failures (network, 5xx, rate limits) leave the
|
|
577
|
+
* session intact and rethrow so the caller can retry.
|
|
578
|
+
*
|
|
579
|
+
* @public
|
|
580
|
+
*/
|
|
581
|
+
const refreshOAuthTokens = bindActionGlobally(authStore, (context) => refreshInFlight || (refreshInFlight = doRefreshOAuthTokens(context).finally(() => {
|
|
582
|
+
refreshInFlight = null;
|
|
583
|
+
}), refreshInFlight));
|
|
584
|
+
async function doRefreshOAuthTokens({ state, instance }) {
|
|
585
|
+
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), current = state.get().oauthTokens;
|
|
586
|
+
if (!current?.refreshToken) return logger.warn("No refresh token available — logging out"), options.storageArea?.removeItem(options.storageKey), state.set("oauthRefreshNoToken", {
|
|
587
|
+
authState: {
|
|
395
588
|
type: "logged-out",
|
|
396
589
|
isDestroyingSession: !1
|
|
397
|
-
}
|
|
590
|
+
},
|
|
591
|
+
oauthTokens: void 0
|
|
592
|
+
}), null;
|
|
593
|
+
try {
|
|
594
|
+
let client = createOAuthClient(options), params = new URLSearchParams({
|
|
595
|
+
grant_type: "refresh_token",
|
|
596
|
+
refresh_token: current.refreshToken,
|
|
597
|
+
client_id: options.oauth.clientId,
|
|
598
|
+
resource: getResourceIndicator(options.oauth.organizationId)
|
|
599
|
+
}), tokens = toOAuthTokens(await client.request({
|
|
600
|
+
method: "POST",
|
|
601
|
+
url: "/auth/oauth/token",
|
|
602
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
603
|
+
body: params.toString(),
|
|
604
|
+
tag: "oauth.refresh"
|
|
605
|
+
}));
|
|
606
|
+
return tokens.refreshToken ||= current.refreshToken, options.storageArea?.setItem(options.storageKey, serializeTokens(tokens)), logger.info("OAuth tokens refreshed"), state.set("oauthRefreshed", {
|
|
607
|
+
authState: createLoggedInAuthState(tokens.accessToken, null),
|
|
608
|
+
oauthTokens: tokens
|
|
609
|
+
}), tokens;
|
|
610
|
+
} catch (error) {
|
|
611
|
+
throw isUnrecoverableRefreshError(error) ? (logger.error("OAuth token refresh failed — logging out", { error }), options.storageArea?.removeItem(options.storageKey), state.set("oauthRefreshFailed", {
|
|
612
|
+
authState: {
|
|
613
|
+
type: "logged-out",
|
|
614
|
+
isDestroyingSession: !1
|
|
615
|
+
},
|
|
616
|
+
oauthTokens: void 0
|
|
617
|
+
}), error) : (logger.warn("OAuth token refresh failed — keeping session for retry", { error }), error);
|
|
398
618
|
}
|
|
399
|
-
}
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Revokes the OAuth tokens then clears local storage and transitions to `LOGGED_OUT`.
|
|
622
|
+
* Local state is cleared even if the revoke request fails.
|
|
623
|
+
*
|
|
624
|
+
* @public
|
|
625
|
+
*/
|
|
626
|
+
const revokeOAuthTokens = bindActionGlobally(authStore, async ({ state, instance }) => {
|
|
627
|
+
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), current = state.get().oauthTokens, token = current?.refreshToken ?? current?.accessToken;
|
|
628
|
+
try {
|
|
629
|
+
if (token) {
|
|
630
|
+
let client = createOAuthClient(options), params = new URLSearchParams({
|
|
631
|
+
token,
|
|
632
|
+
client_id: options.oauth.clientId
|
|
633
|
+
});
|
|
634
|
+
await client.request({
|
|
635
|
+
method: "POST",
|
|
636
|
+
url: "/auth/oauth/revoke",
|
|
637
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
638
|
+
body: params.toString(),
|
|
639
|
+
tag: "oauth.revoke"
|
|
640
|
+
}), logger.info("OAuth tokens revoked");
|
|
641
|
+
}
|
|
642
|
+
} catch (error) {
|
|
643
|
+
logger.warn("OAuth revoke request failed — clearing local state anyway", { error });
|
|
644
|
+
} finally {
|
|
645
|
+
options.storageArea?.removeItem(options.storageKey), state.set("oauthRevoked", {
|
|
646
|
+
authState: {
|
|
647
|
+
type: "logged-out",
|
|
648
|
+
isDestroyingSession: !1
|
|
649
|
+
},
|
|
650
|
+
oauthTokens: void 0
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}), getOAuthTokensState = bindActionGlobally(authStore, createStateSourceAction(({ state }) => state.oauthTokens ?? null));
|
|
654
|
+
/** Removes the transient PKCE artifacts from session storage. */
|
|
655
|
+
function clearOAuthArtifacts(session) {
|
|
656
|
+
session?.removeItem(OAUTH_VERIFIER_KEY), session?.removeItem(OAUTH_STATE_KEY);
|
|
657
|
+
}
|
|
400
658
|
function weaken(node) {
|
|
401
659
|
return Array.isArray(node) ? node.map(weaken) : node && typeof node == "object" ? "_ref" in node ? {
|
|
402
660
|
...node,
|
|
@@ -517,7 +775,7 @@ const createComment = bindActionByResource(commentsStore, async (context, option
|
|
|
517
775
|
let { instance, key } = context, perspective = options.perspective ?? instance.config.perspective, fieldPath = requireFieldPath(options.fieldPath);
|
|
518
776
|
return postComment(context, options, buildCommentPayload({
|
|
519
777
|
authorId: requireCurrentUserId(instance),
|
|
520
|
-
commentId: options.commentId ??
|
|
778
|
+
commentId: options.commentId ?? randomUuid(),
|
|
521
779
|
contentSnapshot: options.contentSnapshot,
|
|
522
780
|
context: options.context,
|
|
523
781
|
documentRevisionId: options.documentRevisionId,
|
|
@@ -527,7 +785,7 @@ const createComment = bindActionByResource(commentsStore, async (context, option
|
|
|
527
785
|
fieldPath,
|
|
528
786
|
selection: options.selection,
|
|
529
787
|
status: options.status ?? "open",
|
|
530
|
-
threadId: options.threadId ??
|
|
788
|
+
threadId: options.threadId ?? randomUuid(),
|
|
531
789
|
...isReleasePerspective(perspective) ? { documentVersionId: perspective.releaseName } : {}
|
|
532
790
|
}));
|
|
533
791
|
}), replyToComment = bindActionByResource(commentsStore, async (context, options) => {
|
|
@@ -538,7 +796,7 @@ const createComment = bindActionByResource(commentsStore, async (context, option
|
|
|
538
796
|
let perspective = options.perspective ?? instance.config.perspective;
|
|
539
797
|
return postComment(context, options, buildCommentPayload({
|
|
540
798
|
authorId: requireCurrentUserId(instance),
|
|
541
|
-
commentId: options.commentId ??
|
|
799
|
+
commentId: options.commentId ?? randomUuid(),
|
|
542
800
|
handle: options,
|
|
543
801
|
message: options.message,
|
|
544
802
|
parentCommentId: parent?.parentCommentId ?? options.parentCommentId,
|
|
@@ -549,7 +807,7 @@ const createComment = bindActionByResource(commentsStore, async (context, option
|
|
|
549
807
|
...isReleasePerspective(perspective) ? { documentVersionId: perspective.releaseName } : {}
|
|
550
808
|
}));
|
|
551
809
|
}), updateComment = bindActionByResource(commentsStore, async ({ state, instance, key }, { commentId, message }) => {
|
|
552
|
-
let lastEditedAt = (/* @__PURE__ */ new Date()).toISOString(), transactionId =
|
|
810
|
+
let lastEditedAt = (/* @__PURE__ */ new Date()).toISOString(), transactionId = randomUuid(), previous = findCommentById(state, commentId);
|
|
553
811
|
previous && (state.set("setPendingTransaction", setPendingTransaction(commentId, transactionId)), state.set("updateComment", applyCommentUpdate(commentId, {
|
|
554
812
|
message,
|
|
555
813
|
lastEditedAt
|
|
@@ -564,7 +822,7 @@ const createComment = bindActionByResource(commentsStore, async (context, option
|
|
|
564
822
|
throw previous && state.set("rollbackCommentUpdate", rollbackCommentUpdate(commentId, transactionId, previous)), error;
|
|
565
823
|
}
|
|
566
824
|
}), setCommentStatus = bindActionByResource(commentsStore, async ({ state, instance, key }, { commentId, status }) => {
|
|
567
|
-
let transactionId =
|
|
825
|
+
let transactionId = randomUuid(), previousComments = [];
|
|
568
826
|
for (let entry of Object.values(state.get().entries)) for (let candidate of Object.values(entry?.comments ?? {})) (candidate._id === commentId || candidate.parentCommentId === commentId) && (previousComments.push(candidate), state.set("setPendingTransaction", setPendingTransaction(candidate._id, transactionId)), state.set("updateCommentStatus", applyCommentUpdate(candidate._id, { status })));
|
|
569
827
|
try {
|
|
570
828
|
await (await getWritableClient(instance, key.resource, { createIfMissing: !1 })).mutate([{ patch: {
|
|
@@ -1232,7 +1490,29 @@ function unsetDeep(input, path) {
|
|
|
1232
1490
|
let segment = _segment;
|
|
1233
1491
|
return typeof segment == "number" && Array.isArray(input) && (segment = segment < 0 ? input.length + segment : segment), segment in input ? restOfPath.length ? Array.isArray(input) ? input.map((nestedInput, index) => index === segment ? unsetDeep(nestedInput, restOfPath) : nestedInput) : Object.fromEntries(Object.entries(input).map(([key, value]) => key === segment ? [key, unsetDeep(value, restOfPath)] : [key, value])) : Array.isArray(input) ? input.filter((_nestedInput, index) => index !== segment) : Object.fromEntries(Object.entries(input).filter(([key]) => key !== segment.toString())) : input;
|
|
1234
1492
|
}
|
|
1235
|
-
|
|
1493
|
+
/**
|
|
1494
|
+
* Exposes the patch operations used by {@link processMutations}.
|
|
1495
|
+
*
|
|
1496
|
+
* @remarks
|
|
1497
|
+
* Property order determines execution order in {@link processMutations}:
|
|
1498
|
+
* `ifRevisionID`, `set`, `setIfMissing`, `unset`, `inc`, `dec`, `insert`,
|
|
1499
|
+
* then `diffMatchPatch`. Reordering the properties changes mutation results.
|
|
1500
|
+
* Freezes the collection to prevent callers from replacing the functions
|
|
1501
|
+
* used by the SDK's mutation evaluator.
|
|
1502
|
+
*
|
|
1503
|
+
* @see https://www.sanity.io/docs/http-mutations#5b4db1396e56
|
|
1504
|
+
*
|
|
1505
|
+
* @example
|
|
1506
|
+
* ```ts
|
|
1507
|
+
* const document = {items: [{_key: 'a', title: 'Before'}]}
|
|
1508
|
+
* const updated = patchOperations.set<typeof document>(document, {
|
|
1509
|
+
* 'items[_key=="a"].title': 'After',
|
|
1510
|
+
* })
|
|
1511
|
+
* ```
|
|
1512
|
+
*
|
|
1513
|
+
* @internal
|
|
1514
|
+
*/
|
|
1515
|
+
const patchOperations = Object.freeze({
|
|
1236
1516
|
ifRevisionID,
|
|
1237
1517
|
set,
|
|
1238
1518
|
setIfMissing,
|
|
@@ -1241,7 +1521,7 @@ const patchOperations = {
|
|
|
1241
1521
|
dec,
|
|
1242
1522
|
insert,
|
|
1243
1523
|
diffMatchPatch
|
|
1244
|
-
};
|
|
1524
|
+
});
|
|
1245
1525
|
/**
|
|
1246
1526
|
* Implements ID generation:
|
|
1247
1527
|
*
|
|
@@ -1258,7 +1538,7 @@ const patchOperations = {
|
|
|
1258
1538
|
* [- source](https://www.sanity.io/docs/http-mutations#c732f27330a4)
|
|
1259
1539
|
*/
|
|
1260
1540
|
function getId(id) {
|
|
1261
|
-
return !id || typeof id != "string" ?
|
|
1541
|
+
return !id || typeof id != "string" ? randomUuid() : id.endsWith(".") ? `${id}${randomUuid()}` : id;
|
|
1262
1542
|
}
|
|
1263
1543
|
function getDocumentIds(selection) {
|
|
1264
1544
|
if ("id" in selection) {
|
|
@@ -1269,18 +1549,31 @@ function getDocumentIds(selection) {
|
|
|
1269
1549
|
return [];
|
|
1270
1550
|
}
|
|
1271
1551
|
/**
|
|
1272
|
-
* Applies
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1552
|
+
* Applies mutations to an in-memory set of Sanity documents.
|
|
1553
|
+
* Deleted documents remain in the returned set with a value of `null`.
|
|
1554
|
+
*
|
|
1555
|
+
* Include every document affected by `mutations` in `documents`, using `null`
|
|
1556
|
+
* for documents that do not exist.
|
|
1557
|
+
*
|
|
1558
|
+
* Returns `documents` itself when `mutations` is empty. Otherwise, returns a
|
|
1559
|
+
* shallow copy of that object. The result can reuse document objects and
|
|
1560
|
+
* nested objects from `documents`. Mutating a reused object through the
|
|
1561
|
+
* result also changes the input.
|
|
1278
1562
|
*
|
|
1279
|
-
*
|
|
1280
|
-
*
|
|
1563
|
+
* Sets `_rev` to `transactionId` on created, replaced, and patched documents.
|
|
1564
|
+
* Uses `timestamp` for timestamps unless the mutation preserves them.
|
|
1565
|
+
* Ignores `merge` patches; `inc` and `dec` skip values that are not numbers.
|
|
1566
|
+
* Generates document IDs when omitted or ending in `.`.
|
|
1567
|
+
* Patch operations can generate missing array keys.
|
|
1281
1568
|
*
|
|
1282
|
-
*
|
|
1283
|
-
*
|
|
1569
|
+
* Does not persist documents or run Content Lake's server validation.
|
|
1570
|
+
*
|
|
1571
|
+
* @throws If a selection uses a query, a `create` targets an existing document,
|
|
1572
|
+
* or a `patch` targets a document that does not exist.
|
|
1573
|
+
* @throws If a patch operation fails, including a revision check failure or
|
|
1574
|
+
* `diffMatchPatch` applied to a value other than a string or `undefined`.
|
|
1575
|
+
*
|
|
1576
|
+
* @internal
|
|
1284
1577
|
*/
|
|
1285
1578
|
function processMutations({ documents, mutations, transactionId, timestamp }) {
|
|
1286
1579
|
if (!mutations.length) return documents;
|
|
@@ -1340,36 +1633,6 @@ function processMutations({ documents, mutations, transactionId, timestamp }) {
|
|
|
1340
1633
|
}
|
|
1341
1634
|
return dataset;
|
|
1342
1635
|
}
|
|
1343
|
-
function _typeof(o) {
|
|
1344
|
-
"@babel/helpers - typeof";
|
|
1345
|
-
return _typeof = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(o) {
|
|
1346
|
-
return typeof o;
|
|
1347
|
-
} : function(o) {
|
|
1348
|
-
return o && typeof Symbol == "function" && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
1349
|
-
}, _typeof(o);
|
|
1350
|
-
}
|
|
1351
|
-
function toPrimitive(t, r) {
|
|
1352
|
-
if (_typeof(t) != "object" || !t) return t;
|
|
1353
|
-
var e = t[Symbol.toPrimitive];
|
|
1354
|
-
if (e !== void 0) {
|
|
1355
|
-
var i = e.call(t, r || "default");
|
|
1356
|
-
if (_typeof(i) != "object") return i;
|
|
1357
|
-
throw TypeError("@@toPrimitive must return a primitive value.");
|
|
1358
|
-
}
|
|
1359
|
-
return (r === "string" ? String : Number)(t);
|
|
1360
|
-
}
|
|
1361
|
-
function toPropertyKey(t) {
|
|
1362
|
-
var i = toPrimitive(t, "string");
|
|
1363
|
-
return _typeof(i) == "symbol" ? i : i + "";
|
|
1364
|
-
}
|
|
1365
|
-
function _defineProperty(e, r, t) {
|
|
1366
|
-
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
1367
|
-
value: t,
|
|
1368
|
-
enumerable: !0,
|
|
1369
|
-
configurable: !0,
|
|
1370
|
-
writable: !0
|
|
1371
|
-
}) : e[r] = t, e;
|
|
1372
|
-
}
|
|
1373
1636
|
var OutOfSyncError = class extends Error {
|
|
1374
1637
|
constructor(message, state) {
|
|
1375
1638
|
super(message), _defineProperty(
|
|
@@ -1790,7 +2053,7 @@ const _calculatePermissions = createSelector([
|
|
|
1790
2053
|
try {
|
|
1791
2054
|
processActions({
|
|
1792
2055
|
actions,
|
|
1793
|
-
transactionId:
|
|
2056
|
+
transactionId: randomId(16),
|
|
1794
2057
|
working: documents,
|
|
1795
2058
|
base: documents,
|
|
1796
2059
|
timestamp,
|
|
@@ -2835,7 +3098,7 @@ function evictOrphanedDocumentStates(documentStates) {
|
|
|
2835
3098
|
return next;
|
|
2836
3099
|
}
|
|
2837
3100
|
function manageSubscriberIds({ state }, handles) {
|
|
2838
|
-
let documentIds = getDocumentIdsFromHandleLikes(handles), subscriptionId =
|
|
3101
|
+
let documentIds = getDocumentIdsFromHandleLikes(handles), subscriptionId = randomId(16);
|
|
2839
3102
|
return state.set("addSubscribers", (prev) => documentIds.reduce((acc, id) => addSubscriptionIdToDocument(acc, id, subscriptionId), prev)), () => {
|
|
2840
3103
|
setCleanupTimeout(() => {
|
|
2841
3104
|
state.set("removeSubscribers", (prev) => documentIds.reduce((acc, id) => removeSubscriptionIdFromDocument(acc, id, subscriptionId), prev));
|
|
@@ -3185,13 +3448,13 @@ const _resolveDocument = bindActionByResource(documentStore, ({ instance }, docH
|
|
|
3185
3448
|
let clientOptions = {
|
|
3186
3449
|
apiVersion: API_VERSION$4,
|
|
3187
3450
|
resource
|
|
3188
|
-
},
|
|
3189
|
-
if (resource && isDatasetResource(resource))
|
|
3190
|
-
else if (resource && isMediaLibraryResource(resource))
|
|
3191
|
-
else if (resource && isCanvasResource(resource))
|
|
3451
|
+
}, url;
|
|
3452
|
+
if (resource && isDatasetResource(resource)) url = `/projects/${resource.projectId}/datasets/${resource.dataset}/acl`;
|
|
3453
|
+
else if (resource && isMediaLibraryResource(resource)) url = `/media-libraries/${resource.mediaLibraryId}/acl`;
|
|
3454
|
+
else if (resource && isCanvasResource(resource)) url = `/canvases/${resource.canvasId}/acl`;
|
|
3192
3455
|
else throw Error(`Received invalid resource: ${JSON.stringify(resource)}`);
|
|
3193
3456
|
return getClientState(instance, clientOptions).observable.pipe(switchMap((client) => client.observable.request({
|
|
3194
|
-
|
|
3457
|
+
url,
|
|
3195
3458
|
tag: "acl.get"
|
|
3196
3459
|
}).pipe(retry({ delay: (error, retryCount) => {
|
|
3197
3460
|
let isTransientClientError = error instanceof ClientError && (error.statusCode === 408 || error.statusCode === 429);
|
|
@@ -3269,7 +3532,7 @@ function applyDocumentActions(...args) {
|
|
|
3269
3532
|
}
|
|
3270
3533
|
const boundApplyDocumentActions = bindActionByResource(documentStore, _applyDocumentActions);
|
|
3271
3534
|
/** @internal */
|
|
3272
|
-
async function _applyDocumentActions({ state }, { actions, resource, transactionId =
|
|
3535
|
+
async function _applyDocumentActions({ state }, { actions, resource, transactionId = randomUuid(), disableBatching }) {
|
|
3273
3536
|
let { events } = state.get(), transaction = {
|
|
3274
3537
|
transactionId,
|
|
3275
3538
|
actions: normalizeActionsForResource(actions, resource),
|
|
@@ -3395,7 +3658,7 @@ const installations = defineFetcher({
|
|
|
3395
3658
|
apiVersion: "vX",
|
|
3396
3659
|
scope: "global"
|
|
3397
3660
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
3398
|
-
|
|
3661
|
+
url: "/installations",
|
|
3399
3662
|
query: buildQuery({
|
|
3400
3663
|
organizationId: options.organizationId,
|
|
3401
3664
|
include: serializeInclude(options.include),
|
|
@@ -3418,7 +3681,7 @@ const installations = defineFetcher({
|
|
|
3418
3681
|
apiVersion: "vX",
|
|
3419
3682
|
scope: "global"
|
|
3420
3683
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
3421
|
-
|
|
3684
|
+
url: `/installations/${installationId}`,
|
|
3422
3685
|
query: buildQuery({ include: serializeInclude(options?.include) }),
|
|
3423
3686
|
tag: "installations.get"
|
|
3424
3687
|
}))),
|
|
@@ -3458,7 +3721,7 @@ const organization = defineFetcher({
|
|
|
3458
3721
|
apiVersion: "v2025-02-19",
|
|
3459
3722
|
scope: "global"
|
|
3460
3723
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
3461
|
-
|
|
3724
|
+
url: `/organizations/${resolveOrganizationId(options)}`,
|
|
3462
3725
|
query: buildQuery(normalizeOrganizationOptions(options)),
|
|
3463
3726
|
tag: "organizations.get"
|
|
3464
3727
|
}))),
|
|
@@ -3492,7 +3755,7 @@ const organizations = defineFetcher({
|
|
|
3492
3755
|
apiVersion: "v2025-02-19",
|
|
3493
3756
|
scope: "global"
|
|
3494
3757
|
}).observable.pipe(switchMap((client) => client.observable.request({
|
|
3495
|
-
|
|
3758
|
+
url: "/organizations",
|
|
3496
3759
|
query: buildQuery(normalizeOrganizationsOptions(options)),
|
|
3497
3760
|
tag: "organizations.list"
|
|
3498
3761
|
}))),
|
|
@@ -3529,7 +3792,7 @@ const organizations = defineFetcher({
|
|
|
3529
3792
|
useProjectHostname: !0
|
|
3530
3793
|
}).observable.request({
|
|
3531
3794
|
method: "GET",
|
|
3532
|
-
|
|
3795
|
+
url: `/users/${userId}`,
|
|
3533
3796
|
tag: "users.get"
|
|
3534
3797
|
}).pipe(map((user) => ({
|
|
3535
3798
|
data: [{
|
|
@@ -3558,7 +3821,7 @@ const organizations = defineFetcher({
|
|
|
3558
3821
|
}), resourceType = options.resourceType || "project", resourceId = resourceType === "organization" ? options.organizationId : options.projectId;
|
|
3559
3822
|
return resourceId ? client.observable.request({
|
|
3560
3823
|
method: "GET",
|
|
3561
|
-
|
|
3824
|
+
url: `access/${resourceType}/${resourceId}/users/${userId}`,
|
|
3562
3825
|
tag: "users.get"
|
|
3563
3826
|
}).pipe(map((response) => "sanityUserId" in response ? {
|
|
3564
3827
|
data: [response],
|
|
@@ -3582,7 +3845,7 @@ const organizations = defineFetcher({
|
|
|
3582
3845
|
loadMore$
|
|
3583
3846
|
]).pipe(withLatestFrom(cursor$), switchMap(([[resource, client], cursor]) => client.observable.request({
|
|
3584
3847
|
method: "GET",
|
|
3585
|
-
|
|
3848
|
+
url: `access/${resource.type}/${resource.id}/users`,
|
|
3586
3849
|
tag: "users.list",
|
|
3587
3850
|
query: cursor ? {
|
|
3588
3851
|
nextCursor: cursor,
|
|
@@ -3604,7 +3867,7 @@ const organizations = defineFetcher({
|
|
|
3604
3867
|
};
|
|
3605
3868
|
}),
|
|
3606
3869
|
onSubscribe: ({ instance, state }, options) => {
|
|
3607
|
-
let subscriptionId =
|
|
3870
|
+
let subscriptionId = randomId(16), key = getUsersKey(instance, options);
|
|
3608
3871
|
return state.set("addSubscription", addSubscription(subscriptionId, key)), () => {
|
|
3609
3872
|
setCleanupTimeout(() => state.set("removeSubscription", removeSubscription(subscriptionId, key)), USERS_STATE_CLEAR_DELAY);
|
|
3610
3873
|
};
|
|
@@ -3756,7 +4019,7 @@ const presenceStore = defineStore({
|
|
|
3756
4019
|
initialize: (context) => {
|
|
3757
4020
|
let { instance, state, key: { resource } } = context;
|
|
3758
4021
|
if (isMediaLibraryResource(resource)) throw Error("Presence is not supported for media library resources.");
|
|
3759
|
-
let sessionId =
|
|
4022
|
+
let sessionId = randomId(16), client = isDatasetResource(resource) ? getClient(instance, {
|
|
3760
4023
|
apiVersion: PRESENCE_API_VERSION,
|
|
3761
4024
|
projectId: resource.projectId,
|
|
3762
4025
|
dataset: resource.dataset,
|
|
@@ -3839,7 +4102,7 @@ const presenceStore = defineStore({
|
|
|
3839
4102
|
})), isCanvasResource(resource)) {
|
|
3840
4103
|
let globalClient = getClient(instance, { apiVersion: PRESENCE_API_VERSION });
|
|
3841
4104
|
subscription.add(globalClient.observable.request({
|
|
3842
|
-
|
|
4105
|
+
url: `/canvases/${resource.canvasId}`,
|
|
3843
4106
|
tag: "canvases.get"
|
|
3844
4107
|
}).subscribe({
|
|
3845
4108
|
next: ({ organizationId }) => {
|
|
@@ -4181,7 +4444,7 @@ const _getProjectionState = bindActionByResourceAndPerspective(projectionStore,
|
|
|
4181
4444
|
return state.values[documentId]?.[projectionHash] ?? STABLE_EMPTY_PROJECTION;
|
|
4182
4445
|
},
|
|
4183
4446
|
onSubscribe: ({ state }, options) => {
|
|
4184
|
-
let { projection, ...docHandle } = options, subscriptionId =
|
|
4447
|
+
let { projection, ...docHandle } = options, subscriptionId = randomId(16), documentId = getPublishedId(DocumentId(docHandle.documentId)), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
4185
4448
|
return state.set("addSubscription", (prev) => ({
|
|
4186
4449
|
documentProjections: {
|
|
4187
4450
|
...prev.documentProjections,
|
|
@@ -4232,6 +4495,23 @@ function resolveProjection(...args) {
|
|
|
4232
4495
|
*/
|
|
4233
4496
|
const _resolveProjection = bindActionByResourceAndPerspective(projectionStore, ({ instance }, options) => firstValueFrom(getProjectionState(instance, options).observable.pipe(filter((state) => !!state?.data))));
|
|
4234
4497
|
/**
|
|
4498
|
+
* Preserves a projection string's literal type and returns the string unchanged.
|
|
4499
|
+
* Use this import when migrating an app with existing experimental Typegen output.
|
|
4500
|
+
*
|
|
4501
|
+
* Current Typegen does not scan this helper. New or changed projections need an
|
|
4502
|
+
* explicit result type until projection generation is supported.
|
|
4503
|
+
*
|
|
4504
|
+
* @example
|
|
4505
|
+
* ```ts
|
|
4506
|
+
* const preview = defineProjection('{title, "author": author->name}')
|
|
4507
|
+
* ```
|
|
4508
|
+
*
|
|
4509
|
+
* @beta
|
|
4510
|
+
*/
|
|
4511
|
+
function defineProjection(projection) {
|
|
4512
|
+
return projection;
|
|
4513
|
+
}
|
|
4514
|
+
/**
|
|
4235
4515
|
* @public
|
|
4236
4516
|
* Extracts the project ID from a CorsOriginError message.
|
|
4237
4517
|
* @param error - The error to extract the project ID from.
|
|
@@ -4269,6 +4549,6 @@ function isImportError(error) {
|
|
|
4269
4549
|
let message = error.message || "";
|
|
4270
4550
|
return /Loading chunk [\w-]+ failed/i.test(message) || /Failed to fetch dynamically imported module/i.test(message) || /error loading dynamically imported module/i.test(message) || /Import(?:ing)? a module script failed/i.test(message) || /Unable to preload CSS/i.test(message);
|
|
4271
4551
|
}
|
|
4272
|
-
export { AuthStateType, CORE_SDK_VERSION, application, applications, applyDocumentActions, archiveRelease, checkPermissions, configureLogging, createComment, createDatasetHandle, createDocument, createDocumentHandle, createDocumentTypeHandle, createProjectHandle, createRelease, createSanityInstance, datasets, deleteApplication, deleteDocument, deleteRelease, discardDocument, editDocument, editRelease, favorites, getActiveReleasesState, getAllReleasesState, getAuthState, getClient, getClientState, getCommentThreadsState, getCommentsState, getCorsErrorProjectId, getCurrentUserState, getDashboardOrganizationId, getDocumentPresence, getDocumentState, getDocumentSyncStatus, getIndexForKey, getIsInDashboardState, getLoginUrlState, getPathDepth, getPermissionsState, getPerspectiveState, getPresence, getProjectionState, getQueryState, getReleaseDocumentId, getTokenState, getUserState, getUsersState, handleAuthCallback, installation, installations, isCanvasResource, isDatasetResource, isImportError, isMediaLibraryResource, joinPaths, jsonMatch, loadMoreUsers, logout, observeOrganizationVerificationState, organization, organizations, project, projects, publishDocument, publishRelease, removeComment, replyToComment, reportPresence, resolveCommentThreads, resolveComments, resolveDocument, resolvePermissions, resolveProjection, resolveQuery, resolveUser, resolveUsers, scheduleRelease, setAuthToken, setCommentStatus, setFavorite, slicePath, stringifyPath, subscribeDocumentEvents, unarchiveRelease, unpublishDocument, unscheduleRelease, updateApplication, updateComment };
|
|
4552
|
+
export { AuthStateType, CORE_SDK_VERSION, application, applications, applyDocumentActions, archiveRelease, checkPermissions, configureLogging, createComment, createDatasetHandle, createDocument, createDocumentHandle, createDocumentTypeHandle, createProjectHandle, createRelease, createSanityInstance, datasets, defineProjection, deleteApplication, deleteDocument, deleteRelease, discardDocument, editDocument, editRelease, favorites, getActiveReleasesState, getAllReleasesState, getAuthState, getClient, getClientState, getCommentThreadsState, getCommentsState, getCorsErrorProjectId, getCurrentUserState, getDashboardOrganizationId, getDocumentPresence, getDocumentState, getDocumentSyncStatus, getIndexForKey, getIsInDashboardState, getLoginUrlState, getOAuthTokensState, getPathDepth, getPermissionsState, getPerspectiveState, getPresence, getProjectionState, getQueryState, getReleaseDocumentId, getTokenState, getUserState, getUsersState, handleAuthCallback, handleOAuthCallback, installation, installations, isCanvasResource, isDatasetResource, isImportError, isMediaLibraryResource, joinPaths, jsonMatch, loadMoreUsers, logout, observeOrganizationVerificationState, organization, organizations, patchOperations, processMutations, project, projects, publishDocument, publishRelease, refreshOAuthTokens, removeComment, replyToComment, reportPresence, resolveCommentThreads, resolveComments, resolveDocument, resolvePermissions, resolveProjection, resolveQuery, resolveUser, resolveUsers, revokeOAuthTokens, scheduleRelease, setAuthToken, setCommentStatus, setFavorite, slicePath, startOAuthAuthorization, stringifyPath, subscribeDocumentEvents, unarchiveRelease, unpublishDocument, unscheduleRelease, updateApplication, updateComment };
|
|
4273
4553
|
|
|
4274
4554
|
//# sourceMappingURL=index.js.map
|