@sanity/sdk-react 3.0.0-rc.0 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -155
- package/dist/index.d.ts +1564 -682
- package/dist/index.js +1118 -612
- package/dist/index.js.map +1 -1
- package/package.json +51 -54
- package/src/_exports/index.ts +2 -4
- package/src/_exports/sdk-react.ts +26 -17
- package/src/components/SDKProvider.test.tsx +173 -32
- package/src/components/SDKProvider.tsx +87 -28
- package/src/components/SanityApp.test.tsx +68 -12
- package/src/components/SanityApp.tsx +94 -87
- package/src/components/auth/AuthBoundary.recovery.test.tsx +86 -0
- package/src/components/auth/AuthBoundary.test.tsx +26 -8
- package/src/components/auth/AuthBoundary.tsx +28 -6
- package/src/components/auth/DashboardAccessRequest.tsx +37 -0
- package/src/components/auth/LoginError.test.tsx +191 -5
- package/src/components/auth/LoginError.tsx +103 -59
- package/src/components/errors/ChunkLoadError.test.tsx +59 -0
- package/src/components/errors/ChunkLoadError.tsx +56 -0
- package/src/components/errors/CorsErrorComponent.tsx +2 -2
- package/src/components/errors/chunkReloadStorage.ts +57 -0
- package/src/config/handles.ts +29 -27
- package/src/constants.ts +5 -0
- package/src/context/ComlinkTokenRefresh.test.tsx +10 -27
- package/src/context/DefaultResourceContext.ts +3 -3
- package/src/context/OrganizationResourcesProvider.test.tsx +189 -0
- package/src/context/OrganizationResourcesProvider.tsx +111 -0
- package/src/context/PerspectiveContext.ts +3 -3
- package/src/context/ProjectContext.ts +15 -0
- package/src/context/ResourceProvider.test.tsx +72 -90
- package/src/context/ResourceProvider.tsx +59 -93
- package/src/context/SDKStudioContext.test.tsx +28 -33
- package/src/context/SanityInstanceProvider.test.tsx +100 -0
- package/src/context/SanityInstanceProvider.tsx +71 -0
- package/src/context/WorkbenchTokenRefresh.test.tsx +106 -0
- package/src/context/WorkbenchTokenRefresh.tsx +61 -0
- package/src/context/renderSanityApp.test.tsx +151 -49
- package/src/context/renderSanityApp.tsx +12 -8
- package/src/context/workbenchToken.ts +63 -0
- package/src/hooks/access/useCheckPermissions.test-d.ts +15 -0
- package/src/hooks/access/useCheckPermissions.test.tsx +53 -0
- package/src/hooks/access/useCheckPermissions.ts +24 -0
- package/src/hooks/agent/agentActions.test.tsx +1 -1
- package/src/hooks/agent/agentActions.ts +51 -71
- package/src/hooks/applications/useApplication.test-d.ts +30 -0
- package/src/hooks/applications/useApplication.ts +22 -0
- package/src/hooks/applications/useApplications.test-d.ts +31 -0
- package/src/hooks/applications/useApplications.ts +25 -0
- package/src/hooks/applications/useCreateUserApplication.test-d.ts +14 -0
- package/src/hooks/applications/useCreateUserApplication.ts +11 -0
- package/src/hooks/applications/useDeleteApplication.test-d.ts +12 -0
- package/src/hooks/applications/useDeleteApplication.ts +11 -0
- package/src/hooks/applications/useDeleteUserApplication.test-d.ts +14 -0
- package/src/hooks/applications/useDeleteUserApplication.ts +11 -0
- package/src/hooks/applications/useUpdateApplication.test-d.ts +12 -0
- package/src/hooks/applications/useUpdateApplication.ts +11 -0
- package/src/hooks/applications/useUpdateUserApplication.test-d.ts +14 -0
- package/src/hooks/applications/useUpdateUserApplication.ts +11 -0
- package/src/hooks/applications/useUserApplication.test-d.ts +11 -0
- package/src/hooks/applications/useUserApplication.ts +14 -0
- package/src/hooks/applications/useUserApplications.test-d.ts +11 -0
- package/src/hooks/applications/useUserApplications.ts +14 -0
- package/src/hooks/auth/useDashboardOrganizationId.test.tsx +2 -8
- package/src/hooks/auth/useVerifyOrgProjects.test.tsx +8 -32
- package/src/hooks/auth/useVerifyOrgProjects.tsx +13 -6
- package/src/hooks/client/useClient.test.tsx +1 -4
- package/src/hooks/client/useClient.ts +1 -0
- package/src/hooks/context/useResource.test.tsx +32 -0
- package/src/hooks/context/useResource.ts +24 -0
- package/src/hooks/context/useSanityInstance.test.tsx +72 -3
- package/src/hooks/context/useSanityInstance.ts +30 -8
- package/src/hooks/dashboard/useManageFavorite.test.tsx +110 -46
- package/src/hooks/dashboard/useManageFavorite.ts +10 -16
- package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +5 -7
- package/src/hooks/dashboard/useNavigateToStudioDocument.ts +2 -6
- package/src/hooks/dashboard/useRecordDocumentHistoryEvent.test.ts +0 -2
- package/src/hooks/dashboard/useRecordDocumentHistoryEvent.ts +1 -2
- package/src/hooks/dashboard/useWindowTitle.test.ts +244 -0
- package/src/hooks/dashboard/useWindowTitle.ts +114 -0
- package/src/hooks/datasets/useDatasets.test.tsx +116 -0
- package/src/hooks/datasets/useDatasets.ts +33 -13
- package/src/hooks/document/useApplyDocumentActions.test.tsx +48 -0
- package/src/hooks/document/useApplyDocumentActions.ts +66 -48
- package/src/hooks/document/useCreateDocument.test.tsx +83 -0
- package/src/hooks/document/useCreateDocument.ts +117 -0
- package/src/hooks/document/useDocument.test.tsx +37 -8
- package/src/hooks/document/useDocument.ts +131 -66
- package/src/hooks/document/useDocumentEvent.test.tsx +16 -4
- package/src/hooks/document/useDocumentEvent.ts +16 -10
- package/src/hooks/document/useDocumentPermissions.test.tsx +8 -7
- package/src/hooks/document/useDocumentPermissions.ts +71 -39
- package/src/hooks/document/useDocumentSyncStatus.test.ts +1 -0
- package/src/hooks/document/useDocumentSyncStatus.ts +13 -9
- package/src/hooks/document/useEditDocument.test.tsx +21 -14
- package/src/hooks/document/useEditDocument.ts +163 -17
- package/src/hooks/documents/useDocuments.test.tsx +64 -44
- package/src/hooks/documents/useDocuments.ts +36 -20
- package/src/hooks/helpers/createCallbackHook.test.tsx +13 -19
- package/src/hooks/helpers/createFetcherHook.test.tsx +180 -0
- package/src/hooks/helpers/createFetcherHook.ts +69 -0
- package/src/hooks/helpers/createMutationHook.test.tsx +125 -0
- package/src/hooks/helpers/createMutationHook.tsx +93 -0
- package/src/hooks/helpers/createStateSourceHook.test.tsx +10 -10
- package/src/hooks/helpers/createStateSourceHook.tsx +2 -1
- package/src/hooks/{document/useApplyDocumentActions.test.ts → helpers/useApplyActions.test.tsx} +92 -53
- package/src/hooks/helpers/useApplyActions.ts +68 -0
- package/src/hooks/helpers/useNormalizedResourceOptions.test.tsx +253 -0
- package/src/hooks/helpers/useNormalizedResourceOptions.ts +92 -50
- package/src/hooks/helpers/useResolvedProjectId.test.tsx +59 -0
- package/src/hooks/helpers/useResolvedProjectId.ts +35 -0
- package/src/hooks/helpers/useTrackHookUsage.ts +37 -0
- package/src/hooks/installations/useInstallation.test-d.ts +19 -0
- package/src/hooks/installations/useInstallation.ts +22 -0
- package/src/hooks/installations/useInstallations.test-d.ts +26 -0
- package/src/hooks/installations/useInstallations.ts +25 -0
- package/src/hooks/organizations/useOrganization.test-d.ts +60 -0
- package/src/hooks/organizations/useOrganization.test.ts +63 -0
- package/src/hooks/organizations/useOrganization.ts +34 -0
- package/src/hooks/organizations/useOrganizations.test-d.ts +68 -0
- package/src/hooks/organizations/useOrganizations.test.ts +63 -0
- package/src/hooks/organizations/useOrganizations.ts +39 -0
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.test.tsx +34 -27
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +40 -22
- package/src/hooks/presence/usePresence.test.tsx +0 -15
- package/src/hooks/presence/usePresence.ts +9 -20
- package/src/hooks/preview/useDocumentPreview.test.tsx +0 -1
- package/src/hooks/preview/useDocumentPreview.tsx +10 -8
- package/src/hooks/projection/useDocumentProjection.test.tsx +78 -9
- package/src/hooks/projection/useDocumentProjection.ts +81 -2
- package/src/hooks/projects/useProject.test-d.ts +56 -0
- package/src/hooks/projects/useProject.test.tsx +120 -0
- package/src/hooks/projects/useProject.ts +42 -43
- package/src/hooks/projects/useProjects.test-d.ts +60 -0
- package/src/hooks/projects/useProjects.test.ts +45 -98
- package/src/hooks/projects/useProjects.ts +19 -26
- package/src/hooks/query/useQuery.test.tsx +6 -5
- package/src/hooks/query/useQuery.ts +91 -9
- package/src/hooks/releases/useActiveReleases.test.tsx +13 -7
- package/src/hooks/releases/useActiveReleases.ts +28 -24
- package/src/hooks/releases/useAllReleases.test.tsx +93 -0
- package/src/hooks/releases/useAllReleases.ts +62 -0
- package/src/hooks/releases/useApplyReleaseActions.test.tsx +66 -0
- package/src/hooks/releases/useApplyReleaseActions.ts +82 -0
- package/src/hooks/releases/usePerspective.test.tsx +18 -10
- package/src/hooks/releases/usePerspective.ts +13 -17
- package/src/hooks/users/useUser.test.tsx +3 -9
- package/src/hooks/users/useUser.ts +2 -0
- package/src/hooks/users/useUsers.test.tsx +103 -7
- package/src/hooks/users/useUsers.ts +37 -3
- package/src/utils/resolveOrgResources.test.ts +111 -0
- package/src/utils/resolveOrgResources.ts +69 -0
- package/src/hooks/context/useDefaultResource.test.tsx +0 -25
- package/src/hooks/context/useDefaultResource.ts +0 -30
- package/src/hooks/dashboard/useDispatchIntent.test.ts +0 -254
- package/src/hooks/dashboard/useDispatchIntent.ts +0 -157
- package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.test.ts +0 -107
- package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +0 -39
- package/src/hooks/datasets/useDatasets.test.ts +0 -66
- package/src/hooks/helpers/useNormalizedResourceOptions.test.ts +0 -65
- package/src/hooks/projects/useProject.test.ts +0 -79
package/package.json
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/sdk-react",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Sanity SDK React toolkit for Content OS",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"sanity",
|
|
8
|
-
"sdk",
|
|
9
|
-
"content operating system",
|
|
10
7
|
"cms",
|
|
8
|
+
"content",
|
|
9
|
+
"content operating system",
|
|
11
10
|
"headless",
|
|
12
11
|
"realtime",
|
|
13
|
-
"
|
|
12
|
+
"sanity",
|
|
13
|
+
"sdk"
|
|
14
14
|
],
|
|
15
15
|
"homepage": "https://github.com/sanity-io/sdk/tree/main/packages/react/README.md",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/sanity-io/sdk/issues"
|
|
18
18
|
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": "Sanity <developers@sanity.io>",
|
|
19
21
|
"repository": {
|
|
20
22
|
"type": "git",
|
|
21
23
|
"url": "git+https://github.com/sanity-io/sdk.git",
|
|
22
24
|
"directory": "packages/react"
|
|
23
25
|
},
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
27
30
|
"type": "module",
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"module": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
28
35
|
"exports": {
|
|
29
36
|
".": {
|
|
30
37
|
"source": "./src/_exports/index.ts",
|
|
@@ -33,71 +40,61 @@
|
|
|
33
40
|
},
|
|
34
41
|
"./package.json": "./package.json"
|
|
35
42
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"files": [
|
|
40
|
-
"dist",
|
|
41
|
-
"src"
|
|
42
|
-
],
|
|
43
|
-
"browserslist": "extends @sanity/browserslist-config",
|
|
44
|
-
"prettier": "@sanity/prettier-config",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
45
46
|
"dependencies": {
|
|
46
|
-
"@sanity/client": "^7.
|
|
47
|
-
"@sanity/message-protocol": "^0.
|
|
48
|
-
"@sanity/types": "^5.
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"react-
|
|
47
|
+
"@sanity/client": "^7.23.2",
|
|
48
|
+
"@sanity/message-protocol": "^0.23.0",
|
|
49
|
+
"@sanity/types": "^6.5.0",
|
|
50
|
+
"@sanity/workbench": "0.1.0-alpha.24",
|
|
51
|
+
"groq": "3.88.1-typegen-experimental.0",
|
|
52
|
+
"react-compiler-runtime": "^1.0.0",
|
|
53
|
+
"react-error-boundary": "^6.1.2",
|
|
52
54
|
"rxjs": "^7.8.2",
|
|
53
|
-
"
|
|
55
|
+
"xstate": "^5.31.0",
|
|
56
|
+
"@sanity/sdk": "3.0.0-rc.1"
|
|
54
57
|
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"@sanity/browserslist-config": "^1.0.5",
|
|
57
|
-
"@sanity/comlink": "^
|
|
58
|
-
"@sanity/pkg-utils": "^
|
|
59
|
-
"@sanity/prettier-config": "^1.0.6",
|
|
60
|
+
"@sanity/comlink": "^4.0.1",
|
|
61
|
+
"@sanity/pkg-utils": "^10.9.2",
|
|
60
62
|
"@testing-library/jest-dom": "^6.9.1",
|
|
61
|
-
"@testing-library/react": "^16.3.
|
|
62
|
-
"@types/node": "^
|
|
63
|
-
"@types/react": "^19.2.
|
|
63
|
+
"@testing-library/react": "^16.3.2",
|
|
64
|
+
"@types/node": "^24.13.3",
|
|
65
|
+
"@types/react": "^19.2.17",
|
|
64
66
|
"@types/react-dom": "^19.2.3",
|
|
65
|
-
"@vitejs/plugin-react": "^
|
|
66
|
-
"@vitest/coverage-v8": "
|
|
67
|
-
"babel-plugin-react-compiler": "
|
|
68
|
-
"eslint": "^
|
|
69
|
-
"groq-js": "^
|
|
70
|
-
"jsdom": "^
|
|
71
|
-
"
|
|
72
|
-
"react": "^19.2.
|
|
73
|
-
"react-dom": "^19.2.
|
|
74
|
-
"rollup-plugin-visualizer": "^
|
|
75
|
-
"typescript": "^
|
|
76
|
-
"vite": "^
|
|
77
|
-
"vitest": "^
|
|
67
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
68
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
69
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
70
|
+
"eslint": "^10.6.0",
|
|
71
|
+
"groq-js": "^2.0.0",
|
|
72
|
+
"jsdom": "^29.1.1",
|
|
73
|
+
"oxfmt": "^0.58.0",
|
|
74
|
+
"react": "^19.2.7",
|
|
75
|
+
"react-dom": "^19.2.7",
|
|
76
|
+
"rollup-plugin-visualizer": "^7.0.1",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
78
|
+
"vite": "^8.1.5",
|
|
79
|
+
"vitest": "^4.1.10",
|
|
78
80
|
"@repo/config-eslint": "0.0.0",
|
|
79
81
|
"@repo/config-test": "0.0.1",
|
|
80
82
|
"@repo/package.bundle": "3.82.0",
|
|
81
|
-
"@repo/
|
|
82
|
-
"@repo/
|
|
83
|
+
"@repo/package.config": "0.0.1",
|
|
84
|
+
"@repo/tsconfig": "0.0.1"
|
|
83
85
|
},
|
|
84
86
|
"peerDependencies": {
|
|
85
|
-
"react": "^19.
|
|
86
|
-
"react-dom": "^19.
|
|
87
|
-
},
|
|
88
|
-
"engines": {
|
|
89
|
-
"node": ">=20.19"
|
|
90
|
-
},
|
|
91
|
-
"publishConfig": {
|
|
92
|
-
"access": "public"
|
|
87
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
88
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
93
89
|
},
|
|
90
|
+
"browserslist": "extends @sanity/browserslist-config",
|
|
94
91
|
"scripts": {
|
|
95
92
|
"build": "pkg build --strict --clean --check",
|
|
96
93
|
"build:bundle": "vite build --configLoader runner --config package.bundle.ts",
|
|
97
94
|
"clean": "rimraf dist",
|
|
98
95
|
"dev": "pkg watch",
|
|
99
96
|
"docs": "typedoc --json docs/typedoc.json --tsconfig ./tsconfig.dist.json",
|
|
100
|
-
"format": "
|
|
97
|
+
"format": "oxfmt",
|
|
101
98
|
"lint": "eslint .",
|
|
102
99
|
"test": "vitest run",
|
|
103
100
|
"test:coverage": "vitest run --coverage",
|
package/src/_exports/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export * from './sdk-react.ts'
|
|
2
2
|
export * from '@sanity/sdk'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// These shadow the core (strict) versions for @sanity/sdk-react consumers.
|
|
6
|
-
export {type DocumentHandle, type DocumentTypeHandle, type ResourceHandle} from './sdk-react.ts'
|
|
3
|
+
// React-layer handles shadow core equivalents when imported from @sanity/sdk-react
|
|
4
|
+
export type {DocumentHandle, DocumentTypeHandle, ResourceHandle} from './sdk-react.ts'
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module exports
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
// React-layer handle types (relaxed) — shadow core versions for @sanity/sdk-react consumers.
|
|
6
|
-
// resource is optional and resolved from context when not provided.
|
|
7
4
|
export {AuthBoundary, type AuthBoundaryProps} from '../components/auth/AuthBoundary'
|
|
8
5
|
export {SanityApp, type SanityAppProps} from '../components/SanityApp'
|
|
9
6
|
export {SDKProvider, type SDKProviderProps} from '../components/SDKProvider'
|
|
10
|
-
export {
|
|
11
|
-
type DocumentHandle as DocumentHandle,
|
|
12
|
-
type DocumentTypeHandle as DocumentTypeHandle,
|
|
13
|
-
type ResourceHandle as ResourceHandle,
|
|
14
|
-
} from '../config/handles'
|
|
7
|
+
export {type DocumentHandle, type DocumentTypeHandle, type ResourceHandle} from '../config/handles'
|
|
15
8
|
export {ComlinkTokenRefreshProvider} from '../context/ComlinkTokenRefresh'
|
|
16
9
|
export {renderSanityApp} from '../context/renderSanityApp'
|
|
17
10
|
export {ResourceProvider, type ResourceProviderProps} from '../context/ResourceProvider'
|
|
11
|
+
export {
|
|
12
|
+
SanityInstanceProvider,
|
|
13
|
+
type SanityInstanceProviderProps,
|
|
14
|
+
} from '../context/SanityInstanceProvider'
|
|
18
15
|
export {SDKStudioContext, type StudioWorkspaceHandle} from '../context/SDKStudioContext'
|
|
16
|
+
export {useCheckPermissions} from '../hooks/access/useCheckPermissions'
|
|
19
17
|
export {
|
|
20
18
|
useAgentGenerate,
|
|
21
19
|
useAgentPatch,
|
|
@@ -27,6 +25,15 @@ export {
|
|
|
27
25
|
type AgentResourceContextOptions,
|
|
28
26
|
useAgentResourceContext,
|
|
29
27
|
} from '../hooks/agent/useAgentResourceContext'
|
|
28
|
+
export {useApplication} from '../hooks/applications/useApplication'
|
|
29
|
+
export {useApplications} from '../hooks/applications/useApplications'
|
|
30
|
+
export {useCreateUserApplication} from '../hooks/applications/useCreateUserApplication'
|
|
31
|
+
export {useDeleteApplication} from '../hooks/applications/useDeleteApplication'
|
|
32
|
+
export {useDeleteUserApplication} from '../hooks/applications/useDeleteUserApplication'
|
|
33
|
+
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'
|
|
30
37
|
export {useAuthState} from '../hooks/auth/useAuthState'
|
|
31
38
|
export {useAuthToken} from '../hooks/auth/useAuthToken'
|
|
32
39
|
export {useCurrentUser} from '../hooks/auth/useCurrentUser'
|
|
@@ -48,10 +55,9 @@ export {
|
|
|
48
55
|
type WindowConnection,
|
|
49
56
|
type WindowMessageHandler,
|
|
50
57
|
} from '../hooks/comlink/useWindowConnection'
|
|
51
|
-
export {useResource} from '../hooks/context/
|
|
58
|
+
export {useResource} from '../hooks/context/useResource'
|
|
52
59
|
export {useSanityInstance} from '../hooks/context/useSanityInstance'
|
|
53
60
|
export {useDashboardNavigate} from '../hooks/dashboard/useDashboardNavigate'
|
|
54
|
-
export {useDispatchIntent} from '../hooks/dashboard/useDispatchIntent'
|
|
55
61
|
export {useManageFavorite} from '../hooks/dashboard/useManageFavorite'
|
|
56
62
|
export {
|
|
57
63
|
type NavigateToStudioResult,
|
|
@@ -59,8 +65,10 @@ export {
|
|
|
59
65
|
} from '../hooks/dashboard/useNavigateToStudioDocument'
|
|
60
66
|
export {useRecordDocumentHistoryEvent} from '../hooks/dashboard/useRecordDocumentHistoryEvent'
|
|
61
67
|
export {useStudioWorkspacesByProjectIdDataset} from '../hooks/dashboard/useStudioWorkspacesByProjectIdDataset'
|
|
68
|
+
export {useWindowTitle} from '../hooks/dashboard/useWindowTitle'
|
|
62
69
|
export {useDatasets} from '../hooks/datasets/useDatasets'
|
|
63
70
|
export {useApplyDocumentActions} from '../hooks/document/useApplyDocumentActions'
|
|
71
|
+
export {type CreateDocumentOverrides, useCreateDocument} from '../hooks/document/useCreateDocument'
|
|
64
72
|
export {useDocument} from '../hooks/document/useDocument'
|
|
65
73
|
export {useDocumentEvent} from '../hooks/document/useDocumentEvent'
|
|
66
74
|
export {useDocumentPermissions} from '../hooks/document/useDocumentPermissions'
|
|
@@ -71,6 +79,12 @@ export {
|
|
|
71
79
|
type DocumentsResponse,
|
|
72
80
|
useDocuments,
|
|
73
81
|
} from '../hooks/documents/useDocuments'
|
|
82
|
+
export {type FetcherHookResult} from '../hooks/helpers/createFetcherHook'
|
|
83
|
+
export {type MutationHookResult} from '../hooks/helpers/createMutationHook'
|
|
84
|
+
export {useInstallation} from '../hooks/installations/useInstallation'
|
|
85
|
+
export {useInstallations} from '../hooks/installations/useInstallations'
|
|
86
|
+
export {useOrganization} from '../hooks/organizations/useOrganization'
|
|
87
|
+
export {useOrganizations} from '../hooks/organizations/useOrganizations'
|
|
74
88
|
export {
|
|
75
89
|
type PaginatedDocumentsOptions,
|
|
76
90
|
type PaginatedDocumentsResponse,
|
|
@@ -91,17 +105,12 @@ export {useProject} from '../hooks/projects/useProject'
|
|
|
91
105
|
export {type ProjectWithoutMembers, useProjects} from '../hooks/projects/useProjects'
|
|
92
106
|
export {useQuery} from '../hooks/query/useQuery'
|
|
93
107
|
export {useActiveReleases} from '../hooks/releases/useActiveReleases'
|
|
108
|
+
export {useAllReleases} from '../hooks/releases/useAllReleases'
|
|
109
|
+
export {useApplyReleaseActions} from '../hooks/releases/useApplyReleaseActions'
|
|
94
110
|
export {usePerspective} from '../hooks/releases/usePerspective'
|
|
95
111
|
export {type UserResult, useUser} from '../hooks/users/useUser'
|
|
96
112
|
export {type UsersResult, useUsers} from '../hooks/users/useUsers'
|
|
97
113
|
export {REACT_SDK_VERSION} from '../version'
|
|
98
114
|
export {type DatasetsResponse, type SanityProjectMember} from '@sanity/client'
|
|
99
115
|
export type {Status as ComlinkStatus} from '@sanity/comlink'
|
|
100
|
-
|
|
101
|
-
// Strict core versions — available for users who need explicit resource
|
|
102
|
-
export {
|
|
103
|
-
type DocumentHandle as StrictDocumentHandle,
|
|
104
|
-
type DocumentTypeHandle as StrictDocumentTypeHandle,
|
|
105
|
-
type ResourceHandle as StrictResourceHandle,
|
|
106
|
-
} from '@sanity/sdk'
|
|
107
116
|
export {type SanityDocument, type SortOrderingItem} from '@sanity/types'
|
|
@@ -1,68 +1,209 @@
|
|
|
1
|
+
import {createSanityInstance, type SanityConfig} from '@sanity/sdk'
|
|
1
2
|
import {render} from '@testing-library/react'
|
|
2
3
|
import React from 'react'
|
|
3
|
-
import {describe, expect, it, vi} from 'vitest'
|
|
4
|
+
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
4
5
|
|
|
6
|
+
import {useDashboardOrganizationId} from '../hooks/auth/useDashboardOrganizationId'
|
|
7
|
+
import {resolveOrgResources} from '../utils/resolveOrgResources'
|
|
5
8
|
import {SDKProvider} from './SDKProvider'
|
|
6
9
|
|
|
10
|
+
const instance = createSanityInstance()
|
|
11
|
+
|
|
12
|
+
// Returns the same object on every call so the module-level WeakMap cache works across renders.
|
|
13
|
+
vi.mock('../hooks/context/useSanityInstance', () => {
|
|
14
|
+
return {useSanityInstance: () => instance}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
vi.mock('../hooks/auth/useDashboardOrganizationId', () => ({
|
|
18
|
+
useDashboardOrganizationId: vi.fn(),
|
|
19
|
+
}))
|
|
20
|
+
|
|
21
|
+
vi.mock('../utils/resolveOrgResources', () => ({
|
|
22
|
+
resolveOrgResources: vi.fn(),
|
|
23
|
+
}))
|
|
24
|
+
|
|
7
25
|
vi.mock('../context/ResourceProvider', () => ({
|
|
8
|
-
ResourceProvider: ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
26
|
+
ResourceProvider: ({
|
|
27
|
+
children,
|
|
28
|
+
// exclude fallback: it's a real ResourceProvider prop but not part of config
|
|
29
|
+
fallback: _fallback,
|
|
30
|
+
resource,
|
|
31
|
+
...config
|
|
32
|
+
}: {
|
|
33
|
+
children: React.ReactNode
|
|
34
|
+
fallback?: React.ReactNode
|
|
35
|
+
resource?: {projectId?: string; dataset?: string}
|
|
36
|
+
}) => (
|
|
37
|
+
<div
|
|
38
|
+
data-testid="resource-provider"
|
|
39
|
+
data-config={JSON.stringify(config)}
|
|
40
|
+
data-resource={JSON.stringify(resource ?? null)}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
),
|
|
15
45
|
}))
|
|
16
46
|
|
|
17
47
|
vi.mock('./auth/AuthBoundary', () => ({
|
|
18
|
-
AuthBoundary: ({children}: {children: React.ReactNode}) =>
|
|
19
|
-
|
|
20
|
-
|
|
48
|
+
AuthBoundary: ({children, projectIds}: {children: React.ReactNode; projectIds?: string[]}) => (
|
|
49
|
+
<div data-testid="auth-boundary" data-project-ids={JSON.stringify(projectIds ?? [])}>
|
|
50
|
+
{children}
|
|
51
|
+
</div>
|
|
52
|
+
),
|
|
21
53
|
}))
|
|
22
54
|
|
|
55
|
+
const mockResolveOrgResources = vi.mocked(resolveOrgResources)
|
|
56
|
+
const mockUseDashboardOrganizationId = vi.mocked(useDashboardOrganizationId)
|
|
57
|
+
|
|
23
58
|
describe('SDKProvider', () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
vi.clearAllMocks()
|
|
61
|
+
mockResolveOrgResources.mockResolvedValue({})
|
|
62
|
+
mockUseDashboardOrganizationId.mockReturnValue(undefined)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('renders single ResourceProvider with AuthBoundary for a single config', () => {
|
|
66
|
+
const config = {
|
|
67
|
+
projectId: 'test-project',
|
|
68
|
+
dataset: 'production',
|
|
28
69
|
}
|
|
29
70
|
|
|
30
|
-
const {getByTestId} = render(
|
|
31
|
-
<SDKProvider config={config}
|
|
71
|
+
const {getAllByTestId, getByTestId} = render(
|
|
72
|
+
<SDKProvider config={[config]} fallback={<div>Loading...</div>}>
|
|
32
73
|
<div>Child Content</div>
|
|
33
74
|
</SDKProvider>,
|
|
34
75
|
)
|
|
35
76
|
|
|
36
|
-
|
|
37
|
-
|
|
77
|
+
// Should create a single ResourceProvider
|
|
78
|
+
const providers = getAllByTestId('resource-provider')
|
|
79
|
+
expect(providers.length).toBe(1)
|
|
80
|
+
|
|
81
|
+
// Should create an AuthBoundary inside
|
|
38
82
|
expect(getByTestId('auth-boundary')).toBeInTheDocument()
|
|
39
83
|
|
|
40
|
-
//
|
|
41
|
-
expect(JSON.parse(
|
|
84
|
+
// Verify provider has the correct config
|
|
85
|
+
expect(JSON.parse(providers[0].getAttribute('data-config') || '{}')).toEqual({
|
|
42
86
|
projectId: 'test-project',
|
|
43
87
|
dataset: 'production',
|
|
44
88
|
})
|
|
45
89
|
})
|
|
46
90
|
|
|
47
|
-
it('renders
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
91
|
+
it('renders a single ResourceProvider using the first config when multiple configs are provided', () => {
|
|
92
|
+
const configs = [
|
|
93
|
+
{
|
|
94
|
+
projectId: 'project-1',
|
|
95
|
+
dataset: 'production',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
projectId: 'project-2',
|
|
99
|
+
dataset: 'staging',
|
|
100
|
+
},
|
|
101
|
+
]
|
|
53
102
|
|
|
54
|
-
const {getByTestId} = render(
|
|
55
|
-
<SDKProvider config={
|
|
103
|
+
const {getAllByTestId, getByTestId} = render(
|
|
104
|
+
<SDKProvider config={configs} fallback={<div>Loading...</div>}>
|
|
56
105
|
<div>Child Content</div>
|
|
57
106
|
</SDKProvider>,
|
|
58
107
|
)
|
|
59
108
|
|
|
60
|
-
|
|
61
|
-
|
|
109
|
+
// Should create a single ResourceProvider using the first config
|
|
110
|
+
const providers = getAllByTestId('resource-provider')
|
|
111
|
+
expect(providers.length).toBe(1)
|
|
62
112
|
|
|
63
|
-
|
|
113
|
+
// Should create an AuthBoundary inside
|
|
114
|
+
expect(getByTestId('auth-boundary')).toBeInTheDocument()
|
|
115
|
+
|
|
116
|
+
// Verify the provider uses the first config
|
|
117
|
+
expect(JSON.parse(providers[0].getAttribute('data-config') || '{}')).toEqual({
|
|
64
118
|
projectId: 'project-1',
|
|
65
119
|
dataset: 'production',
|
|
66
120
|
})
|
|
67
121
|
})
|
|
122
|
+
|
|
123
|
+
it('preserves non-resource config fields (e.g. studio auth, perspective) on the root provider', () => {
|
|
124
|
+
const tokenSource = {subscribe: () => ({unsubscribe: () => {}})}
|
|
125
|
+
const config: SanityConfig = {
|
|
126
|
+
projectId: 'test-project',
|
|
127
|
+
dataset: 'production',
|
|
128
|
+
perspective: 'published',
|
|
129
|
+
studio: {authenticated: true, auth: {token: tokenSource}},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const {getAllByTestId} = render(
|
|
133
|
+
<SDKProvider config={config} fallback={<div>Loading...</div>}>
|
|
134
|
+
<div>Child Content</div>
|
|
135
|
+
</SDKProvider>,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
const providers = getAllByTestId('resource-provider')
|
|
139
|
+
// The full first config is spread onto the root ResourceProvider so the
|
|
140
|
+
// root SanityInstance retains auth/perspective/etc. (The token source is a
|
|
141
|
+
// function and doesn't survive JSON serialization, so assert on the
|
|
142
|
+
// serializable fields and that the studio config object is carried through.)
|
|
143
|
+
const spreadConfig = JSON.parse(providers[0].getAttribute('data-config') || '{}')
|
|
144
|
+
expect(spreadConfig).toMatchObject({
|
|
145
|
+
projectId: 'test-project',
|
|
146
|
+
dataset: 'production',
|
|
147
|
+
perspective: 'published',
|
|
148
|
+
studio: {authenticated: true},
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('synthesizes the default resource from the first config when none is explicit', () => {
|
|
153
|
+
const config = {projectId: 'test-project', dataset: 'production'}
|
|
154
|
+
|
|
155
|
+
const {getAllByTestId} = render(
|
|
156
|
+
<SDKProvider config={config} fallback={<div>Loading...</div>}>
|
|
157
|
+
<div>Child Content</div>
|
|
158
|
+
</SDKProvider>,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
const providers = getAllByTestId('resource-provider')
|
|
162
|
+
expect(JSON.parse(providers[0].getAttribute('data-resource') || 'null')).toEqual({
|
|
163
|
+
projectId: 'test-project',
|
|
164
|
+
dataset: 'production',
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('uses an explicitly provided "default" resource over the config-derived one', () => {
|
|
169
|
+
const config = {projectId: 'config-project', dataset: 'production'}
|
|
170
|
+
const resources = {default: {projectId: 'explicit-project', dataset: 'staging'}}
|
|
171
|
+
|
|
172
|
+
const {getAllByTestId} = render(
|
|
173
|
+
<SDKProvider config={config} resources={resources} fallback={<div>Loading...</div>}>
|
|
174
|
+
<div>Child Content</div>
|
|
175
|
+
</SDKProvider>,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
const providers = getAllByTestId('resource-provider')
|
|
179
|
+
// Config fields still flow through for instance creation…
|
|
180
|
+
expect(JSON.parse(providers[0].getAttribute('data-config') || '{}')).toEqual(config)
|
|
181
|
+
// …but the explicit default resource wins as the resource context value.
|
|
182
|
+
expect(JSON.parse(providers[0].getAttribute('data-resource') || 'null')).toEqual(
|
|
183
|
+
resources.default,
|
|
184
|
+
)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('collects deduped projectIds from both config and explicit resources', () => {
|
|
188
|
+
const configs = [
|
|
189
|
+
{projectId: 'project-1', dataset: 'production'},
|
|
190
|
+
{projectId: 'project-2', dataset: 'production'},
|
|
191
|
+
]
|
|
192
|
+
const resources = {
|
|
193
|
+
// duplicates project-1 (should be deduped)
|
|
194
|
+
default: {projectId: 'project-1', dataset: 'production'},
|
|
195
|
+
other: {projectId: 'project-3', dataset: 'production'},
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const {getByTestId} = render(
|
|
199
|
+
<SDKProvider config={configs} resources={resources} fallback={<div>Loading...</div>}>
|
|
200
|
+
<div>Child Content</div>
|
|
201
|
+
</SDKProvider>,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
const projectIds = JSON.parse(
|
|
205
|
+
getByTestId('auth-boundary').getAttribute('data-project-ids') || '[]',
|
|
206
|
+
)
|
|
207
|
+
expect([...projectIds].sort()).toEqual(['project-1', 'project-2', 'project-3'])
|
|
208
|
+
})
|
|
68
209
|
})
|
|
@@ -1,65 +1,124 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DEFAULT_RESOURCE_NAME,
|
|
3
2
|
type DocumentResource,
|
|
4
3
|
isDatasetResource,
|
|
4
|
+
isImportError,
|
|
5
5
|
type SanityConfig,
|
|
6
6
|
} from '@sanity/sdk'
|
|
7
|
-
import {type ReactElement, type ReactNode, useMemo} from 'react'
|
|
7
|
+
import {type ReactElement, type ReactNode, useEffect, useMemo} from 'react'
|
|
8
|
+
import {ErrorBoundary, type FallbackProps} from 'react-error-boundary'
|
|
8
9
|
|
|
10
|
+
import {DEFAULT_RESOURCE_NAME} from '../constants'
|
|
11
|
+
import {OrganizationResourcesProvider} from '../context/OrganizationResourcesProvider'
|
|
9
12
|
import {ResourceProvider} from '../context/ResourceProvider'
|
|
10
|
-
import {ResourcesContext} from '../context/ResourcesContext'
|
|
11
13
|
import {AuthBoundary, type AuthBoundaryProps} from './auth/AuthBoundary'
|
|
14
|
+
import {ChunkLoadError} from './errors/ChunkLoadError'
|
|
15
|
+
import {clearChunkReloadFlag} from './errors/chunkReloadStorage'
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* @internal
|
|
15
19
|
*/
|
|
16
20
|
export interface SDKProviderProps extends AuthBoundaryProps {
|
|
17
21
|
children: ReactNode
|
|
18
|
-
config: SanityConfig
|
|
19
|
-
/**
|
|
20
|
-
* Named document resources map. Provided to `ResourcesContext` for
|
|
21
|
-
* name-based resource resolution in hooks.
|
|
22
|
-
*/
|
|
23
|
-
resources?: Record<string, DocumentResource>
|
|
22
|
+
config: SanityConfig | SanityConfig[]
|
|
24
23
|
fallback: ReactNode
|
|
24
|
+
resources?: Record<string, DocumentResource>
|
|
25
|
+
/** When set, automatically fetches and registers the organization's media library and canvas as named resources. */
|
|
26
|
+
inferMediaLibraryAndCanvas?: boolean
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
|
-
*
|
|
30
|
+
* Clears the chunk-reload flag once children render successfully past the
|
|
31
|
+
* top-level boundary, so a future incident in the same session can trigger
|
|
32
|
+
* another automatic reload.
|
|
29
33
|
*/
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return [...ids]
|
|
34
|
+
function ResetChunkReloadFlagOnMount(): null {
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
clearChunkReloadFlag()
|
|
37
|
+
}, [])
|
|
38
|
+
return null
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
42
|
* @internal
|
|
40
43
|
*
|
|
41
44
|
* Top-level context provider that provides access to the Sanity SDK.
|
|
42
|
-
*
|
|
43
|
-
* Creates a single `ResourceProvider` (and therefore a single `SanityInstance`)
|
|
44
|
-
* for the given config. Resource resolution is handled by `ResourcesContext`
|
|
45
|
-
* and the `"default"` named resource.
|
|
46
45
|
*/
|
|
47
46
|
export function SDKProvider({
|
|
48
47
|
children,
|
|
49
48
|
config,
|
|
50
|
-
resources = {},
|
|
51
49
|
fallback,
|
|
50
|
+
inferMediaLibraryAndCanvas,
|
|
52
51
|
...props
|
|
53
52
|
}: SDKProviderProps): ReactElement {
|
|
54
|
-
|
|
53
|
+
// For legacy config support, extract the first config object as a default resource,
|
|
54
|
+
// matching the legacy behavior nesting ResourceProviders with the first config closest to users' application code.
|
|
55
|
+
// This should be removed when we remove legacy config support.
|
|
56
|
+
const defaultConfig = Array.isArray(config) ? config[0] : config
|
|
57
|
+
const defaultProjectId = defaultConfig?.projectId
|
|
58
|
+
const defaultDataset = defaultConfig?.dataset
|
|
55
59
|
|
|
56
|
-
const
|
|
60
|
+
const resourcesValue = useMemo(() => {
|
|
61
|
+
const explicit = props.resources ?? {}
|
|
62
|
+
if (defaultProjectId && defaultDataset && !Object.hasOwn(explicit, DEFAULT_RESOURCE_NAME)) {
|
|
63
|
+
return {
|
|
64
|
+
[DEFAULT_RESOURCE_NAME]: {
|
|
65
|
+
projectId: defaultProjectId,
|
|
66
|
+
dataset: defaultDataset,
|
|
67
|
+
},
|
|
68
|
+
...explicit,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return explicit
|
|
72
|
+
}, [defaultProjectId, defaultDataset, props.resources])
|
|
73
|
+
|
|
74
|
+
// Collect all projectIds from both resources and config, deduped so
|
|
75
|
+
// AuthBoundary doesn't verify the same project more than once.
|
|
76
|
+
const projectIds = useMemo(
|
|
77
|
+
() =>
|
|
78
|
+
Array.from(
|
|
79
|
+
new Set(
|
|
80
|
+
[
|
|
81
|
+
...Object.values(resourcesValue)
|
|
82
|
+
.filter(isDatasetResource)
|
|
83
|
+
.map((resource) => resource.projectId),
|
|
84
|
+
...(Array.isArray(config) ? config : [config]).map((configObj) => configObj.projectId),
|
|
85
|
+
].filter((id): id is string => !!id),
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
[resourcesValue, config],
|
|
89
|
+
)
|
|
57
90
|
|
|
58
91
|
return (
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
92
|
+
<ErrorBoundary FallbackComponent={ChunkAwareFallback}>
|
|
93
|
+
<ResetChunkReloadFlagOnMount />
|
|
94
|
+
{/* Spread the first config so SanityInstance can use the auth,
|
|
95
|
+
perspective, and other config fields; `resource` lets an explicitly
|
|
96
|
+
provided `default` resource override the config-derived resource. */}
|
|
97
|
+
<ResourceProvider
|
|
98
|
+
{...defaultConfig}
|
|
99
|
+
resource={resourcesValue[DEFAULT_RESOURCE_NAME]}
|
|
100
|
+
fallback={fallback}
|
|
101
|
+
>
|
|
102
|
+
<AuthBoundary {...props} projectIds={projectIds}>
|
|
103
|
+
{/* OrganizationResourcesProvider wraps ResourcesContext.
|
|
104
|
+
It merges explicit resources with lazily inferred org resources (media
|
|
105
|
+
library, canvas) and provides the combined map to the subtree. */}
|
|
106
|
+
<OrganizationResourcesProvider
|
|
107
|
+
resources={resourcesValue}
|
|
108
|
+
inferMediaLibraryAndCanvas={inferMediaLibraryAndCanvas}
|
|
109
|
+
>
|
|
110
|
+
{children}
|
|
111
|
+
</OrganizationResourcesProvider>
|
|
112
|
+
</AuthBoundary>
|
|
113
|
+
</ResourceProvider>
|
|
114
|
+
</ErrorBoundary>
|
|
64
115
|
)
|
|
65
116
|
}
|
|
117
|
+
|
|
118
|
+
function ChunkAwareFallback(fallbackProps: FallbackProps): ReactElement {
|
|
119
|
+
if (isImportError(fallbackProps.error)) {
|
|
120
|
+
return <ChunkLoadError {...fallbackProps} />
|
|
121
|
+
}
|
|
122
|
+
// Re-throw so downstream boundaries (e.g. AuthBoundary) handle other errors.
|
|
123
|
+
throw fallbackProps.error
|
|
124
|
+
}
|