@sanity/sdk-react 3.0.0-rc.1 → 3.0.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/dashboard.d.ts +209 -0
- package/dist/_exports/dashboard.d.ts.map +1 -0
- package/dist/_exports/dashboard.js +278 -0
- package/dist/_exports/dashboard.js.map +1 -0
- package/dist/index.d.ts +2186 -2774
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3953 -1951
- package/dist/index.js.map +1 -1
- package/dist/useStudioWorkspacesByProjectIdDataset-I4S3CuR5.js +177 -0
- package/dist/useStudioWorkspacesByProjectIdDataset-I4S3CuR5.js.map +1 -0
- package/package.json +19 -19
- package/src/_exports/dashboard.ts +11 -0
- package/src/_exports/sdk-react.ts +11 -18
- package/src/components/SDKProvider.test.tsx +5 -5
- package/src/components/SanityApp.tsx +2 -3
- package/src/components/auth/AuthBoundary.test.tsx +1 -19
- package/src/components/auth/AuthBoundary.tsx +7 -6
- package/src/components/auth/LoginError.tsx +2 -3
- package/src/context/ComlinkTokenRefresh.tsx +3 -5
- package/src/context/{WorkbenchTokenRefresh.test.tsx → DashboardTokenRefresh.test.tsx} +26 -26
- package/src/context/{WorkbenchTokenRefresh.tsx → DashboardTokenRefresh.tsx} +14 -14
- package/src/context/OrganizationResourcesProvider.test.tsx +9 -9
- package/src/context/OrganizationResourcesProvider.tsx +2 -2
- package/src/context/ResourceProvider.test.tsx +21 -0
- package/src/context/ResourceProvider.tsx +4 -1
- package/src/context/{workbenchToken.ts → dashboardToken.ts} +13 -13
- package/src/hooks/agent/agentActions.test.tsx +1 -1
- package/src/hooks/agent/agentActions.ts +1 -1
- package/src/hooks/comlink/useFrameConnection.test.tsx +3 -2
- package/src/hooks/comlink/useFrameConnection.ts +1 -1
- package/src/hooks/comlink/useWindowConnection.test.tsx +4 -3
- package/src/hooks/comlink/useWindowConnection.ts +3 -4
- package/src/hooks/comments/useCommentActions.test.tsx +150 -0
- package/src/hooks/comments/useCommentActions.ts +109 -0
- package/src/hooks/comments/useCommentList.ts +79 -0
- package/src/hooks/comments/useCommentThreads.test.tsx +107 -0
- package/src/hooks/comments/useCommentThreads.ts +73 -0
- package/src/hooks/comments/useComments.test.tsx +242 -0
- package/src/hooks/comments/useComments.ts +59 -0
- package/src/hooks/context/useSanityInstance.test.tsx +2 -54
- package/src/hooks/context/useSanityInstance.ts +2 -24
- package/src/hooks/{agent → dashboard}/useAgentResourceContext.ts +2 -2
- package/src/hooks/dashboard/useFavorite.test.tsx +101 -0
- package/src/hooks/dashboard/useFavorite.ts +34 -0
- package/src/hooks/dashboard/useFavoriteContext.ts +61 -0
- package/src/hooks/dashboard/{useDashboardNavigate.test.ts → useNavigate.test.ts} +3 -3
- package/src/hooks/dashboard/{useDashboardNavigate.ts → useNavigate.ts} +5 -5
- package/src/hooks/dashboard/useNavigateToStudioDocument.ts +2 -1
- package/src/hooks/{auth/useDashboardOrganizationId.test.tsx → dashboard/useOrganizationId.test.tsx} +4 -4
- package/src/hooks/{auth/useDashboardOrganizationId.tsx → dashboard/useOrganizationId.tsx} +2 -2
- package/src/hooks/dashboard/useRecordDocumentHistoryEvent.ts +2 -1
- package/src/hooks/dashboard/useUpdateFavorite.test.tsx +146 -0
- package/src/hooks/dashboard/useUpdateFavorite.ts +74 -0
- package/src/hooks/dashboard/useWindowTitle.ts +1 -1
- package/src/hooks/datasets/useDatasets.test.tsx +29 -22
- package/src/hooks/datasets/useDatasets.ts +31 -53
- package/src/hooks/documents/useDocuments.ts +2 -7
- package/src/hooks/helpers/useNormalizedResourceOptions.test.tsx +0 -27
- package/src/hooks/helpers/useNormalizedResourceOptions.ts +14 -25
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +2 -7
- package/src/hooks/presence/usePresence.ts +14 -1
- package/src/hooks/presence/usePresenceForDocument.test.tsx +141 -0
- package/src/hooks/presence/usePresenceForDocument.ts +104 -0
- package/src/hooks/presence/useReportPresence.test.tsx +202 -0
- package/src/hooks/presence/useReportPresence.ts +170 -0
- package/src/hooks/preview/useDocumentPreview.tsx +2 -6
- package/src/hooks/projects/useProjects.ts +0 -8
- package/src/hooks/query/useQuery.ts +3 -8
- package/src/hooks/releases/useActiveReleases.ts +2 -2
- package/src/hooks/releases/useAllReleases.ts +2 -2
- package/src/hooks/users/useUser.ts +2 -8
- package/src/hooks/users/useUsers.ts +1 -2
- package/src/hooks/applications/useCreateUserApplication.test-d.ts +0 -14
- package/src/hooks/applications/useCreateUserApplication.ts +0 -11
- package/src/hooks/applications/useDeleteUserApplication.test-d.ts +0 -14
- package/src/hooks/applications/useDeleteUserApplication.ts +0 -11
- package/src/hooks/applications/useUpdateUserApplication.test-d.ts +0 -14
- package/src/hooks/applications/useUpdateUserApplication.ts +0 -11
- package/src/hooks/applications/useUserApplication.test-d.ts +0 -11
- package/src/hooks/applications/useUserApplication.ts +0 -14
- package/src/hooks/applications/useUserApplications.test-d.ts +0 -11
- package/src/hooks/applications/useUserApplications.ts +0 -14
- package/src/hooks/dashboard/useManageFavorite.test.tsx +0 -379
- package/src/hooks/dashboard/useManageFavorite.ts +0 -173
- /package/src/hooks/{agent → dashboard}/useAgentResourceContext.test.tsx +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { c } from "react-compiler-runtime";
|
|
2
|
+
import { getDashboardOrganizationId } from "@sanity/sdk";
|
|
3
|
+
import { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
|
|
5
|
+
import { getNodeState } from "@sanity/sdk/comlink";
|
|
6
|
+
import { filter, firstValueFrom } from "rxjs";
|
|
7
|
+
const SanityInstanceContext = createContext(null), useSanityInstance = () => {
|
|
8
|
+
let instance = useContext(SanityInstanceContext);
|
|
9
|
+
if (!instance) throw Error("SanityInstance context not found. Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.");
|
|
10
|
+
return instance;
|
|
11
|
+
};
|
|
12
|
+
function createStateSourceHook(options) {
|
|
13
|
+
let getState = typeof options == "function" ? options : options.getState, suspense = "shouldSuspend" in options && "suspender" in options ? options : void 0;
|
|
14
|
+
function useHook(...t0) {
|
|
15
|
+
let $ = c(3), params = t0, instance = useSanityInstance();
|
|
16
|
+
if (suspense?.suspender && suspense?.shouldSuspend?.(instance, ...params)) throw suspense.suspender(instance, ...params);
|
|
17
|
+
let t1;
|
|
18
|
+
$[0] !== instance || $[1] !== params ? (t1 = getState(instance, ...params), $[0] = instance, $[1] = params, $[2] = t1) : t1 = $[2];
|
|
19
|
+
let state = t1;
|
|
20
|
+
return useSyncExternalStore(state.subscribe, state.getCurrent);
|
|
21
|
+
}
|
|
22
|
+
return useHook;
|
|
23
|
+
}
|
|
24
|
+
const useNodeState = createStateSourceHook({
|
|
25
|
+
getState: getNodeState,
|
|
26
|
+
shouldSuspend: (instance, nodeInput) => getNodeState(instance, nodeInput).getCurrent() === void 0,
|
|
27
|
+
suspender: (instance, nodeInput) => firstValueFrom(getNodeState(instance, nodeInput).observable.pipe(filter(Boolean)))
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* @internal
|
|
31
|
+
* Hook to wrap a Comlink node in a React hook.
|
|
32
|
+
* Our store functionality takes care of the lifecycle of the node,
|
|
33
|
+
* as well as sharing a single node between invocations if they share the same name.
|
|
34
|
+
*
|
|
35
|
+
* Generally not to be used directly, but to be used as a dependency of
|
|
36
|
+
* Comlink-powered hooks like `useStudioWorkspacesByProjectIdDataset`.
|
|
37
|
+
*/
|
|
38
|
+
function useWindowConnection(t0) {
|
|
39
|
+
let $ = c(19), { name, connectTo, onMessage } = t0, t1;
|
|
40
|
+
$[0] !== connectTo || $[1] !== name ? (t1 = {
|
|
41
|
+
name,
|
|
42
|
+
connectTo
|
|
43
|
+
}, $[0] = connectTo, $[1] = name, $[2] = t1) : t1 = $[2];
|
|
44
|
+
let { node } = useNodeState(t1), t2;
|
|
45
|
+
$[3] === Symbol.for("react.memo_cache_sentinel") ? (t2 = [], $[3] = t2) : t2 = $[3];
|
|
46
|
+
let messageUnsubscribers = useRef(t2), instance = useSanityInstance(), t3;
|
|
47
|
+
$[4] !== node || $[5] !== onMessage ? (t3 = () => (onMessage && Object.entries(onMessage).forEach((t4) => {
|
|
48
|
+
let [type, handler] = t4, messageUnsubscribe = node.on(type, handler);
|
|
49
|
+
messageUnsubscribe && messageUnsubscribers.current.push(messageUnsubscribe);
|
|
50
|
+
}), () => {
|
|
51
|
+
messageUnsubscribers.current.forEach(_temp), messageUnsubscribers.current = [];
|
|
52
|
+
}), $[4] = node, $[5] = onMessage, $[6] = t3) : t3 = $[6];
|
|
53
|
+
let t4;
|
|
54
|
+
$[7] !== instance || $[8] !== name || $[9] !== node || $[10] !== onMessage ? (t4 = [
|
|
55
|
+
instance,
|
|
56
|
+
name,
|
|
57
|
+
onMessage,
|
|
58
|
+
node
|
|
59
|
+
], $[7] = instance, $[8] = name, $[9] = node, $[10] = onMessage, $[11] = t4) : t4 = $[11], useEffect(t3, t4);
|
|
60
|
+
let t5;
|
|
61
|
+
$[12] === node ? t5 = $[13] : (t5 = (type_0, data) => {
|
|
62
|
+
node.post(type_0, data);
|
|
63
|
+
}, $[12] = node, $[13] = t5);
|
|
64
|
+
let sendMessage = t5, t6;
|
|
65
|
+
$[14] === node ? t6 = $[15] : (t6 = (type_1, data_0, fetchOptions) => node.fetch(type_1, data_0, fetchOptions ?? {}), $[14] = node, $[15] = t6);
|
|
66
|
+
let fetch = t6, t7;
|
|
67
|
+
return $[16] !== fetch || $[17] !== sendMessage ? (t7 = {
|
|
68
|
+
sendMessage,
|
|
69
|
+
fetch
|
|
70
|
+
}, $[16] = fetch, $[17] = sendMessage, $[18] = t7) : t7 = $[18], t7;
|
|
71
|
+
}
|
|
72
|
+
function _temp(unsubscribe) {
|
|
73
|
+
return unsubscribe();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @public
|
|
77
|
+
*
|
|
78
|
+
* A React hook that retrieves the dashboard organization ID that is currently selected in the Sanity Dashboard.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```tsx
|
|
82
|
+
* function DashboardComponent() {
|
|
83
|
+
* const orgId = useOrganizationId()
|
|
84
|
+
*
|
|
85
|
+
* if (!orgId) return null
|
|
86
|
+
*
|
|
87
|
+
* return <div>Organization ID: {String(orgId)}</div>
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @category Dashboard
|
|
92
|
+
* @returns The dashboard organization ID (string | undefined)
|
|
93
|
+
*/
|
|
94
|
+
function useOrganizationId() {
|
|
95
|
+
let $ = c(2), instance = useSanityInstance(), t0;
|
|
96
|
+
$[0] === instance ? t0 = $[1] : (t0 = getDashboardOrganizationId(instance), $[0] = instance, $[1] = t0);
|
|
97
|
+
let { subscribe, getCurrent } = t0;
|
|
98
|
+
return useSyncExternalStore(subscribe, getCurrent);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Hook that fetches studio workspaces and organizes them by projectId:dataset
|
|
102
|
+
* @internal
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```tsx
|
|
106
|
+
* import {useStudioWorkspacesByProjectIdDataset} from '@sanity/sdk-react'
|
|
107
|
+
* import {Card, Code, Button} from '@sanity/ui'
|
|
108
|
+
* import {Suspense} from 'react'
|
|
109
|
+
*
|
|
110
|
+
* function WorkspacesCard() {
|
|
111
|
+
* const {workspacesByProjectIdAndDataset, error} = useStudioWorkspacesByProjectIdDataset()
|
|
112
|
+
* if (error) {
|
|
113
|
+
* return <div>Error: {error}</div>
|
|
114
|
+
* }
|
|
115
|
+
* return (
|
|
116
|
+
* <Card padding={4} radius={2} shadow={1}>
|
|
117
|
+
* <Code language="json">
|
|
118
|
+
* {JSON.stringify(workspacesByProjectIdAndDataset, null, 2)}
|
|
119
|
+
* </Code>
|
|
120
|
+
* </Card>
|
|
121
|
+
* )
|
|
122
|
+
* }
|
|
123
|
+
*
|
|
124
|
+
* // Wrap the component with Suspense since the hook may suspend
|
|
125
|
+
* function DashboardWorkspaces() {
|
|
126
|
+
* return (
|
|
127
|
+
* <Suspense fallback={<Button text="Loading..." disabled />}>
|
|
128
|
+
* <WorkspacesCard />
|
|
129
|
+
* </Suspense>
|
|
130
|
+
* )
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
function useStudioWorkspacesByProjectIdDataset() {
|
|
135
|
+
let $ = c(8), t0;
|
|
136
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = {}, $[0] = t0) : t0 = $[0];
|
|
137
|
+
let [workspacesByProjectIdAndDataset, setWorkspacesByProjectIdAndDataset] = useState(t0), [error, setError] = useState(null), t1;
|
|
138
|
+
$[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
|
|
139
|
+
name: SDK_NODE_NAME,
|
|
140
|
+
connectTo: SDK_CHANNEL_NAME
|
|
141
|
+
}, $[1] = t1) : t1 = $[1];
|
|
142
|
+
let { fetch } = useWindowConnection(t1), t2, t3;
|
|
143
|
+
$[2] === fetch ? (t2 = $[3], t3 = $[4]) : (t2 = () => {
|
|
144
|
+
if (!fetch) return;
|
|
145
|
+
let fetchWorkspaces = async function fetchWorkspaces(signal) {
|
|
146
|
+
try {
|
|
147
|
+
let data = await fetch("dashboard/v1/context", void 0, { signal }), workspaceMap = {}, noProjectIdAndDataset = [];
|
|
148
|
+
data.context.availableResources.forEach((resource) => {
|
|
149
|
+
if (resource.type !== "studio") return;
|
|
150
|
+
if (!resource.projectId || !resource.dataset) {
|
|
151
|
+
noProjectIdAndDataset.push(resource);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
let key = `${resource.projectId}:${resource.dataset}`;
|
|
155
|
+
workspaceMap[key] || (workspaceMap[key] = []), workspaceMap[key].push(resource);
|
|
156
|
+
}), noProjectIdAndDataset.length > 0 && (workspaceMap["NO_PROJECT_ID:NO_DATASET"] = noProjectIdAndDataset), setWorkspacesByProjectIdAndDataset(workspaceMap), setError(null);
|
|
157
|
+
} catch (t4) {
|
|
158
|
+
let err = t4;
|
|
159
|
+
if (err instanceof Error) {
|
|
160
|
+
if (err.name === "AbortError") return;
|
|
161
|
+
setError("Failed to fetch workspaces");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}, controller = new AbortController();
|
|
165
|
+
return fetchWorkspaces(controller.signal), () => {
|
|
166
|
+
controller.abort();
|
|
167
|
+
};
|
|
168
|
+
}, t3 = [fetch], $[2] = fetch, $[3] = t2, $[4] = t3), useEffect(t2, t3);
|
|
169
|
+
let t4;
|
|
170
|
+
return $[5] !== error || $[6] !== workspacesByProjectIdAndDataset ? (t4 = {
|
|
171
|
+
workspacesByProjectIdAndDataset,
|
|
172
|
+
error
|
|
173
|
+
}, $[5] = error, $[6] = workspacesByProjectIdAndDataset, $[7] = t4) : t4 = $[7], t4;
|
|
174
|
+
}
|
|
175
|
+
export { useSanityInstance as a, createStateSourceHook as i, useOrganizationId as n, SanityInstanceContext as o, useWindowConnection as r, useStudioWorkspacesByProjectIdDataset as t };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=useStudioWorkspacesByProjectIdDataset-I4S3CuR5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStudioWorkspacesByProjectIdDataset-I4S3CuR5.js","names":["SanityInstance","createContext","SanityInstanceContext","SanityInstance","useContext","SanityInstanceContext","useSanityInstance","instance","Error","SanityConfig","SanityInstance","StateSource","useSyncExternalStore","useSanityInstance","StateSourceFactory","instance","params","TParams","TState","CreateStateSourceHookOptions","getState","shouldSuspend","suspender","Promise","getConfig","createStateSourceHook","options","suspense","undefined","useHook","t0","$","_c","t1","state","subscribe","getCurrent","MessageData","NodeInput","SanityInstance","StateSource","FrameMessage","getNodeState","NodeState","WindowMessage","useCallback","useEffect","useRef","filter","firstValueFrom","useSanityInstance","createStateSourceHook","WindowMessageHandler","event","TFrameMessage","UseWindowConnectionOptions","name","connectTo","onMessage","Record","TMessage","WindowConnection","sendMessage","type","TType","data","Extract","fetch","options","signal","AbortSignal","suppressWarnings","responseTimeout","Promise","TResponse","useNodeState","getState","instance","nodeInput","shouldSuspend","getCurrent","undefined","suspender","observable","pipe","Boolean","useWindowConnection","t0","$","_c","t1","node","t2","Symbol","for","messageUnsubscribers","t3","Object","entries","forEach","t4","handler","messageUnsubscribe","on","current","push","_temp","t5","type_0","post","t6","type_1","data_0","fetchOptions","t7","unsubscribe","getDashboardOrganizationId","useMemo","useSyncExternalStore","useSanityInstance","useOrganizationId","$","_c","instance","t0","subscribe","getCurrent","SDK_CHANNEL_NAME","SDK_NODE_NAME","useEffect","useState","useWindowConnection","DashboardResource","id","name","title","basePath","projectId","dataset","type","userApplicationId","url","WorkspacesByProjectIdDataset","key","StudioWorkspacesResult","workspacesByProjectIdAndDataset","error","useStudioWorkspacesByProjectIdDataset","$","_c","t0","Symbol","for","setWorkspacesByProjectIdAndDataset","setError","t1","connectTo","fetch","t2","t3","fetchWorkspaces","signal","data","undefined","workspaceMap","noProjectIdAndDataset","context","availableResources","forEach","resource","push","const","length","t4","err","Error","controller","AbortController","abort"],"sources":["../src/context/SanityInstanceContext.ts","../src/hooks/context/useSanityInstance.ts","../src/hooks/helpers/createStateSourceHook.tsx","../src/hooks/comlink/useWindowConnection.ts","../src/hooks/dashboard/useOrganizationId.tsx","../src/hooks/dashboard/useStudioWorkspacesByProjectIdDataset.ts"],"sourcesContent":["import {type SanityInstance} from '@sanity/sdk'\nimport {createContext} from 'react'\n\nexport const SanityInstanceContext = createContext<SanityInstance | null>(null)\n","import {type SanityInstance} from '@sanity/sdk'\nimport {useContext} from 'react'\n\nimport {SanityInstanceContext} from '../../context/SanityInstanceContext'\n\n/**\n * Retrieves the current Sanity instance from context\n *\n * @public\n *\n * @category Platform\n * @returns The current Sanity instance\n *\n * @remarks\n * This hook accesses the nearest Sanity instance from the React context.\n * The hook must be used within a component wrapped by a `ResourceProvider` or `SanityApp`.\n *\n * @example Get the current instance\n * ```tsx\n * const instance = useSanityInstance()\n * console.log(instance.config.projectId)\n * ```\n *\n * @throws Error if no SanityInstance is found in context\n */\nexport const useSanityInstance = (): SanityInstance => {\n const instance = useContext(SanityInstanceContext)\n\n if (!instance) {\n throw new Error(\n `SanityInstance context not found. Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.`,\n )\n }\n\n return instance\n}\n","import {type SanityConfig, type SanityInstance, type StateSource} from '@sanity/sdk'\nimport {useSyncExternalStore} from 'react'\n\nimport {useSanityInstance} from '../context/useSanityInstance'\n\ntype StateSourceFactory<TParams extends unknown[], TState> = (\n instance: SanityInstance,\n ...params: TParams\n) => StateSource<TState>\n\ninterface CreateStateSourceHookOptions<TParams extends unknown[], TState> {\n getState: StateSourceFactory<TParams, TState>\n shouldSuspend?: (instance: SanityInstance, ...params: TParams) => boolean\n suspender?: (instance: SanityInstance, ...params: TParams) => Promise<unknown>\n getConfig?: (...params: TParams) => SanityConfig | undefined\n}\n\nexport function createStateSourceHook<TParams extends unknown[], TState>(\n options: StateSourceFactory<TParams, TState> | CreateStateSourceHookOptions<TParams, TState>,\n): (...params: TParams) => TState {\n const getState = typeof options === 'function' ? options : options.getState\n const suspense = 'shouldSuspend' in options && 'suspender' in options ? options : undefined\n\n function useHook(...params: TParams) {\n const instance = useSanityInstance()\n\n if (suspense?.suspender && suspense?.shouldSuspend?.(instance, ...params)) {\n throw suspense.suspender(instance, ...params)\n }\n\n const state = getState(instance, ...params)\n return useSyncExternalStore(state.subscribe, state.getCurrent)\n }\n\n return useHook\n}\n","import {type MessageData, type NodeInput} from '@sanity/comlink'\nimport {type SanityInstance, type StateSource} from '@sanity/sdk'\nimport {\n type FrameMessage,\n getNodeState,\n type NodeState,\n type WindowMessage,\n} from '@sanity/sdk/comlink'\nimport {useCallback, useEffect, useRef} from 'react'\nimport {filter, firstValueFrom} from 'rxjs'\n\nimport {useSanityInstance} from '../context/useSanityInstance'\nimport {createStateSourceHook} from '../helpers/createStateSourceHook'\n\n/**\n * @internal\n */\nexport type WindowMessageHandler<TFrameMessage extends FrameMessage> = (\n event: TFrameMessage['data'],\n) => TFrameMessage['response']\n\n/**\n * @internal\n */\nexport interface UseWindowConnectionOptions<TMessage extends FrameMessage> {\n name: string\n connectTo: string\n onMessage?: Record<TMessage['type'], WindowMessageHandler<TMessage>>\n}\n\n/**\n * @internal\n */\nexport interface WindowConnection<TMessage extends WindowMessage> {\n sendMessage: <TType extends TMessage['type']>(\n type: TType,\n data?: Extract<TMessage, {type: TType}>['data'],\n ) => void\n fetch: <TResponse>(\n type: string,\n data?: MessageData,\n options?: {\n signal?: AbortSignal\n suppressWarnings?: boolean\n responseTimeout?: number\n },\n ) => Promise<TResponse>\n}\n\nconst useNodeState = createStateSourceHook({\n getState: getNodeState as (\n instance: SanityInstance,\n nodeInput: NodeInput,\n ) => StateSource<NodeState>,\n shouldSuspend: (instance: SanityInstance, nodeInput: NodeInput) =>\n getNodeState(instance, nodeInput).getCurrent() === undefined,\n suspender: (instance: SanityInstance, nodeInput: NodeInput) => {\n return firstValueFrom(getNodeState(instance, nodeInput).observable.pipe(filter(Boolean)))\n },\n})\n\n/**\n * @internal\n * Hook to wrap a Comlink node in a React hook.\n * Our store functionality takes care of the lifecycle of the node,\n * as well as sharing a single node between invocations if they share the same name.\n *\n * Generally not to be used directly, but to be used as a dependency of\n * Comlink-powered hooks like `useStudioWorkspacesByProjectIdDataset`.\n */\nexport function useWindowConnection<\n TWindowMessage extends WindowMessage,\n TFrameMessage extends FrameMessage,\n>({\n name,\n connectTo,\n onMessage,\n}: UseWindowConnectionOptions<TFrameMessage>): WindowConnection<TWindowMessage> {\n const {node} = useNodeState({name, connectTo})\n const messageUnsubscribers = useRef<(() => void)[]>([])\n const instance = useSanityInstance()\n\n useEffect(() => {\n if (onMessage) {\n Object.entries(onMessage).forEach(([type, handler]) => {\n const messageUnsubscribe = node.on(type, handler as WindowMessageHandler<TFrameMessage>)\n if (messageUnsubscribe) {\n messageUnsubscribers.current.push(messageUnsubscribe)\n }\n })\n }\n\n return () => {\n messageUnsubscribers.current.forEach((unsubscribe) => unsubscribe())\n messageUnsubscribers.current = []\n }\n }, [instance, name, onMessage, node])\n\n const sendMessage = useCallback(\n (type: TWindowMessage['type'], data?: Extract<TWindowMessage, {type: typeof type}>['data']) => {\n node.post(type, data)\n },\n [node],\n )\n\n const fetch = useCallback(\n <TResponse>(\n type: string,\n data?: MessageData,\n fetchOptions?: {\n responseTimeout?: number\n signal?: AbortSignal\n suppressWarnings?: boolean\n },\n ): Promise<TResponse> => {\n return node.fetch(type, data, fetchOptions ?? {}) as Promise<TResponse>\n },\n [node],\n )\n return {\n sendMessage,\n fetch,\n }\n}\n","import {getDashboardOrganizationId} from '@sanity/sdk'\nimport {useMemo, useSyncExternalStore} from 'react'\n\nimport {useSanityInstance} from '../context/useSanityInstance'\n\n/**\n * @public\n *\n * A React hook that retrieves the dashboard organization ID that is currently selected in the Sanity Dashboard.\n *\n * @example\n * ```tsx\n * function DashboardComponent() {\n * const orgId = useOrganizationId()\n *\n * if (!orgId) return null\n *\n * return <div>Organization ID: {String(orgId)}</div>\n * }\n * ```\n *\n * @category Dashboard\n * @returns The dashboard organization ID (string | undefined)\n */\nexport function useOrganizationId(): string | undefined {\n const instance = useSanityInstance()\n const {subscribe, getCurrent} = useMemo(() => getDashboardOrganizationId(instance), [instance])\n\n return useSyncExternalStore(subscribe, getCurrent)\n}\n","import {SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'\nimport {useEffect, useState} from 'react'\n\nimport {useWindowConnection} from '../comlink/useWindowConnection'\n\nexport interface DashboardResource {\n id: string\n name: string\n title: string\n basePath: string\n projectId: string\n dataset: string\n type: string\n userApplicationId: string\n url: string\n}\n\ninterface WorkspacesByProjectIdDataset {\n [key: `${string}:${string}`]: DashboardResource[] // key format: `${projectId}:${dataset}`\n}\n\ninterface StudioWorkspacesResult {\n workspacesByProjectIdAndDataset: WorkspacesByProjectIdDataset\n error: string | null\n}\n\n/**\n * Hook that fetches studio workspaces and organizes them by projectId:dataset\n * @internal\n *\n * @example\n * ```tsx\n * import {useStudioWorkspacesByProjectIdDataset} from '@sanity/sdk-react'\n * import {Card, Code, Button} from '@sanity/ui'\n * import {Suspense} from 'react'\n *\n * function WorkspacesCard() {\n * const {workspacesByProjectIdAndDataset, error} = useStudioWorkspacesByProjectIdDataset()\n * if (error) {\n * return <div>Error: {error}</div>\n * }\n * return (\n * <Card padding={4} radius={2} shadow={1}>\n * <Code language=\"json\">\n * {JSON.stringify(workspacesByProjectIdAndDataset, null, 2)}\n * </Code>\n * </Card>\n * )\n * }\n *\n * // Wrap the component with Suspense since the hook may suspend\n * function DashboardWorkspaces() {\n * return (\n * <Suspense fallback={<Button text=\"Loading...\" disabled />}>\n * <WorkspacesCard />\n * </Suspense>\n * )\n * }\n * ```\n */\nexport function useStudioWorkspacesByProjectIdDataset(): StudioWorkspacesResult {\n const [workspacesByProjectIdAndDataset, setWorkspacesByProjectIdAndDataset] =\n useState<WorkspacesByProjectIdDataset>({})\n const [error, setError] = useState<string | null>(null)\n\n const {fetch} = useWindowConnection({\n name: SDK_NODE_NAME,\n connectTo: SDK_CHANNEL_NAME,\n })\n\n // Once computed, this should probably be in a store and poll for changes\n // However, our stores are currently being refactored\n useEffect(() => {\n if (!fetch) return\n\n async function fetchWorkspaces(signal: AbortSignal) {\n try {\n const data = await fetch<{\n context: {availableResources: Array<DashboardResource>}\n }>('dashboard/v1/context', undefined, {signal})\n\n const workspaceMap: WorkspacesByProjectIdDataset = {}\n const noProjectIdAndDataset: DashboardResource[] = []\n\n data.context.availableResources.forEach((resource) => {\n if (resource.type !== 'studio') return\n if (!resource.projectId || !resource.dataset) {\n noProjectIdAndDataset.push(resource)\n return\n }\n const key = `${resource.projectId}:${resource.dataset}` as const\n if (!workspaceMap[key]) {\n workspaceMap[key] = []\n }\n workspaceMap[key].push(resource)\n })\n\n if (noProjectIdAndDataset.length > 0) {\n workspaceMap['NO_PROJECT_ID:NO_DATASET'] = noProjectIdAndDataset\n }\n\n setWorkspacesByProjectIdAndDataset(workspaceMap)\n setError(null)\n } catch (err: unknown) {\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return\n }\n setError('Failed to fetch workspaces')\n }\n }\n }\n\n const controller = new AbortController()\n fetchWorkspaces(controller.signal)\n\n return () => {\n controller.abort()\n }\n }, [fetch])\n\n return {\n workspacesByProjectIdAndDataset,\n error,\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/sdk-react",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Sanity SDK React toolkit for Content OS",
|
|
6
6
|
"keywords": [
|
|
@@ -33,32 +33,29 @@
|
|
|
33
33
|
"module": "./dist/index.js",
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"exports": {
|
|
36
|
-
".":
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"default": "./dist/index.js"
|
|
40
|
-
},
|
|
41
|
-
"./package.json": "./package.json"
|
|
36
|
+
".": "./dist/index.js",
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
"./dashboard": "./dist/_exports/dashboard.js"
|
|
42
39
|
},
|
|
43
40
|
"publishConfig": {
|
|
44
41
|
"access": "public"
|
|
45
42
|
},
|
|
46
43
|
"dependencies": {
|
|
47
|
-
"@sanity/client": "^7.
|
|
48
|
-
"@sanity/message-protocol": "^0.
|
|
49
|
-
"@sanity/types": "^6.
|
|
44
|
+
"@sanity/client": "^7.26.2",
|
|
45
|
+
"@sanity/message-protocol": "^0.24.0",
|
|
46
|
+
"@sanity/types": "^6.9.1",
|
|
50
47
|
"@sanity/workbench": "0.1.0-alpha.24",
|
|
51
48
|
"groq": "3.88.1-typegen-experimental.0",
|
|
52
49
|
"react-compiler-runtime": "^1.0.0",
|
|
53
50
|
"react-error-boundary": "^6.1.2",
|
|
54
51
|
"rxjs": "^7.8.2",
|
|
55
52
|
"xstate": "^5.31.0",
|
|
56
|
-
"@sanity/sdk": "3.0.0
|
|
53
|
+
"@sanity/sdk": "3.0.0"
|
|
57
54
|
},
|
|
58
55
|
"devDependencies": {
|
|
59
56
|
"@sanity/browserslist-config": "^1.0.5",
|
|
60
|
-
"@sanity/comlink": "^4.0.
|
|
61
|
-
"@sanity/pkg-utils": "^
|
|
57
|
+
"@sanity/comlink": "^4.0.3",
|
|
58
|
+
"@sanity/pkg-utils": "^12.1.0",
|
|
62
59
|
"@testing-library/jest-dom": "^6.9.1",
|
|
63
60
|
"@testing-library/react": "^16.3.2",
|
|
64
61
|
"@types/node": "^24.13.3",
|
|
@@ -73,21 +70,24 @@
|
|
|
73
70
|
"oxfmt": "^0.58.0",
|
|
74
71
|
"react": "^19.2.7",
|
|
75
72
|
"react-dom": "^19.2.7",
|
|
76
|
-
"
|
|
73
|
+
"rolldown": "^1.2.3",
|
|
77
74
|
"typescript": "^6.0.3",
|
|
78
75
|
"vite": "^8.1.5",
|
|
79
76
|
"vitest": "^4.1.10",
|
|
80
77
|
"@repo/config-eslint": "0.0.0",
|
|
81
|
-
"@repo/config-test": "0.0.1",
|
|
82
|
-
"@repo/package.bundle": "3.82.0",
|
|
83
78
|
"@repo/package.config": "0.0.1",
|
|
84
|
-
"@repo/
|
|
79
|
+
"@repo/package.bundle": "3.82.0",
|
|
80
|
+
"@repo/tsconfig": "0.0.1",
|
|
81
|
+
"@repo/config-test": "0.0.1"
|
|
85
82
|
},
|
|
86
83
|
"peerDependencies": {
|
|
87
|
-
"react": "^
|
|
88
|
-
"react-dom": "^
|
|
84
|
+
"react": "^19.2.0",
|
|
85
|
+
"react-dom": "^19.2.0"
|
|
89
86
|
},
|
|
90
87
|
"browserslist": "extends @sanity/browserslist-config",
|
|
88
|
+
"inlinedDependencies": {
|
|
89
|
+
"@sanity/comlink": "4.0.3"
|
|
90
|
+
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"build": "pkg build --strict --clean --check",
|
|
93
93
|
"build:bundle": "vite build --configLoader runner --config package.bundle.ts",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type AgentResourceContextOptions,
|
|
3
|
+
useAgentResourceContext,
|
|
4
|
+
} from '../hooks/dashboard/useAgentResourceContext'
|
|
5
|
+
export {useNavigate} from '../hooks/dashboard/useNavigate'
|
|
6
|
+
export {
|
|
7
|
+
type NavigateToStudioResult,
|
|
8
|
+
useNavigateToStudioDocument,
|
|
9
|
+
} from '../hooks/dashboard/useNavigateToStudioDocument'
|
|
10
|
+
export {useOrganizationId} from '../hooks/dashboard/useOrganizationId'
|
|
11
|
+
export {useWindowTitle} from '../hooks/dashboard/useWindowTitle'
|
|
@@ -21,23 +21,13 @@ export {
|
|
|
21
21
|
useAgentTransform,
|
|
22
22
|
useAgentTranslate,
|
|
23
23
|
} from '../hooks/agent/agentActions'
|
|
24
|
-
export {
|
|
25
|
-
type AgentResourceContextOptions,
|
|
26
|
-
useAgentResourceContext,
|
|
27
|
-
} from '../hooks/agent/useAgentResourceContext'
|
|
28
24
|
export {useApplication} from '../hooks/applications/useApplication'
|
|
29
25
|
export {useApplications} from '../hooks/applications/useApplications'
|
|
30
|
-
export {useCreateUserApplication} from '../hooks/applications/useCreateUserApplication'
|
|
31
26
|
export {useDeleteApplication} from '../hooks/applications/useDeleteApplication'
|
|
32
|
-
export {useDeleteUserApplication} from '../hooks/applications/useDeleteUserApplication'
|
|
33
27
|
export {useUpdateApplication} from '../hooks/applications/useUpdateApplication'
|
|
34
|
-
export {useUpdateUserApplication} from '../hooks/applications/useUpdateUserApplication'
|
|
35
|
-
export {useUserApplication} from '../hooks/applications/useUserApplication'
|
|
36
|
-
export {useUserApplications} from '../hooks/applications/useUserApplications'
|
|
37
28
|
export {useAuthState} from '../hooks/auth/useAuthState'
|
|
38
29
|
export {useAuthToken} from '../hooks/auth/useAuthToken'
|
|
39
30
|
export {useCurrentUser} from '../hooks/auth/useCurrentUser'
|
|
40
|
-
export {useDashboardOrganizationId} from '../hooks/auth/useDashboardOrganizationId'
|
|
41
31
|
export {useHandleAuthCallback} from '../hooks/auth/useHandleAuthCallback'
|
|
42
32
|
export {useLoginUrl} from '../hooks/auth/useLoginUrl'
|
|
43
33
|
export {useLogOut} from '../hooks/auth/useLogOut'
|
|
@@ -55,17 +45,15 @@ export {
|
|
|
55
45
|
type WindowConnection,
|
|
56
46
|
type WindowMessageHandler,
|
|
57
47
|
} from '../hooks/comlink/useWindowConnection'
|
|
48
|
+
export {type CommentActions, useCommentActions} from '../hooks/comments/useCommentActions'
|
|
49
|
+
export {useComments, type UseCommentsResult} from '../hooks/comments/useComments'
|
|
50
|
+
export {useCommentThreads, type UseCommentThreadsResult} from '../hooks/comments/useCommentThreads'
|
|
58
51
|
export {useResource} from '../hooks/context/useResource'
|
|
59
52
|
export {useSanityInstance} from '../hooks/context/useSanityInstance'
|
|
60
|
-
export {
|
|
61
|
-
export {useManageFavorite} from '../hooks/dashboard/useManageFavorite'
|
|
62
|
-
export {
|
|
63
|
-
type NavigateToStudioResult,
|
|
64
|
-
useNavigateToStudioDocument,
|
|
65
|
-
} from '../hooks/dashboard/useNavigateToStudioDocument'
|
|
53
|
+
export {useFavorite} from '../hooks/dashboard/useFavorite'
|
|
66
54
|
export {useRecordDocumentHistoryEvent} from '../hooks/dashboard/useRecordDocumentHistoryEvent'
|
|
67
55
|
export {useStudioWorkspacesByProjectIdDataset} from '../hooks/dashboard/useStudioWorkspacesByProjectIdDataset'
|
|
68
|
-
export {
|
|
56
|
+
export {useUpdateFavorite} from '../hooks/dashboard/useUpdateFavorite'
|
|
69
57
|
export {useDatasets} from '../hooks/datasets/useDatasets'
|
|
70
58
|
export {useApplyDocumentActions} from '../hooks/document/useApplyDocumentActions'
|
|
71
59
|
export {type CreateDocumentOverrides, useCreateDocument} from '../hooks/document/useCreateDocument'
|
|
@@ -91,6 +79,11 @@ export {
|
|
|
91
79
|
usePaginatedDocuments,
|
|
92
80
|
} from '../hooks/paginatedDocuments/usePaginatedDocuments'
|
|
93
81
|
export {usePresence} from '../hooks/presence/usePresence'
|
|
82
|
+
export {
|
|
83
|
+
usePresenceForDocument,
|
|
84
|
+
type UsePresenceForDocumentOptions,
|
|
85
|
+
} from '../hooks/presence/usePresenceForDocument'
|
|
86
|
+
export {useReportPresence, type UseReportPresenceOptions} from '../hooks/presence/useReportPresence'
|
|
94
87
|
export {
|
|
95
88
|
useDocumentPreview,
|
|
96
89
|
type useDocumentPreviewOptions,
|
|
@@ -102,7 +95,7 @@ export {
|
|
|
102
95
|
type useDocumentProjectionResults,
|
|
103
96
|
} from '../hooks/projection/useDocumentProjection'
|
|
104
97
|
export {useProject} from '../hooks/projects/useProject'
|
|
105
|
-
export {
|
|
98
|
+
export {useProjects} from '../hooks/projects/useProjects'
|
|
106
99
|
export {useQuery} from '../hooks/query/useQuery'
|
|
107
100
|
export {useActiveReleases} from '../hooks/releases/useActiveReleases'
|
|
108
101
|
export {useAllReleases} from '../hooks/releases/useAllReleases'
|
|
@@ -3,7 +3,7 @@ import {render} from '@testing-library/react'
|
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {useOrganizationId} from '../hooks/dashboard/useOrganizationId'
|
|
7
7
|
import {resolveOrgResources} from '../utils/resolveOrgResources'
|
|
8
8
|
import {SDKProvider} from './SDKProvider'
|
|
9
9
|
|
|
@@ -14,8 +14,8 @@ vi.mock('../hooks/context/useSanityInstance', () => {
|
|
|
14
14
|
return {useSanityInstance: () => instance}
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
vi.mock('../hooks/
|
|
18
|
-
|
|
17
|
+
vi.mock('../hooks/dashboard/useOrganizationId', () => ({
|
|
18
|
+
useOrganizationId: vi.fn(),
|
|
19
19
|
}))
|
|
20
20
|
|
|
21
21
|
vi.mock('../utils/resolveOrgResources', () => ({
|
|
@@ -53,13 +53,13 @@ vi.mock('./auth/AuthBoundary', () => ({
|
|
|
53
53
|
}))
|
|
54
54
|
|
|
55
55
|
const mockResolveOrgResources = vi.mocked(resolveOrgResources)
|
|
56
|
-
const
|
|
56
|
+
const mockUseOrganizationId = vi.mocked(useOrganizationId)
|
|
57
57
|
|
|
58
58
|
describe('SDKProvider', () => {
|
|
59
59
|
beforeEach(() => {
|
|
60
60
|
vi.clearAllMocks()
|
|
61
61
|
mockResolveOrgResources.mockResolvedValue({})
|
|
62
|
-
|
|
62
|
+
mockUseOrganizationId.mockReturnValue(undefined)
|
|
63
63
|
})
|
|
64
64
|
|
|
65
65
|
it('renders single ResourceProvider with AuthBoundary for a single config', () => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {type DocumentResource,
|
|
1
|
+
import {type DocumentResource, type SanityConfig} from '@sanity/sdk'
|
|
2
|
+
import {isStudioConfig} from '@sanity/sdk/_internal'
|
|
2
3
|
import {type ReactElement, useContext, useEffect, useMemo} from 'react'
|
|
3
4
|
|
|
4
5
|
import {SDKStudioContext, type StudioWorkspaceHandle} from '../context/SDKStudioContext'
|
|
@@ -17,8 +18,6 @@ export interface SanityAppProps {
|
|
|
17
18
|
* automatically.
|
|
18
19
|
*/
|
|
19
20
|
config?: SanityConfig | SanityConfig[]
|
|
20
|
-
/** @deprecated use the `config` prop instead. */
|
|
21
|
-
sanityConfigs?: SanityConfig[]
|
|
22
21
|
resources?: Record<string, DocumentResource>
|
|
23
22
|
children: React.ReactNode
|
|
24
23
|
/* Fallback content to show when child components are suspending. Same as the `fallback` prop for React Suspense. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {AuthStateType
|
|
1
|
+
import {AuthStateType} from '@sanity/sdk'
|
|
2
2
|
import {render, screen, waitFor} from '@testing-library/react'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import {type FallbackProps} from 'react-error-boundary'
|
|
@@ -110,24 +110,6 @@ describe('AuthBoundary', () => {
|
|
|
110
110
|
const mockUseVerifyOrgProjects = vi.mocked(useVerifyOrgProjects)
|
|
111
111
|
const testProjectIds = ['proj-test'] // Example project ID for tests
|
|
112
112
|
|
|
113
|
-
// Mock Sanity instance
|
|
114
|
-
const mockSanityInstance = {
|
|
115
|
-
instanceId: 'test-instance-id',
|
|
116
|
-
config: {
|
|
117
|
-
projectId: 'test-project',
|
|
118
|
-
dataset: 'test-dataset',
|
|
119
|
-
},
|
|
120
|
-
isDisposed: () => false,
|
|
121
|
-
dispose: () => {},
|
|
122
|
-
onDispose: () => () => {},
|
|
123
|
-
getParent: () => undefined,
|
|
124
|
-
createChild: (config: SanityConfig) => ({
|
|
125
|
-
...mockSanityInstance,
|
|
126
|
-
config: {...mockSanityInstance.config, ...config},
|
|
127
|
-
}),
|
|
128
|
-
match: () => undefined,
|
|
129
|
-
}
|
|
130
|
-
|
|
131
113
|
beforeEach(() => {
|
|
132
114
|
vi.clearAllMocks()
|
|
133
115
|
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {CorsOriginError} from '@sanity/client'
|
|
2
|
-
import {AuthStateType, getCorsErrorProjectId, isImportError
|
|
2
|
+
import {AuthStateType, getCorsErrorProjectId, isImportError} from '@sanity/sdk'
|
|
3
|
+
import {isStudioConfig} from '@sanity/sdk/_internal'
|
|
3
4
|
import {useEffect, useMemo} from 'react'
|
|
4
5
|
import {ErrorBoundary, type FallbackProps} from 'react-error-boundary'
|
|
5
6
|
|
|
6
7
|
import {ComlinkTokenRefreshProvider} from '../../context/ComlinkTokenRefresh'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import {isDashboardEnvironment} from '../../context/dashboardToken'
|
|
9
|
+
import {DashboardTokenRefreshProvider} from '../../context/DashboardTokenRefresh'
|
|
9
10
|
import {useAuthState} from '../../hooks/auth/useAuthState'
|
|
10
11
|
import {useLoginUrl} from '../../hooks/auth/useLoginUrl'
|
|
11
12
|
import {useVerifyOrgProjects} from '../../hooks/auth/useVerifyOrgProjects'
|
|
@@ -143,11 +144,11 @@ export function AuthBoundary({
|
|
|
143
144
|
|
|
144
145
|
return (
|
|
145
146
|
<ComlinkTokenRefreshProvider>
|
|
146
|
-
<
|
|
147
|
+
<DashboardTokenRefreshProvider>
|
|
147
148
|
<ErrorBoundary FallbackComponent={FallbackComponent} resetKeys={[sessionResetKey]}>
|
|
148
149
|
<AuthSwitch {...props} />
|
|
149
150
|
</ErrorBoundary>
|
|
150
|
-
</
|
|
151
|
+
</DashboardTokenRefreshProvider>
|
|
151
152
|
</ComlinkTokenRefreshProvider>
|
|
152
153
|
)
|
|
153
154
|
}
|
|
@@ -186,7 +187,7 @@ function AuthSwitch({
|
|
|
186
187
|
const loginUrl = useLoginUrl()
|
|
187
188
|
|
|
188
189
|
useEffect(() => {
|
|
189
|
-
if (isLoggedOut && !isInIframe() && !isStudio && !
|
|
190
|
+
if (isLoggedOut && !isInIframe() && !isStudio && !isDashboardEnvironment()) {
|
|
190
191
|
// We don't want to redirect to login if we're in the Dashboard, in studio
|
|
191
192
|
// mode, or in the workbench (the OS owns the session and mints the token)
|
|
192
193
|
window.location.href = loginUrl
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {ClientError} from '@sanity/client'
|
|
2
|
+
import {AuthStateType, getIsInDashboardState} from '@sanity/sdk'
|
|
2
3
|
import {
|
|
3
|
-
AuthStateType,
|
|
4
4
|
getClientErrorApiBody,
|
|
5
5
|
getClientErrorApiDescription,
|
|
6
|
-
getIsInDashboardState,
|
|
7
6
|
isProjectUserNotFoundClientError,
|
|
8
|
-
} from '@sanity/sdk'
|
|
7
|
+
} from '@sanity/sdk/_internal'
|
|
9
8
|
import {Suspense, useCallback, useEffect, useMemo, useRef} from 'react'
|
|
10
9
|
import {type FallbackProps} from 'react-error-boundary'
|
|
11
10
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import {type ClientError} from '@sanity/client'
|
|
2
2
|
import {SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'
|
|
3
|
+
import {AuthStateType, getIsInDashboardState, setAuthToken} from '@sanity/sdk'
|
|
4
|
+
import {isStudioConfig} from '@sanity/sdk/_internal'
|
|
3
5
|
import {
|
|
4
|
-
AuthStateType,
|
|
5
6
|
type FrameMessage,
|
|
6
|
-
getIsInDashboardState,
|
|
7
|
-
isStudioConfig,
|
|
8
7
|
type NewTokenResponseMessage,
|
|
9
8
|
type RequestNewTokenMessage,
|
|
10
|
-
setAuthToken,
|
|
11
9
|
type WindowMessage,
|
|
12
|
-
} from '@sanity/sdk'
|
|
10
|
+
} from '@sanity/sdk/comlink'
|
|
13
11
|
import React, {type PropsWithChildren, useCallback, useEffect, useMemo, useRef} from 'react'
|
|
14
12
|
|
|
15
13
|
import {useAuthState} from '../hooks/auth/useAuthState'
|