@sanity/sdk 2.6.0 → 2.7.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/index.d.ts +124 -13
- package/dist/index.js +468 -243
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/_exports/index.ts +3 -0
- package/src/auth/authMode.test.ts +56 -0
- package/src/auth/authMode.ts +71 -0
- package/src/auth/authStore.test.ts +85 -4
- package/src/auth/authStore.ts +63 -125
- package/src/auth/authStrategy.ts +39 -0
- package/src/auth/dashboardAuth.ts +132 -0
- package/src/auth/standaloneAuth.ts +109 -0
- package/src/auth/studioAuth.ts +217 -0
- package/src/auth/studioModeAuth.test.ts +43 -1
- package/src/auth/studioModeAuth.ts +10 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +21 -6
- package/src/config/sanityConfig.ts +48 -7
- package/src/projection/getProjectionState.ts +6 -5
- package/src/projection/projectionQuery.test.ts +38 -55
- package/src/projection/projectionQuery.ts +27 -31
- package/src/projection/projectionStore.test.ts +4 -4
- package/src/projection/projectionStore.ts +3 -2
- package/src/projection/resolveProjection.ts +2 -2
- package/src/projection/statusQuery.test.ts +35 -0
- package/src/projection/statusQuery.ts +71 -0
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +63 -50
- package/src/projection/subscribeToStateAndFetchBatches.ts +106 -27
- package/src/projection/types.ts +12 -0
- package/src/projection/util.ts +0 -1
- package/src/query/queryStore.test.ts +64 -0
- package/src/query/queryStore.ts +30 -10
- package/src/releases/getPerspectiveState.test.ts +17 -14
- package/src/releases/getPerspectiveState.ts +58 -38
- package/src/releases/releasesStore.test.ts +59 -61
- package/src/releases/releasesStore.ts +21 -35
- package/src/releases/utils/isReleasePerspective.ts +7 -0
- package/src/store/createActionBinder.test.ts +211 -1
- package/src/store/createActionBinder.ts +95 -17
- package/src/store/createSanityInstance.ts +3 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, from, timer, switchMap, takeWhile, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, combineLatest, of, concatMap, withLatestFrom, concat, throwError, first as first$1, Subject, takeUntil, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, NEVER, Subscription,
|
|
1
|
+
import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, from, timer, switchMap, takeWhile, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, combineLatest, of, concatMap, withLatestFrom, concat, throwError, first as first$1, Subject, takeUntil, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, NEVER, Subscription, debounceTime } from "rxjs";
|
|
2
2
|
import { createClient, CorsOriginError } from "@sanity/client";
|
|
3
3
|
import { pick, omit, isEqual, isObject } from "lodash-es";
|
|
4
4
|
import { devtools } from "zustand/middleware";
|
|
5
5
|
import { createStore } from "zustand/vanilla";
|
|
6
|
-
import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter as filter$1, map as map$1, delay, tap, catchError, scan, share as share$1
|
|
6
|
+
import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter as filter$1, map as map$1, delay, tap, catchError, scan, share as share$1 } from "rxjs/operators";
|
|
7
7
|
import { createController, createNode } from "@sanity/comlink";
|
|
8
8
|
import { createSelector } from "reselect";
|
|
9
9
|
import { SanityEncoder } from "@sanity/mutate";
|
|
@@ -17,6 +17,7 @@ import { isKeySegment, isKeyedObject } from "@sanity/types";
|
|
|
17
17
|
import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
|
|
18
18
|
import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
|
|
19
19
|
import { fromUrl } from "@sanity/bifur-client";
|
|
20
|
+
import { DocumentId, getPublishedId as getPublishedId$2, getDraftId as getDraftId$1, getVersionId, isDraftId, isVersionId, isPublishedId } from "@sanity/id-utils";
|
|
20
21
|
function isDatasetSource(source) {
|
|
21
22
|
return "projectId" in source && "dataset" in source;
|
|
22
23
|
}
|
|
@@ -26,6 +27,7 @@ function isMediaLibrarySource(source) {
|
|
|
26
27
|
function isCanvasSource(source) {
|
|
27
28
|
return "canvasId" in source;
|
|
28
29
|
}
|
|
30
|
+
const isReleasePerspective = (perspective) => typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
|
|
29
31
|
function getPublishedId(id) {
|
|
30
32
|
const draftsPrefix = "drafts.";
|
|
31
33
|
return id.startsWith(draftsPrefix) ? id.slice(draftsPrefix.length) : id;
|
|
@@ -166,7 +168,9 @@ function createSanityInstance(config = {}) {
|
|
|
166
168
|
projectId: config.projectId,
|
|
167
169
|
dataset: config.dataset,
|
|
168
170
|
perspective: config.perspective,
|
|
169
|
-
|
|
171
|
+
hasStudioConfig: !!config.studio,
|
|
172
|
+
hasStudioTokenSource: !!config.studio?.auth?.token,
|
|
173
|
+
legacyStudioMode: config.studioMode?.enabled,
|
|
170
174
|
hasAuthProviders: !!config.auth?.providers,
|
|
171
175
|
hasAuthToken: !!config.auth?.token
|
|
172
176
|
});
|
|
@@ -279,16 +283,33 @@ const bindActionByDataset = createActionBinder((instance, options) => {
|
|
|
279
283
|
if (!projectId || !dataset)
|
|
280
284
|
throw new Error("This API requires a project ID and dataset configured.");
|
|
281
285
|
return { name: `${projectId}.${dataset}`, projectId, dataset };
|
|
282
|
-
}),
|
|
286
|
+
}), createSourceKey = (instance, source) => {
|
|
287
|
+
let name, sourceForKey;
|
|
283
288
|
if (source) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
289
|
+
if (sourceForKey = source, isDatasetSource(source))
|
|
290
|
+
name = `${source.projectId}.${source.dataset}`;
|
|
291
|
+
else if (isMediaLibrarySource(source))
|
|
292
|
+
name = `media-library:${source.mediaLibraryId}`;
|
|
293
|
+
else if (isCanvasSource(source))
|
|
294
|
+
name = `canvas:${source.canvasId}`;
|
|
295
|
+
else
|
|
296
|
+
throw new Error(`Received invalid source: ${JSON.stringify(source)}`);
|
|
297
|
+
return { name, source: sourceForKey };
|
|
287
298
|
}
|
|
288
299
|
const { projectId, dataset } = instance.config;
|
|
289
300
|
if (!projectId || !dataset)
|
|
290
301
|
throw new Error("This API requires a project ID and dataset configured.");
|
|
291
|
-
return { name: `${projectId}.${dataset}
|
|
302
|
+
return { name: `${projectId}.${dataset}`, source: { projectId, dataset } };
|
|
303
|
+
}, bindActionBySource = createActionBinder((instance, { source }) => createSourceKey(instance, source)), bindActionBySourceAndPerspective = createActionBinder((instance, options) => {
|
|
304
|
+
const { source, perspective } = options, utilizedPerspective = perspective ?? instance.config.perspective ?? "drafts";
|
|
305
|
+
let perspectiveKey;
|
|
306
|
+
isReleasePerspective(utilizedPerspective) ? perspectiveKey = utilizedPerspective.releaseName : typeof utilizedPerspective == "string" ? perspectiveKey = utilizedPerspective : perspectiveKey = JSON.stringify(utilizedPerspective);
|
|
307
|
+
const sourceKey = createSourceKey(instance, source);
|
|
308
|
+
return {
|
|
309
|
+
name: `${sourceKey.name}:${perspectiveKey}`,
|
|
310
|
+
source: sourceKey.source,
|
|
311
|
+
perspective: utilizedPerspective
|
|
312
|
+
};
|
|
292
313
|
}), bindActionGlobally = createActionBinder((..._rest) => ({ name: "global" }));
|
|
293
314
|
function createStateSourceAction(options) {
|
|
294
315
|
const selector = typeof options == "function" ? options : options.selector, subscribeHandler = options && "onSubscribe" in options ? options.onSubscribe : void 0, isEqual2 = options && "isEqual" in options ? options.isEqual ?? Object.is : Object.is, selectorContextCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -337,8 +358,25 @@ function createStateSourceAction(options) {
|
|
|
337
358
|
}
|
|
338
359
|
return stateSourceAction;
|
|
339
360
|
}
|
|
361
|
+
const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth";
|
|
362
|
+
function resolveAuthMode(config, locationHref) {
|
|
363
|
+
return isStudioConfig(config) ? "studio" : detectDashboardContext(locationHref) ? "dashboard" : "standalone";
|
|
364
|
+
}
|
|
365
|
+
function isStudioConfig(config) {
|
|
366
|
+
return !!config.studio || !!config.studioMode?.enabled;
|
|
367
|
+
}
|
|
368
|
+
function detectDashboardContext(locationHref) {
|
|
369
|
+
try {
|
|
370
|
+
const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
|
|
371
|
+
if (!contextParam) return !1;
|
|
372
|
+
const parsed = JSON.parse(contextParam);
|
|
373
|
+
return typeof parsed == "object" && parsed !== null && !Array.isArray(parsed) && Object.keys(parsed).length > 0;
|
|
374
|
+
} catch (err) {
|
|
375
|
+
return console.error("Failed to parse dashboard context from initial location:", err), !1;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
340
378
|
var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
|
|
341
|
-
const
|
|
379
|
+
const REFRESH_INTERVAL = 720 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
|
|
342
380
|
function getLastRefreshTime(storageArea, storageKey) {
|
|
343
381
|
try {
|
|
344
382
|
const data = storageArea?.getItem(`${storageKey}_last_refresh`), parsed = data ? parseInt(data, 10) : 0;
|
|
@@ -501,6 +539,47 @@ const refreshStampedToken = ({ state }) => {
|
|
|
501
539
|
state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
|
|
502
540
|
}
|
|
503
541
|
});
|
|
542
|
+
}, subscribeToStateAndFetchCurrentUser = ({ state, instance }, fetchOptions) => {
|
|
543
|
+
const { clientFactory, apiHost } = state.get().options, useProjectHostname = fetchOptions?.useProjectHostname ?? isStudioConfig(instance.config), projectId = instance.config.projectId;
|
|
544
|
+
return state.observable.pipe(
|
|
545
|
+
map(({ authState, options: storeOptions }) => ({
|
|
546
|
+
authState,
|
|
547
|
+
authMethod: storeOptions.authMethod
|
|
548
|
+
})),
|
|
549
|
+
filter(
|
|
550
|
+
(value) => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser
|
|
551
|
+
),
|
|
552
|
+
map((value) => ({ token: value.authState.token, authMethod: value.authMethod })),
|
|
553
|
+
distinctUntilChanged(
|
|
554
|
+
(prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod
|
|
555
|
+
)
|
|
556
|
+
).pipe(
|
|
557
|
+
map(
|
|
558
|
+
({ token, authMethod }) => clientFactory({
|
|
559
|
+
apiVersion: DEFAULT_API_VERSION$1,
|
|
560
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
561
|
+
token: authMethod === "cookie" ? void 0 : token,
|
|
562
|
+
ignoreBrowserTokenWarning: !0,
|
|
563
|
+
useProjectHostname,
|
|
564
|
+
useCdn: !1,
|
|
565
|
+
...authMethod === "cookie" ? { withCredentials: !0 } : {},
|
|
566
|
+
...useProjectHostname && projectId ? { projectId } : {},
|
|
567
|
+
...apiHost && { apiHost }
|
|
568
|
+
})
|
|
569
|
+
),
|
|
570
|
+
switchMap(
|
|
571
|
+
(client) => client.observable.request({ uri: "/users/me", method: "GET" })
|
|
572
|
+
)
|
|
573
|
+
).subscribe({
|
|
574
|
+
next: (currentUser) => {
|
|
575
|
+
state.set("setCurrentUser", (prev) => ({
|
|
576
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
|
|
577
|
+
}));
|
|
578
|
+
},
|
|
579
|
+
error: (error) => {
|
|
580
|
+
state.set("setError", { authState: { type: AuthStateType.ERROR, error } });
|
|
581
|
+
}
|
|
582
|
+
});
|
|
504
583
|
};
|
|
505
584
|
function getAuthCode(callbackUrl, locationHref) {
|
|
506
585
|
const loc = new URL(locationHref, DEFAULT_BASE), callbackLocation = callbackUrl ? new URL(callbackUrl, DEFAULT_BASE) : void 0, callbackLocationMatches = callbackLocation ? loc.pathname.toLowerCase().startsWith(callbackLocation.pathname.toLowerCase()) : !0;
|
|
@@ -575,66 +654,53 @@ function getClientErrorApiDescription(error) {
|
|
|
575
654
|
function isProjectUserNotFoundClientError(error) {
|
|
576
655
|
return getClientErrorApiType(error) === "projectUserNotFoundError";
|
|
577
656
|
}
|
|
578
|
-
|
|
579
|
-
if (!projectId) return !1;
|
|
657
|
+
function parseDashboardContext(locationHref) {
|
|
580
658
|
try {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
} catch {
|
|
590
|
-
return !1;
|
|
659
|
+
const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
|
|
660
|
+
if (contextParam) {
|
|
661
|
+
const parsedContext = JSON.parse(contextParam);
|
|
662
|
+
if (parsedContext && typeof parsedContext == "object" && !Array.isArray(parsedContext) && Object.keys(parsedContext).length > 0)
|
|
663
|
+
return delete parsedContext.sid, parsedContext;
|
|
664
|
+
}
|
|
665
|
+
} catch (err) {
|
|
666
|
+
console.error("Failed to parse dashboard context from initial location:", err);
|
|
591
667
|
}
|
|
668
|
+
return {};
|
|
669
|
+
}
|
|
670
|
+
function getDashboardInitialState(options) {
|
|
671
|
+
const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", dashboardContext = parseDashboardContext(initialLocationHref), storageArea = void 0;
|
|
672
|
+
return providedToken ? {
|
|
673
|
+
authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
|
|
674
|
+
storageKey,
|
|
675
|
+
storageArea,
|
|
676
|
+
authMethod: void 0,
|
|
677
|
+
dashboardContext
|
|
678
|
+
} : getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref) ? {
|
|
679
|
+
authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
|
|
680
|
+
storageKey,
|
|
681
|
+
storageArea,
|
|
682
|
+
authMethod: void 0,
|
|
683
|
+
dashboardContext
|
|
684
|
+
} : {
|
|
685
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
|
|
686
|
+
storageKey,
|
|
687
|
+
storageArea,
|
|
688
|
+
authMethod: void 0,
|
|
689
|
+
dashboardContext
|
|
690
|
+
};
|
|
592
691
|
}
|
|
593
|
-
function
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
const { clientFactory, apiHost } = state.get().options, useProjectHostname = !!instance.config.studioMode?.enabled, projectId = instance.config.projectId;
|
|
601
|
-
return state.observable.pipe(
|
|
602
|
-
map(({ authState, options }) => ({ authState, authMethod: options.authMethod })),
|
|
603
|
-
filter(
|
|
604
|
-
(value) => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser
|
|
605
|
-
),
|
|
606
|
-
map((value) => ({ token: value.authState.token, authMethod: value.authMethod })),
|
|
607
|
-
distinctUntilChanged(
|
|
608
|
-
(prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod
|
|
609
|
-
)
|
|
610
|
-
).pipe(
|
|
611
|
-
map(
|
|
612
|
-
({ token, authMethod }) => clientFactory({
|
|
613
|
-
apiVersion: DEFAULT_API_VERSION$1,
|
|
614
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
615
|
-
token: authMethod === "cookie" ? void 0 : token,
|
|
616
|
-
ignoreBrowserTokenWarning: !0,
|
|
617
|
-
useProjectHostname,
|
|
618
|
-
useCdn: !1,
|
|
619
|
-
...authMethod === "cookie" ? { withCredentials: !0 } : {},
|
|
620
|
-
...useProjectHostname && projectId ? { projectId } : {},
|
|
621
|
-
...apiHost && { apiHost }
|
|
622
|
-
})
|
|
623
|
-
),
|
|
624
|
-
switchMap(
|
|
625
|
-
(client) => client.observable.request({ uri: "/users/me", method: "GET" })
|
|
626
|
-
)
|
|
627
|
-
).subscribe({
|
|
628
|
-
next: (currentUser) => {
|
|
629
|
-
state.set("setCurrentUser", (prev) => ({
|
|
630
|
-
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
|
|
631
|
-
}));
|
|
692
|
+
function initializeDashboardAuth(context, tokenRefresherRunning2) {
|
|
693
|
+
const subscriptions = [];
|
|
694
|
+
let startedRefresher = !1;
|
|
695
|
+
return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
|
|
696
|
+
dispose: () => {
|
|
697
|
+
for (const subscription of subscriptions)
|
|
698
|
+
subscription.unsubscribe();
|
|
632
699
|
},
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}, subscribeToStorageEventsAndSetToken = ({
|
|
700
|
+
tokenRefresherStarted: startedRefresher
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const subscribeToStorageEventsAndSetToken = ({
|
|
638
704
|
state
|
|
639
705
|
}) => {
|
|
640
706
|
const { storageArea, storageKey } = state.get().options;
|
|
@@ -650,6 +716,159 @@ const subscribeToStateAndFetchCurrentUser = ({
|
|
|
650
716
|
});
|
|
651
717
|
});
|
|
652
718
|
};
|
|
719
|
+
function getStandaloneInitialState(options) {
|
|
720
|
+
const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", storageArea = authConfig.storageArea ?? getDefaultStorage();
|
|
721
|
+
if (providedToken)
|
|
722
|
+
return {
|
|
723
|
+
authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
|
|
724
|
+
storageKey,
|
|
725
|
+
storageArea,
|
|
726
|
+
authMethod: void 0,
|
|
727
|
+
dashboardContext: {}
|
|
728
|
+
};
|
|
729
|
+
if (getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref))
|
|
730
|
+
return {
|
|
731
|
+
authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
|
|
732
|
+
storageKey,
|
|
733
|
+
storageArea,
|
|
734
|
+
authMethod: void 0,
|
|
735
|
+
dashboardContext: {}
|
|
736
|
+
};
|
|
737
|
+
const token = getTokenFromStorage(storageArea, storageKey);
|
|
738
|
+
return token ? {
|
|
739
|
+
authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null },
|
|
740
|
+
storageKey,
|
|
741
|
+
storageArea,
|
|
742
|
+
authMethod: "localstorage",
|
|
743
|
+
dashboardContext: {}
|
|
744
|
+
} : {
|
|
745
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
|
|
746
|
+
storageKey,
|
|
747
|
+
storageArea,
|
|
748
|
+
authMethod: void 0,
|
|
749
|
+
dashboardContext: {}
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function initializeStandaloneAuth(context, tokenRefresherRunning2) {
|
|
753
|
+
const subscriptions = [];
|
|
754
|
+
let startedRefresher = !1;
|
|
755
|
+
return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context)), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
|
|
756
|
+
dispose: () => {
|
|
757
|
+
for (const subscription of subscriptions)
|
|
758
|
+
subscription.unsubscribe();
|
|
759
|
+
},
|
|
760
|
+
tokenRefresherStarted: startedRefresher
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
const COOKIE_AUTH_TIMEOUT_MS = 1e4;
|
|
764
|
+
async function checkForCookieAuth(projectId, clientFactory) {
|
|
765
|
+
if (!projectId) return !1;
|
|
766
|
+
try {
|
|
767
|
+
const user = await clientFactory({
|
|
768
|
+
projectId,
|
|
769
|
+
useCdn: !1,
|
|
770
|
+
requestTagPrefix: "sdk",
|
|
771
|
+
timeout: COOKIE_AUTH_TIMEOUT_MS
|
|
772
|
+
}).request({
|
|
773
|
+
uri: "/users/me",
|
|
774
|
+
withCredentials: !0,
|
|
775
|
+
tag: "users.get-current"
|
|
776
|
+
});
|
|
777
|
+
return user != null && typeof user == "object" && typeof user.id == "string";
|
|
778
|
+
} catch {
|
|
779
|
+
return !1;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function getStudioTokenFromLocalStorage(storageArea, storageKey) {
|
|
783
|
+
return !storageArea || !storageKey ? null : getTokenFromStorage(storageArea, storageKey) || null;
|
|
784
|
+
}
|
|
785
|
+
function getStudioInitialState(options) {
|
|
786
|
+
const { authConfig, projectId, tokenSource } = options, storageArea = authConfig.storageArea ?? getDefaultStorage(), studioStorageKey = `__studio_auth_token_${projectId ?? ""}`;
|
|
787
|
+
if (tokenSource)
|
|
788
|
+
return {
|
|
789
|
+
authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
|
|
790
|
+
storageKey: studioStorageKey,
|
|
791
|
+
storageArea,
|
|
792
|
+
authMethod: void 0,
|
|
793
|
+
dashboardContext: {}
|
|
794
|
+
};
|
|
795
|
+
const providedToken = authConfig.token;
|
|
796
|
+
let authMethod;
|
|
797
|
+
const token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey);
|
|
798
|
+
return token && (authMethod = "localstorage"), providedToken ? {
|
|
799
|
+
authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
|
|
800
|
+
storageKey: studioStorageKey,
|
|
801
|
+
storageArea,
|
|
802
|
+
authMethod,
|
|
803
|
+
dashboardContext: {}
|
|
804
|
+
} : token ? {
|
|
805
|
+
authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null },
|
|
806
|
+
storageKey: studioStorageKey,
|
|
807
|
+
storageArea,
|
|
808
|
+
authMethod: "localstorage",
|
|
809
|
+
dashboardContext: {}
|
|
810
|
+
} : {
|
|
811
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
|
|
812
|
+
storageKey: studioStorageKey,
|
|
813
|
+
storageArea,
|
|
814
|
+
authMethod: void 0,
|
|
815
|
+
dashboardContext: {}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function initializeStudioAuth(context, tokenRefresherRunning2) {
|
|
819
|
+
const tokenSource = context.instance.config.studio?.auth?.token;
|
|
820
|
+
return tokenSource ? initializeWithTokenSource(context, tokenSource) : initializeWithFallback(context, tokenRefresherRunning2);
|
|
821
|
+
}
|
|
822
|
+
function initializeWithTokenSource(context, tokenSource) {
|
|
823
|
+
const subscriptions = [];
|
|
824
|
+
subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 }));
|
|
825
|
+
const tokenSub = tokenSource.subscribe({
|
|
826
|
+
next: (token) => {
|
|
827
|
+
const { state } = context;
|
|
828
|
+
token ? state.set("studioTokenSource", (prev) => ({
|
|
829
|
+
options: { ...prev.options, authMethod: void 0 },
|
|
830
|
+
authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null }
|
|
831
|
+
})) : state.set("studioTokenSourceLoggedOut", (prev) => ({
|
|
832
|
+
options: { ...prev.options, authMethod: void 0 },
|
|
833
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
|
|
834
|
+
}));
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
return {
|
|
838
|
+
dispose: () => {
|
|
839
|
+
tokenSub.unsubscribe();
|
|
840
|
+
for (const subscription of subscriptions)
|
|
841
|
+
subscription.unsubscribe();
|
|
842
|
+
},
|
|
843
|
+
// Studio handles token refresh — do not start the SDK's refresher
|
|
844
|
+
tokenRefresherStarted: !1
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function initializeWithFallback(context, tokenRefresherRunning2) {
|
|
848
|
+
const subscriptions = [];
|
|
849
|
+
let startedRefresher = !1;
|
|
850
|
+
subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context));
|
|
851
|
+
try {
|
|
852
|
+
const { instance, state } = context;
|
|
853
|
+
if (!(state.get().authState?.type === AuthStateType.LOGGED_IN && state.get().authState.token)) {
|
|
854
|
+
const projectIdValue = instance.config.projectId, clientFactory = state.get().options.clientFactory;
|
|
855
|
+
checkForCookieAuth(projectIdValue, clientFactory).then((isCookieAuthEnabled) => {
|
|
856
|
+
isCookieAuthEnabled && state.set("enableCookieAuth", (prev) => ({
|
|
857
|
+
options: { ...prev.options, authMethod: "cookie" },
|
|
858
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? prev.authState : { type: AuthStateType.LOGGED_IN, token: "", currentUser: null }
|
|
859
|
+
}));
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
} catch {
|
|
863
|
+
}
|
|
864
|
+
return tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
|
|
865
|
+
dispose: () => {
|
|
866
|
+
for (const subscription of subscriptions)
|
|
867
|
+
subscription.unsubscribe();
|
|
868
|
+
},
|
|
869
|
+
tokenRefresherStarted: startedRefresher
|
|
870
|
+
};
|
|
871
|
+
}
|
|
653
872
|
let tokenRefresherRunning = !1;
|
|
654
873
|
const authStore = {
|
|
655
874
|
name: "Auth",
|
|
@@ -661,9 +880,7 @@ const authStore = {
|
|
|
661
880
|
token: providedToken,
|
|
662
881
|
clientFactory = createClient,
|
|
663
882
|
initialLocationHref = getDefaultLocation()
|
|
664
|
-
} = instance.config.auth ?? {};
|
|
665
|
-
let storageArea = instance.config.auth?.storageArea, storageKey = "__sanity_auth_token";
|
|
666
|
-
const studioModeEnabled = instance.config.studioMode?.enabled;
|
|
883
|
+
} = instance.config.auth ?? {}, authConfig = instance.config.auth ?? {};
|
|
667
884
|
let loginDomain = "https://www.sanity.io";
|
|
668
885
|
try {
|
|
669
886
|
apiHost && new URL(apiHost).hostname.endsWith(".sanity.work") && (loginDomain = "https://www.sanity.work");
|
|
@@ -671,27 +888,27 @@ const authStore = {
|
|
|
671
888
|
}
|
|
672
889
|
const loginUrl = new URL("/login", loginDomain);
|
|
673
890
|
loginUrl.searchParams.set("origin", getCleanedUrl(initialLocationHref)), loginUrl.searchParams.set("type", "stampedToken"), loginUrl.searchParams.set("withSid", "true");
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
891
|
+
const mode = resolveAuthMode(instance.config, initialLocationHref), strategyOptions = {
|
|
892
|
+
authConfig,
|
|
893
|
+
projectId: instance.config.projectId,
|
|
894
|
+
initialLocationHref,
|
|
895
|
+
tokenSource: instance.config.studio?.auth?.token
|
|
896
|
+
};
|
|
897
|
+
let result;
|
|
898
|
+
switch (mode) {
|
|
899
|
+
case "studio":
|
|
900
|
+
result = getStudioInitialState(strategyOptions);
|
|
901
|
+
break;
|
|
902
|
+
case "dashboard":
|
|
903
|
+
result = getDashboardInitialState(strategyOptions);
|
|
904
|
+
break;
|
|
905
|
+
case "standalone":
|
|
906
|
+
result = getStandaloneInitialState(strategyOptions);
|
|
907
|
+
break;
|
|
683
908
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const studioStorageKey = `__studio_auth_token_${instance.config.projectId ?? ""}`;
|
|
688
|
-
storageKey = studioStorageKey, token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey), token && (authMethod = "localstorage");
|
|
689
|
-
} else
|
|
690
|
-
token = getTokenFromStorage(storageArea, storageKey), token && (authMethod = "localstorage");
|
|
691
|
-
let authState;
|
|
692
|
-
return providedToken ? authState = { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null } : token && studioModeEnabled ? authState = { type: AuthStateType.LOGGED_IN, token: token ?? "", currentUser: null } : getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref) ? authState = { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 } : token && !isInDashboard && !studioModeEnabled ? authState = { type: AuthStateType.LOGGED_IN, token, currentUser: null } : authState = { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }, {
|
|
693
|
-
authState,
|
|
694
|
-
dashboardContext,
|
|
909
|
+
return {
|
|
910
|
+
authState: result.authState,
|
|
911
|
+
dashboardContext: result.dashboardContext,
|
|
695
912
|
options: {
|
|
696
913
|
apiHost,
|
|
697
914
|
loginUrl: loginUrl.toString(),
|
|
@@ -700,32 +917,27 @@ const authStore = {
|
|
|
700
917
|
providedToken,
|
|
701
918
|
clientFactory,
|
|
702
919
|
initialLocationHref,
|
|
703
|
-
storageKey,
|
|
704
|
-
storageArea,
|
|
705
|
-
authMethod
|
|
920
|
+
storageKey: result.storageKey,
|
|
921
|
+
storageArea: result.storageArea,
|
|
922
|
+
authMethod: result.authMethod
|
|
706
923
|
}
|
|
707
924
|
};
|
|
708
925
|
},
|
|
709
926
|
initialize(context) {
|
|
710
|
-
const
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
} catch {
|
|
927
|
+
const initialLocationHref = context.state.get().options?.initialLocationHref ?? getDefaultLocation(), mode = resolveAuthMode(context.instance.config, initialLocationHref);
|
|
928
|
+
let initResult;
|
|
929
|
+
switch (mode) {
|
|
930
|
+
case "studio":
|
|
931
|
+
initResult = initializeStudioAuth(context, tokenRefresherRunning);
|
|
932
|
+
break;
|
|
933
|
+
case "dashboard":
|
|
934
|
+
initResult = initializeDashboardAuth(context, tokenRefresherRunning);
|
|
935
|
+
break;
|
|
936
|
+
case "standalone":
|
|
937
|
+
initResult = initializeStandaloneAuth(context, tokenRefresherRunning);
|
|
938
|
+
break;
|
|
724
939
|
}
|
|
725
|
-
return
|
|
726
|
-
for (const subscription of subscriptions)
|
|
727
|
-
subscription.unsubscribe();
|
|
728
|
-
};
|
|
940
|
+
return initResult.tokenRefresherStarted && (tokenRefresherRunning = !0), initResult.dispose;
|
|
729
941
|
}
|
|
730
942
|
}, getCurrentUserState = bindActionGlobally(
|
|
731
943
|
authStore,
|
|
@@ -1786,7 +1998,7 @@ function sortListenerEvents(options) {
|
|
|
1786
1998
|
mergeMap((state) => of(...state.emitEvents))
|
|
1787
1999
|
);
|
|
1788
2000
|
}
|
|
1789
|
-
const listen
|
|
2001
|
+
const listen = ({ state }, documentId) => {
|
|
1790
2002
|
const { sharedListener, fetchDocument } = state.get();
|
|
1791
2003
|
return sharedListener.events.pipe(
|
|
1792
2004
|
concatMap((e) => e.type === "welcome" ? fetchDocument(documentId).pipe(
|
|
@@ -2940,9 +3152,9 @@ const _resolveDocument = bindActionByDataset(
|
|
|
2940
3152
|
groupBy$1((i) => i.id),
|
|
2941
3153
|
mergeMap$1(
|
|
2942
3154
|
(group) => group.pipe(
|
|
2943
|
-
switchMap((e) => e.add ? listen
|
|
3155
|
+
switchMap((e) => e.add ? listen(context, e.id).pipe(
|
|
2944
3156
|
catchError$1((error) => {
|
|
2945
|
-
throw error instanceof OutOfSyncError && listen
|
|
3157
|
+
throw error instanceof OutOfSyncError && listen(context, e.id), error;
|
|
2946
3158
|
}),
|
|
2947
3159
|
tap$1(
|
|
2948
3160
|
(remote) => state.set(
|
|
@@ -3423,40 +3635,7 @@ const handleIncomingMessage = (event) => {
|
|
|
3423
3635
|
return () => subscription.unsubscribe();
|
|
3424
3636
|
}
|
|
3425
3637
|
})
|
|
3426
|
-
), fetch = (client, query, params, options) => defer(
|
|
3427
|
-
() => client.observable.fetch(query, params, {
|
|
3428
|
-
tag: options.tag,
|
|
3429
|
-
filterResponse: !0
|
|
3430
|
-
})
|
|
3431
|
-
), listen = (client, query, params, options) => defer(
|
|
3432
|
-
() => client.listen(query, params, {
|
|
3433
|
-
events: ["welcome", "mutation", "reconnect"],
|
|
3434
|
-
includeResult: !1,
|
|
3435
|
-
visibility: "query",
|
|
3436
|
-
tag: options.tag
|
|
3437
|
-
})
|
|
3438
3638
|
);
|
|
3439
|
-
function isWelcomeEvent(event) {
|
|
3440
|
-
return event.type === "welcome";
|
|
3441
|
-
}
|
|
3442
|
-
const listenQuery = (client, query, params = {}, options = {}) => {
|
|
3443
|
-
const fetchQuery = query, listenerQuery = query, fetchOnce$ = fetch(client, fetchQuery, params, options), events$ = listen(client, listenerQuery, params, options).pipe(
|
|
3444
|
-
mergeMap((ev, i) => i === 0 && !isWelcomeEvent(ev) ? throwError(
|
|
3445
|
-
() => new Error(
|
|
3446
|
-
ev.type === "reconnect" ? "Could not establish EventSource connection" : `Received unexpected type of first event "${ev.type}"`
|
|
3447
|
-
)
|
|
3448
|
-
) : of(ev)),
|
|
3449
|
-
share$1()
|
|
3450
|
-
), [welcome$, mutationAndReconnect$] = partition(events$, isWelcomeEvent), isRelevantEvent = (event) => !options.transitions || event.type !== "mutation" ? !0 : options.transitions.includes(event.transition);
|
|
3451
|
-
return merge(
|
|
3452
|
-
welcome$.pipe(take(1)),
|
|
3453
|
-
mutationAndReconnect$.pipe(filter$1(isRelevantEvent), debounceTime(options.throttleTime || 1e3))
|
|
3454
|
-
).pipe(
|
|
3455
|
-
// will cancel any in-flight request when a new one comes in
|
|
3456
|
-
// but ensures we always get the latest data
|
|
3457
|
-
switchMap(() => fetchOnce$)
|
|
3458
|
-
);
|
|
3459
|
-
};
|
|
3460
3639
|
function sortReleases(releases = []) {
|
|
3461
3640
|
return [...releases].sort((a, b) => {
|
|
3462
3641
|
if (a.metadata.releaseType === "undecided" && b.metadata.releaseType !== "undecided")
|
|
@@ -3475,7 +3654,7 @@ function sortReleases(releases = []) {
|
|
|
3475
3654
|
return a.metadata.releaseType === "asap" && b.metadata.releaseType !== "asap" ? 1 : a.metadata.releaseType !== "asap" && b.metadata.releaseType === "asap" ? -1 : a.metadata.releaseType === "asap" && b.metadata.releaseType === "asap" ? new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime() : 0;
|
|
3476
3655
|
});
|
|
3477
3656
|
}
|
|
3478
|
-
const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
|
|
3657
|
+
const ARCHIVED_RELEASE_STATES = ["archived", "published"], STABLE_EMPTY_RELEASES = [], releasesStore = {
|
|
3479
3658
|
name: "Releases",
|
|
3480
3659
|
getInitialState: () => ({
|
|
3481
3660
|
activeReleases: void 0
|
|
@@ -3489,43 +3668,26 @@ const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
|
|
|
3489
3668
|
createStateSourceAction({
|
|
3490
3669
|
selector: ({ state }, _) => state.activeReleases
|
|
3491
3670
|
})
|
|
3492
|
-
), RELEASES_QUERY = "releases::all()",
|
|
3671
|
+
), RELEASES_QUERY = "releases::all()", subscribeToReleases = ({
|
|
3493
3672
|
instance,
|
|
3494
3673
|
state,
|
|
3495
3674
|
key: { projectId, dataset }
|
|
3496
|
-
}) =>
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
delay: (error, retryCount) => (console.error("[releases] Error in subscription:", error, "Retry count:", retryCount), timer(Math.min(1e3 * Math.pow(2, retryCount), 1e4)))
|
|
3513
|
-
}),
|
|
3514
|
-
catchError$1((error) => (state.set("setError", { error }), EMPTY))
|
|
3515
|
-
)
|
|
3516
|
-
)
|
|
3517
|
-
)
|
|
3518
|
-
).subscribe({
|
|
3519
|
-
next: (releases) => {
|
|
3520
|
-
state.set("setActiveReleases", {
|
|
3521
|
-
activeReleases: sortReleases(releases ?? []).filter((release) => !ARCHIVED_RELEASE_STATES.includes(release.state)).reverse()
|
|
3522
|
-
});
|
|
3523
|
-
}
|
|
3524
|
-
});
|
|
3525
|
-
function isReleasePerspective(perspective) {
|
|
3526
|
-
return typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
|
|
3527
|
-
}
|
|
3528
|
-
const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
|
|
3675
|
+
}) => {
|
|
3676
|
+
const { observable: releases$ } = getQueryState(instance, {
|
|
3677
|
+
query: RELEASES_QUERY,
|
|
3678
|
+
perspective: "raw",
|
|
3679
|
+
projectId,
|
|
3680
|
+
dataset,
|
|
3681
|
+
tag: "releases"
|
|
3682
|
+
});
|
|
3683
|
+
return releases$.pipe(
|
|
3684
|
+
map((releases) => {
|
|
3685
|
+
state.set("setActiveReleases", {
|
|
3686
|
+
activeReleases: sortReleases(releases ?? STABLE_EMPTY_RELEASES).filter((release) => !ARCHIVED_RELEASE_STATES.includes(release.state)).reverse()
|
|
3687
|
+
});
|
|
3688
|
+
})
|
|
3689
|
+
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
3690
|
+
}, DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
|
|
3529
3691
|
[selectActiveReleases, selectOptions],
|
|
3530
3692
|
(activeReleases, options) => {
|
|
3531
3693
|
if (!options || !activeReleases) return options;
|
|
@@ -3536,25 +3698,25 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
|
|
|
3536
3698
|
let cachedOptions = nestedCache.get(optionsKey);
|
|
3537
3699
|
return cachedOptions || (cachedOptions = options, nestedCache.set(optionsKey, cachedOptions)), cachedOptions;
|
|
3538
3700
|
}
|
|
3539
|
-
),
|
|
3701
|
+
), _getPerspectiveStateSelector = createStateSourceAction({
|
|
3702
|
+
selector: createSelector(
|
|
3703
|
+
[selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],
|
|
3704
|
+
(instancePerspective, activeReleases, memoizedOptions) => {
|
|
3705
|
+
const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE;
|
|
3706
|
+
if (!isReleasePerspective(perspective)) return perspective;
|
|
3707
|
+
if (!activeReleases || activeReleases.length === 0) return;
|
|
3708
|
+
const releaseNames = sortReleases(activeReleases).map((release) => release.name), index = releaseNames.findIndex((name) => name === perspective.releaseName);
|
|
3709
|
+
if (index < 0)
|
|
3710
|
+
throw new Error(`Release "${perspective.releaseName}" not found in active releases`);
|
|
3711
|
+
return ["drafts", ...releaseNames.slice(0, index + 1)].filter((name) => !perspective.excludedPerspectives?.includes(name)).reverse();
|
|
3712
|
+
}
|
|
3713
|
+
)
|
|
3714
|
+
});
|
|
3715
|
+
let _boundGetPerspectiveState;
|
|
3716
|
+
const getPerspectiveState = (...args) => (_boundGetPerspectiveState || (_boundGetPerspectiveState = bindActionByDataset(
|
|
3540
3717
|
releasesStore,
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
[selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],
|
|
3544
|
-
(instancePerspective, activeReleases, memoizedOptions) => {
|
|
3545
|
-
const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE;
|
|
3546
|
-
if (!isReleasePerspective(perspective)) return perspective;
|
|
3547
|
-
if (!activeReleases || activeReleases.length === 0) return;
|
|
3548
|
-
const releaseNames = sortReleases(activeReleases).map((release) => release.name), index = releaseNames.findIndex((name) => name === perspective.releaseName);
|
|
3549
|
-
if (index < 0)
|
|
3550
|
-
throw new Error(`Release "${perspective.releaseName}" not found in active releases`);
|
|
3551
|
-
return ["drafts", ...releaseNames.slice(0, index + 1)].filter(
|
|
3552
|
-
(name) => !perspective.excludedPerspectives?.includes(name)
|
|
3553
|
-
);
|
|
3554
|
-
}
|
|
3555
|
-
)
|
|
3556
|
-
})
|
|
3557
|
-
), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", QUERY_STORE_DEFAULT_PERSPECTIVE = "drafts", setQueryError = (key, error) => (prev) => {
|
|
3718
|
+
_getPerspectiveStateSelector
|
|
3719
|
+
)), _boundGetPerspectiveState(...args)), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", QUERY_STORE_DEFAULT_PERSPECTIVE = "drafts", setQueryError = (key, error) => (prev) => {
|
|
3558
3720
|
const prevQuery = prev.queries[key];
|
|
3559
3721
|
return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
|
|
3560
3722
|
}, setQueryData = (key, result, syncTags) => (prev) => {
|
|
@@ -3628,17 +3790,21 @@ const queryStore = {
|
|
|
3628
3790
|
source,
|
|
3629
3791
|
perspective: perspectiveFromOptions,
|
|
3630
3792
|
...restOptions
|
|
3631
|
-
} = parseQueryKey(group$.key), perspective$ = getPerspectiveState(instance, {
|
|
3793
|
+
} = parseQueryKey(group$.key), perspective$ = isReleasePerspective(perspectiveFromOptions) ? getPerspectiveState(instance, {
|
|
3632
3794
|
perspective: perspectiveFromOptions
|
|
3633
|
-
}).observable.pipe(filter(Boolean)), client$ = getClientState(instance, {
|
|
3795
|
+
}).observable.pipe(filter(Boolean)) : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE), client$ = getClientState(instance, {
|
|
3634
3796
|
apiVersion: QUERY_STORE_API_VERSION,
|
|
3635
3797
|
projectId,
|
|
3636
3798
|
dataset,
|
|
3637
3799
|
source
|
|
3638
3800
|
}).observable;
|
|
3639
|
-
return combineLatest(
|
|
3801
|
+
return combineLatest({
|
|
3802
|
+
lastLiveEventId: lastLiveEventId$,
|
|
3803
|
+
client: client$,
|
|
3804
|
+
perspective: perspective$
|
|
3805
|
+
}).pipe(
|
|
3640
3806
|
switchMap(
|
|
3641
|
-
(
|
|
3807
|
+
({ lastLiveEventId, client, perspective }) => client.observable.fetch(query, params, {
|
|
3642
3808
|
...restOptions,
|
|
3643
3809
|
perspective,
|
|
3644
3810
|
filterResponse: !1,
|
|
@@ -3657,10 +3823,13 @@ const queryStore = {
|
|
|
3657
3823
|
)
|
|
3658
3824
|
).subscribe({ error: errorHandler(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
|
|
3659
3825
|
state,
|
|
3660
|
-
instance
|
|
3826
|
+
instance,
|
|
3827
|
+
key: { source }
|
|
3661
3828
|
}) => {
|
|
3662
3829
|
const liveMessages$ = getClientState(instance, {
|
|
3663
|
-
apiVersion: QUERY_STORE_API_VERSION
|
|
3830
|
+
apiVersion: QUERY_STORE_API_VERSION,
|
|
3831
|
+
// temporary guard here until we're ready for everything to be queried via global api
|
|
3832
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
3664
3833
|
}).observable.pipe(
|
|
3665
3834
|
switchMap(
|
|
3666
3835
|
(client) => defer(
|
|
@@ -3850,7 +4019,7 @@ const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size &&
|
|
|
3850
4019
|
}) => state.observable.pipe(
|
|
3851
4020
|
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
3852
4021
|
distinctUntilChanged(isSetEqual$1),
|
|
3853
|
-
debounceTime
|
|
4022
|
+
debounceTime(BATCH_DEBOUNCE_TIME$1),
|
|
3854
4023
|
startWith$1(/* @__PURE__ */ new Set()),
|
|
3855
4024
|
pairwise$1(),
|
|
3856
4025
|
tap$1(([prevIds, currIds]) => {
|
|
@@ -3949,7 +4118,7 @@ const _getPreviewState = bindActionByDataset(
|
|
|
3949
4118
|
), resolvePreview = bindActionByDataset(
|
|
3950
4119
|
previewStore,
|
|
3951
4120
|
({ instance }, docHandle) => firstValueFrom(getPreviewState(instance, docHandle).observable.pipe(filter((i) => !!i.data)))
|
|
3952
|
-
), PROJECTION_TAG = "projection",
|
|
4121
|
+
), PROJECTION_TAG = "projection", PROJECTION_STATE_CLEAR_DELAY = 1e3, STABLE_EMPTY_PROJECTION = {
|
|
3953
4122
|
data: null,
|
|
3954
4123
|
isPending: !1
|
|
3955
4124
|
};
|
|
@@ -3973,20 +4142,21 @@ function createProjectionQuery(documentIds, documentProjections) {
|
|
|
3973
4142
|
return obj.documentIds.add(documentId), acc[projectionHash] = obj, acc;
|
|
3974
4143
|
}, {}), query = `[${Object.entries(projections).map(([projectionHash, { projection }]) => `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"__projectionHash":"${projectionHash}","result":{...${projection}}}`).join(",")}]`, params = Object.fromEntries(
|
|
3975
4144
|
Object.entries(projections).map(([projectionHash, value]) => {
|
|
3976
|
-
const idsInProjection = Array.from(value.documentIds).flatMap((id) =>
|
|
3977
|
-
getPublishedId(id),
|
|
3978
|
-
getDraftId(id)
|
|
3979
|
-
]);
|
|
4145
|
+
const idsInProjection = Array.from(value.documentIds).flatMap((id) => DocumentId(id));
|
|
3980
4146
|
return [`__ids_${projectionHash}`, Array.from(idsInProjection)];
|
|
3981
4147
|
})
|
|
3982
4148
|
);
|
|
3983
4149
|
return { query, params };
|
|
3984
4150
|
}
|
|
3985
|
-
function processProjectionQuery({
|
|
4151
|
+
function processProjectionQuery({
|
|
4152
|
+
ids,
|
|
4153
|
+
results,
|
|
4154
|
+
documentStatuses
|
|
4155
|
+
}) {
|
|
3986
4156
|
const groupedResults = {};
|
|
3987
4157
|
for (const result of results) {
|
|
3988
|
-
const originalId = getPublishedId(result._id), hash = result.__projectionHash
|
|
3989
|
-
ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] =
|
|
4158
|
+
const originalId = getPublishedId(result._id), hash = result.__projectionHash;
|
|
4159
|
+
ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] = void 0), groupedResults[originalId][hash] = result);
|
|
3990
4160
|
}
|
|
3991
4161
|
const finalValues = {};
|
|
3992
4162
|
for (const originalId of ids) {
|
|
@@ -3994,27 +4164,40 @@ function processProjectionQuery({ ids, results }) {
|
|
|
3994
4164
|
const projectionsForDoc = groupedResults[originalId];
|
|
3995
4165
|
if (projectionsForDoc)
|
|
3996
4166
|
for (const hash in projectionsForDoc) {
|
|
3997
|
-
const
|
|
4167
|
+
const projectionResultData = projectionsForDoc[hash]?.result;
|
|
3998
4168
|
if (!projectionResultData) {
|
|
3999
4169
|
finalValues[originalId][hash] = { data: null, isPending: !1 };
|
|
4000
4170
|
continue;
|
|
4001
4171
|
}
|
|
4002
|
-
const
|
|
4003
|
-
...draft?._updatedAt && { lastEditedDraftAt: draft._updatedAt },
|
|
4004
|
-
...published?._updatedAt && { lastEditedPublishedAt: published._updatedAt }
|
|
4005
|
-
};
|
|
4172
|
+
const statusFromStore = documentStatuses?.[originalId];
|
|
4006
4173
|
finalValues[originalId][hash] = {
|
|
4007
|
-
data: { ...projectionResultData, _status },
|
|
4174
|
+
data: { ...projectionResultData, _status: statusFromStore },
|
|
4008
4175
|
isPending: !1
|
|
4009
4176
|
};
|
|
4010
4177
|
}
|
|
4011
4178
|
}
|
|
4012
4179
|
return finalValues;
|
|
4013
4180
|
}
|
|
4181
|
+
function buildStatusQueryIds(documentIds, perspective) {
|
|
4182
|
+
const ids = [], releaseName = isReleasePerspective(perspective) ? perspective.releaseName : null;
|
|
4183
|
+
for (const id of documentIds) {
|
|
4184
|
+
const publishedId = getPublishedId$2(DocumentId(id)), draftId = getDraftId$1(publishedId);
|
|
4185
|
+
ids.push(draftId, publishedId), releaseName && ids.push(getVersionId(publishedId, releaseName));
|
|
4186
|
+
}
|
|
4187
|
+
return ids;
|
|
4188
|
+
}
|
|
4189
|
+
function processStatusQueryResults(results) {
|
|
4190
|
+
const documentStatuses = {};
|
|
4191
|
+
for (const result of results) {
|
|
4192
|
+
const id = DocumentId(result._id), updatedAt = result._updatedAt, publishedId = getPublishedId$2(id), statusData = documentStatuses[publishedId] ?? {};
|
|
4193
|
+
isDraftId(id) ? statusData.lastEditedDraftAt = updatedAt : isVersionId(id) ? statusData.lastEditedVersionAt = updatedAt : isPublishedId(id) && (statusData.lastEditedPublishedAt = updatedAt), documentStatuses[publishedId] = statusData;
|
|
4194
|
+
}
|
|
4195
|
+
return documentStatuses;
|
|
4196
|
+
}
|
|
4014
4197
|
const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Array.from(a).every((i) => b.has(i)), subscribeToStateAndFetchBatches = ({
|
|
4015
4198
|
state,
|
|
4016
4199
|
instance,
|
|
4017
|
-
key: {
|
|
4200
|
+
key: { source, perspective }
|
|
4018
4201
|
}) => {
|
|
4019
4202
|
const documentProjections$ = state.observable.pipe(
|
|
4020
4203
|
map((s) => s.documentProjections),
|
|
@@ -4023,7 +4206,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
4023
4206
|
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
4024
4207
|
distinctUntilChanged(isSetEqual)
|
|
4025
4208
|
), pendingUpdateSubscription = activeDocumentIds$.pipe(
|
|
4026
|
-
debounceTime
|
|
4209
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
4027
4210
|
startWith$1(/* @__PURE__ */ new Set()),
|
|
4028
4211
|
pairwise$1(),
|
|
4029
4212
|
tap$1(([prevIds, currIds]) => {
|
|
@@ -4047,42 +4230,82 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
4047
4230
|
});
|
|
4048
4231
|
})
|
|
4049
4232
|
).subscribe(), queryExecutionSubscription = combineLatest([activeDocumentIds$, documentProjections$]).pipe(
|
|
4050
|
-
debounceTime
|
|
4233
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
4051
4234
|
distinctUntilChanged(isEqual)
|
|
4052
4235
|
).pipe(
|
|
4053
4236
|
switchMap(([ids, documentProjections]) => {
|
|
4054
4237
|
if (!ids.size) return EMPTY;
|
|
4055
|
-
const { query, params } = createProjectionQuery(ids, documentProjections), controller = new AbortController()
|
|
4056
|
-
return new Observable((observer) => {
|
|
4238
|
+
const { query, params } = createProjectionQuery(ids, documentProjections), controller = new AbortController(), statusQueryIds = buildStatusQueryIds(ids, perspective), statusQuery = "*[_id in $statusIds]{_id, _updatedAt}", statusParams = { statusIds: statusQueryIds }, projectionQuery$ = new Observable((observer) => {
|
|
4057
4239
|
const { getCurrent, observable } = getQueryState(instance, {
|
|
4058
4240
|
query,
|
|
4059
4241
|
params,
|
|
4060
|
-
projectId,
|
|
4061
|
-
dataset,
|
|
4062
4242
|
tag: PROJECTION_TAG,
|
|
4063
|
-
perspective
|
|
4243
|
+
perspective,
|
|
4244
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4245
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4064
4246
|
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
4065
4247
|
resolveQuery(instance, {
|
|
4066
4248
|
query,
|
|
4067
4249
|
params,
|
|
4068
|
-
projectId,
|
|
4069
|
-
dataset,
|
|
4070
4250
|
tag: PROJECTION_TAG,
|
|
4071
|
-
|
|
4072
|
-
|
|
4251
|
+
signal: controller.signal,
|
|
4252
|
+
perspective,
|
|
4253
|
+
// temporary guard here until we're ready for everything to be queried via global API in v3
|
|
4254
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4073
4255
|
})
|
|
4074
4256
|
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
4075
4257
|
return () => {
|
|
4076
4258
|
controller.signal.aborted || controller.abort(), subscription.unsubscribe();
|
|
4077
4259
|
};
|
|
4078
|
-
})
|
|
4260
|
+
}), statusQuery$ = new Observable((observer) => {
|
|
4261
|
+
const { getCurrent, observable } = getQueryState(instance, {
|
|
4262
|
+
query: statusQuery,
|
|
4263
|
+
params: statusParams,
|
|
4264
|
+
tag: PROJECTION_TAG,
|
|
4265
|
+
perspective: "raw",
|
|
4266
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4267
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4268
|
+
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
4269
|
+
resolveQuery(instance, {
|
|
4270
|
+
query: statusQuery,
|
|
4271
|
+
params: statusParams,
|
|
4272
|
+
tag: PROJECTION_TAG,
|
|
4273
|
+
signal: controller.signal,
|
|
4274
|
+
perspective: "raw",
|
|
4275
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4276
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4277
|
+
})
|
|
4278
|
+
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
4279
|
+
return () => {
|
|
4280
|
+
subscription.unsubscribe();
|
|
4281
|
+
};
|
|
4282
|
+
});
|
|
4283
|
+
return combineLatest([projectionQuery$, statusQuery$]).pipe(
|
|
4284
|
+
filter(
|
|
4285
|
+
(pair) => pair[0] !== void 0 && pair[1] !== void 0
|
|
4286
|
+
),
|
|
4287
|
+
map(([projection, status]) => ({
|
|
4288
|
+
data: projection,
|
|
4289
|
+
ids,
|
|
4290
|
+
statusResults: status
|
|
4291
|
+
}))
|
|
4292
|
+
);
|
|
4079
4293
|
}),
|
|
4080
|
-
map(
|
|
4081
|
-
|
|
4294
|
+
map(({ ids, data, statusResults }) => {
|
|
4295
|
+
const documentStatuses = processStatusQueryResults(statusResults);
|
|
4296
|
+
state.set("updateStatuses", (prev) => ({
|
|
4297
|
+
documentStatuses: {
|
|
4298
|
+
...prev.documentStatuses,
|
|
4299
|
+
...documentStatuses
|
|
4300
|
+
}
|
|
4301
|
+
}));
|
|
4302
|
+
const currentState = state.get();
|
|
4303
|
+
return processProjectionQuery({
|
|
4082
4304
|
ids,
|
|
4083
|
-
results: data
|
|
4084
|
-
|
|
4085
|
-
|
|
4305
|
+
results: data,
|
|
4306
|
+
documentStatuses: currentState.documentStatuses
|
|
4307
|
+
});
|
|
4308
|
+
})
|
|
4086
4309
|
).subscribe({
|
|
4087
4310
|
next: (processedValues) => {
|
|
4088
4311
|
state.set("updateResult", (prev) => {
|
|
@@ -4108,7 +4331,8 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
4108
4331
|
return {
|
|
4109
4332
|
values: {},
|
|
4110
4333
|
documentProjections: {},
|
|
4111
|
-
subscriptions: {}
|
|
4334
|
+
subscriptions: {},
|
|
4335
|
+
documentStatuses: {}
|
|
4112
4336
|
};
|
|
4113
4337
|
},
|
|
4114
4338
|
initialize(context) {
|
|
@@ -4119,15 +4343,15 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
4119
4343
|
function getProjectionState(...args) {
|
|
4120
4344
|
return _getProjectionState(...args);
|
|
4121
4345
|
}
|
|
4122
|
-
const _getProjectionState =
|
|
4346
|
+
const _getProjectionState = bindActionBySourceAndPerspective(
|
|
4123
4347
|
projectionStore,
|
|
4124
4348
|
createStateSourceAction({
|
|
4125
4349
|
selector: ({ state }, options) => {
|
|
4126
|
-
const documentId = getPublishedId(options.documentId), projectionHash = hashString(options.projection);
|
|
4350
|
+
const documentId = getPublishedId$2(DocumentId(options.documentId)), projectionHash = hashString(options.projection);
|
|
4127
4351
|
return state.values[documentId]?.[projectionHash] ?? STABLE_EMPTY_PROJECTION;
|
|
4128
4352
|
},
|
|
4129
4353
|
onSubscribe: ({ state }, options) => {
|
|
4130
|
-
const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId(docHandle.documentId), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
4354
|
+
const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId$2(DocumentId(docHandle.documentId)), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
4131
4355
|
return state.set("addSubscription", (prev) => ({
|
|
4132
4356
|
documentProjections: {
|
|
4133
4357
|
...prev.documentProjections,
|
|
@@ -4179,7 +4403,7 @@ const _getProjectionState = bindActionByDataset(
|
|
|
4179
4403
|
function resolveProjection(...args) {
|
|
4180
4404
|
return _resolveProjection(...args);
|
|
4181
4405
|
}
|
|
4182
|
-
const _resolveProjection =
|
|
4406
|
+
const _resolveProjection = bindActionBySourceAndPerspective(
|
|
4183
4407
|
projectionStore,
|
|
4184
4408
|
({ instance }, options) => firstValueFrom(
|
|
4185
4409
|
getProjectionState(instance, options).observable.pipe(
|
|
@@ -4287,7 +4511,7 @@ function getCorsErrorProjectId(error) {
|
|
|
4287
4511
|
const projMatch = (error.message || "").match(/manage\/project\/([^/?#]+)/);
|
|
4288
4512
|
return projMatch ? projMatch[1] : null;
|
|
4289
4513
|
}
|
|
4290
|
-
var version = "2.
|
|
4514
|
+
var version = "2.7.0";
|
|
4291
4515
|
const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
|
|
4292
4516
|
export {
|
|
4293
4517
|
AuthStateType,
|
|
@@ -4351,6 +4575,7 @@ export {
|
|
|
4351
4575
|
isDatasetSource,
|
|
4352
4576
|
isMediaLibrarySource,
|
|
4353
4577
|
isProjectUserNotFoundClientError,
|
|
4578
|
+
isStudioConfig,
|
|
4354
4579
|
joinPaths,
|
|
4355
4580
|
jsonMatch2 as jsonMatch,
|
|
4356
4581
|
loadMoreUsers,
|