Skip to content

Commit 969d70e

Browse files
refactor: new resource architecture and updated document handles (#374)
* refactor: new store management and action binding (#344) * refactor: update store management * refactor(react): enhance disposal management in ResourceProvider * refactor(client): update client to new store management (#345) * feat(client): enhance client management with improved token handling and configuration validation - Refactored client store to manage clients based on token changes and configuration updates. - Introduced validation for disallowed configuration keys in `getClient`. - Updated tests to cover new client creation logic and token handling scenarios. - Enhanced `useClient` hook to utilize the new configuration structure. * refactor(auth): update auth to new store management (#346) * refactor(auth): streamline authentication store and improve test coverage - Refactored authentication store to utilize a more modular structure with improved action binding. - Updated tests for `authStore`, `fetchLoginUrls`, `handleCallback`, and `logout`. - Removed deprecated interfaces and streamlined state management for better maintainability. * refactor: update query, projection, and preview stores (#347) * refactor: update query, projection, and preview stores - Deleted the `createLiveEventSubscriber` function and its associated test file - Refactored preview and projection stores to eliminate dependencies on the removed functionality. - Moved `hashString` utility for consistent string hashing, along with corresponding tests. - Updated various components and hooks to utilize the new document handle structure. * fix: improve preview/projection handling and abort control - Remove unused documentTypes from PreviewStoreState - Implement proper abort control for in-flight requests in preview/projection - Add PREVIEW_PERSPECTIVE and PROJECTION_PERSPECTIVE constants - Optimize subscription handling with isSetEqual helper - Fix useQuery hook to use useRef instead of useState for AbortController - Add proper error handling and state management for preview/projection queries - Improve test coverage for abort scenarios * refactor(react): remove deprecated `document` property * fix(react): improve useQuery hook's abort signal handling - Update useQuery to capture the current abort signal in a local variable during suspension - Refactor the return statement to use useMemo since the compiler is disabled * fix: use `v2025-02-19` API version for query store * fix: update QUERY_STORE_API_VERSION to use 'vX' for text::query groq function * refactor(comlink): update to new store management (#348) * refactor(comlink): enhance store structure and improve test coverage - Refactored comlink controller and node to utilize a more modular structure with action binding. - Updated tests for comlink actions including `destroyController`, `getOrCreateChannel`, and `releaseNode` to improve coverage and reliability. - Adjusted state management in tests to align with the new store structure. - Renamed document handle properties in hooks for consistency and clarity. * refactor: rename workspace handling - Rename `useStudioWorkspacesByResourceId` to `useStudioWorkspacesByProjectIdDataset` for clarity - Remove dependency on resource ID parsing in favor of direct projectId/dataset usage - Remove documentTypes tracking in preview state test - Update workspace navigation to use direct projectId/dataset instead of parsing from resourceId - Improve error messages with more specific context - Remove old test files in favor of new implementation * refactor(document): update to new store management (#349) * refactor(document): standardize document handle structure and enhance action handling - Updated document handle properties to use `documentId` and `documentType` for consistency across the codebase. - Refactored document action functions to utilize the new document handle structure. - Improved test coverage for document actions and applied actions to ensure correct behavior with the updated structure. - Enhanced hooks and components to align with the new document handling conventions, ensuring better integration with the Sanity instance context. * refactor: new store management for users, projects, and datasets (#350) * refactor(users): enhance user store and hooks for improved functionality - Refactored user store to streamline state management and improve action handling. - Updated `useUsers` hook to support project and organization parameters, enhancing flexibility. - Improved test coverage for user-related hooks and store functionalities. - Introduced new utility functions for better key management and state resolution. - Removed deprecated tests and consolidated user fetching logic for clarity and maintainability. * refactor(project): improve project fetching logic and enhance parameter handling - Updated project fetcher to utilize projectId from options or instance for better flexibility. - Refactored createFetcherStore to include instance in StoreEntry for improved context management. - Enhanced initialization and subscription handling for clearer state management and observability. * fix: update API_VERSIONs and tag prefix * fix: add `@function` back * feat(kitchensink-react): add OrgDocumentExplorerRoute (#351) * refactor(kitchensink-react): standardize document handling and enhance routing - Removed deprecated `@sanity/mutate` dependency from the project. - Introduced `OrgDocumentExplorerRoute` for improved document organization and navigation. - Updated document handling to use `documentId` and `documentType` consistently across components. - Refactored document-related components to enhance readability and maintainability. - Improved user interface elements for document previews and lists, ensuring better user experience. - Adjusted routing structure to accommodate new document exploration features. * refactor(kitchensink-react): update orgdocumentexplorer fix: update import to usePaginatedDocuments * docs: add advanced resource management guide * docs: update migration guide * docs: update migration guide examples * refactor: remove comments from exports * fix: fix bug with document types resetting * refactor: add SDKProvider back in * chore: delete old guide * chore: use projectId and dataset in debug store names * docs: remove tip about Advanced Resource Management Guide from Migration Guide --------- Co-authored-by: Ryan Bonial <[email protected]>
1 parent 954d7ae commit 969d70e

File tree

204 files changed

+9919
-6419
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

204 files changed

+9919
-6419
lines changed

apps/kitchensink-react/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"dependencies": {
1616
"@paramour/css": "1.0.0-rc.2",
1717
"@sanity/icons": "^3.7.0",
18-
"@sanity/mutate": "^0.12.3",
1918
"@sanity/sdk": "workspace:*",
2019
"@sanity/sdk-react": "workspace:*",
2120
"@sanity/types": "^3.79.0",

apps/kitchensink-react/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const sanityConfigs: SanityConfig[] = [
2323
export function App(): JSX.Element {
2424
return (
2525
<ThemeProvider theme={theme}>
26-
<SanityApp sanityConfigs={sanityConfigs} fallback={<Spinner />}>
26+
<SanityApp fallback={<Spinner />} config={sanityConfigs}>
2727
<BrowserRouter>
2828
<AppRoutes />
2929
</BrowserRouter>

apps/kitchensink-react/src/AppRoutes.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {DocumentGridRoute} from './DocumentCollection/DocumentGridRoute'
99
import {DocumentListRoute} from './DocumentCollection/DocumentListRoute'
1010
import {DocumentProjectionRoute} from './DocumentCollection/DocumentProjectionRoute'
1111
import {MultiResourceRoute} from './DocumentCollection/MultiResourceRoute'
12+
import {OrgDocumentExplorerRoute} from './DocumentCollection/OrgDocumentExplorerRoute'
1213
import {SearchRoute} from './DocumentCollection/SearchRoute'
1314
import {ProjectAuthHome} from './ProjectAuthentication/ProjectAuthHome'
1415
import {ProtectedRoute} from './ProtectedRoute'
@@ -37,6 +38,10 @@ const documentCollectionRoutes = [
3738
path: 'multi-resource',
3839
element: <MultiResourceRoute />,
3940
},
41+
{
42+
path: 'org-document-explorer',
43+
element: <OrgDocumentExplorerRoute />,
44+
},
4045
{
4146
path: 'search',
4247
element: <SearchRoute />,

apps/kitchensink-react/src/DocumentCollection/DocumentDashboardInteractionsRoute.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,19 @@ import {DocumentListLayout} from '../components/DocumentListLayout/DocumentListL
1212
import {DocumentPreview} from './DocumentPreview'
1313
import {LoadMore} from './LoadMore'
1414

15-
function ActionButtons({document}: {document: DocumentHandle}) {
15+
function ActionButtons(docHandle: DocumentHandle) {
1616
const {
1717
favorite,
1818
unfavorite,
1919
isFavorited,
2020
isConnected: isFavoriteConnected,
21-
} = useManageFavorite({
22-
documentId: document._id,
23-
documentType: document._type,
24-
resourceType: 'studio',
25-
resourceId: document.resourceId,
26-
})
21+
} = useManageFavorite({...docHandle, resourceType: 'studio'})
2722
const {recordEvent, isConnected: isHistoryConnected} = useRecordDocumentHistoryEvent({
28-
documentId: document._id,
29-
documentType: document._type,
23+
...docHandle,
3024
resourceType: 'studio',
31-
resourceId: document.resourceId,
3225
})
3326
const {navigateToStudioDocument, isConnected: isNavigateConnected} =
34-
useNavigateToStudioDocument(document)
27+
useNavigateToStudioDocument(docHandle)
3528

3629
return (
3730
<Flex gap={2} padding={2}>
@@ -69,10 +62,6 @@ export function DocumentDashboardInteractionsRoute(): JSX.Element {
6962
orderings: [{field: '_updatedAt', direction: 'desc'}],
7063
})
7164

72-
// since resourceIds are being refactored at the moment, hardcode the resourceId for now
73-
// (ideally, they come from document handles returned in the "data" param per document)
74-
const datasetResourceId = 'document:ppsg7ml5.test:' // Note: each doc._id will be appended to this
75-
7665
return (
7766
<Box padding={4}>
7867
<Heading as="h1" size={5}>
@@ -81,9 +70,9 @@ export function DocumentDashboardInteractionsRoute(): JSX.Element {
8170
<Box paddingY={5}>
8271
<DocumentListLayout>
8372
{data.map((doc) => (
84-
<Box key={doc._id}>
85-
<DocumentPreview document={doc} />
86-
<ActionButtons document={{...doc, resourceId: `${datasetResourceId}${doc._id}`}} />
73+
<Box key={doc.documentId}>
74+
<DocumentPreview {...doc} />
75+
<ActionButtons {...doc} />
8776
</Box>
8877
))}
8978
<LoadMore hasMore={hasMore} isPending={isPending} onLoadMore={loadMore} />

apps/kitchensink-react/src/DocumentCollection/DocumentEditorRoute.tsx

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
/* eslint-disable no-console */
2-
import {at, patch, set} from '@sanity/mutate'
32
import {
43
createDocument,
54
deleteDocument,
@@ -27,34 +26,32 @@ interface Author extends SanityDocument {
2726
name?: string
2827
}
2928

30-
const doc: DocumentHandle<Author> = {
31-
_type: 'author',
32-
_id: 'db06bc9e-4608-465a-9551-a10cef478037',
33-
resourceId: 'document:ppsg7ml5.test:db06bc9e-4608-465a-9551-a10cef478037',
29+
const docHandle: DocumentHandle<Author> = {
30+
documentType: 'author',
31+
documentId: 'db06bc9e-4608-465a-9551-a10cef478037',
32+
projectId: 'ppsg7ml5',
33+
dataset: 'test',
3434
}
3535

3636
function Editor() {
37-
useDocumentEvent((e) => console.log(e), doc)
38-
const synced = useDocumentSyncStatus(doc)
37+
useDocumentEvent((e) => console.log(e), docHandle)
38+
const synced = useDocumentSyncStatus(docHandle)
3939
const apply = useApplyDocumentActions()
4040

41-
const canEdit = useDocumentPermissions(editDocument(doc))
42-
const canCreate = useDocumentPermissions(createDocument(doc))
43-
const canPublish = useDocumentPermissions(publishDocument(doc))
44-
const canDelete = useDocumentPermissions(deleteDocument(doc))
45-
const canUnpublish = useDocumentPermissions(unpublishDocument(doc))
46-
const canDiscard = useDocumentPermissions(discardDocument(doc))
41+
const canEdit = useDocumentPermissions(editDocument(docHandle))
42+
const canCreate = useDocumentPermissions(createDocument(docHandle))
43+
const canPublish = useDocumentPermissions(publishDocument(docHandle))
44+
const canDelete = useDocumentPermissions(deleteDocument(docHandle))
45+
const canUnpublish = useDocumentPermissions(unpublishDocument(docHandle))
46+
const canDiscard = useDocumentPermissions(discardDocument(docHandle))
4747

48-
const name = useDocument(doc, 'name') ?? ''
49-
const setName = useEditDocument(doc, 'name')
48+
const name = useDocument(docHandle, 'name') ?? ''
49+
const setName = useEditDocument(docHandle, 'name')
5050

5151
const [value, setValue] = useState('')
5252

53-
const changeNameToValue = editDocument(patch(doc._id, at('name', set(value))))
54-
const canChangeNameToValue = useDocumentPermissions(changeNameToValue)
55-
56-
const document = useDocument(doc)
57-
const setDocument = useEditDocument(doc)
53+
const document = useDocument(docHandle)
54+
const setDocument = useEditDocument(docHandle)
5855

5956
return (
6057
<Box padding={4}>
@@ -69,7 +66,7 @@ function Editor() {
6966
<span>
7067
<Button
7168
disabled={!canCreate.allowed}
72-
onClick={() => apply(createDocument(doc))}
69+
onClick={() => apply(createDocument(docHandle))}
7370
text="Create"
7471
/>
7572
</span>
@@ -78,7 +75,7 @@ function Editor() {
7875
<span>
7976
<Button
8077
disabled={!canDiscard.allowed}
81-
onClick={() => apply(discardDocument(doc))}
78+
onClick={() => apply(discardDocument(docHandle))}
8279
text="Discard"
8380
/>
8481
</span>
@@ -88,7 +85,7 @@ function Editor() {
8885
<Button
8986
disabled={!canPublish.allowed}
9087
onClick={async () => {
91-
const response = await apply(publishDocument(doc))
88+
const response = await apply(publishDocument(docHandle))
9289
await response.submitted()
9390
}}
9491
text="Publish"
@@ -99,7 +96,7 @@ function Editor() {
9996
<span>
10097
<Button
10198
disabled={!canUnpublish.allowed}
102-
onClick={() => apply(unpublishDocument(doc))}
99+
onClick={() => apply(unpublishDocument(docHandle))}
103100
text="Unpublish"
104101
/>
105102
</span>
@@ -108,20 +105,11 @@ function Editor() {
108105
<span>
109106
<Button
110107
disabled={!canDelete.allowed}
111-
onClick={() => apply(deleteDocument(doc))}
108+
onClick={() => apply(deleteDocument(docHandle))}
112109
text="Delete"
113110
/>
114111
</span>
115112
</Tooltip>
116-
<Tooltip content={canChangeNameToValue.message}>
117-
<span>
118-
<Button
119-
disabled={!canChangeNameToValue.allowed}
120-
onClick={() => apply(changeNameToValue)}
121-
text="Change name to value"
122-
/>
123-
</span>
124-
</Tooltip>
125113

126114
<div>{synced ? 'Synced' : 'Syncing…'}</div>
127115
</div>

apps/kitchensink-react/src/DocumentCollection/DocumentGridRoute.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function DocumentGridRoute(): JSX.Element {
1919
<Box paddingY={5}>
2020
<DocumentGridLayout>
2121
{data.map((doc) => (
22-
<DocumentPreview key={doc._id} document={doc} />
22+
<DocumentPreview key={doc.documentId} {...doc} />
2323
))}
2424
</DocumentGridLayout>
2525
<Button text="Load more" mode="ghost" disabled={isPending || !hasMore} onClick={loadMore} />

apps/kitchensink-react/src/DocumentCollection/DocumentListRoute.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ export function DocumentListRoute(): JSX.Element {
1919
</Heading>
2020
<Box paddingY={5}>
2121
<DocumentListLayout>
22-
{data.map((doc) => (
23-
<DocumentPreview key={doc._id} document={doc} />
22+
{data.map((docHandle) => (
23+
<DocumentPreview key={docHandle.documentId} {...docHandle} />
2424
))}
2525
<LoadMore hasMore={hasMore} isPending={isPending} onLoadMore={loadMore} />
2626
</DocumentListLayout>

apps/kitchensink-react/src/DocumentCollection/DocumentPreview.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,25 @@ import {ErrorBoundary} from 'react-error-boundary'
55

66
import {DocumentPreviewLayout} from '../components/DocumentPreviewLayout/DocumentPreviewLayout'
77

8-
interface DocumentPreviewProps {
9-
document: DocumentHandle
10-
}
11-
12-
export function DocumentPreview(props: DocumentPreviewProps): React.ReactNode {
8+
export function DocumentPreview(docHandle: DocumentHandle): React.ReactNode {
139
return (
1410
<li>
1511
<ErrorBoundary
1612
fallback={<DocumentPreviewLayout title="Error" subtitle="This preview failed to render." />}
1713
>
1814
<Suspense fallback={<DocumentPreviewLayout title="Loading" />}>
19-
<DocumentPreviewResolved {...props} />
15+
<DocumentPreviewResolved {...docHandle} />
2016
</Suspense>
2117
</ErrorBoundary>
2218
</li>
2319
)
2420
}
2521

26-
function DocumentPreviewResolved({document}: DocumentPreviewProps): React.ReactNode {
22+
function DocumentPreviewResolved(docHandle: DocumentHandle): React.ReactNode {
2723
const ref = useRef(null)
2824
const {
2925
data: {title, subtitle, media, status},
30-
} = usePreview({document, ref})
26+
} = usePreview({...docHandle, ref})
3127

3228
let statusLabel
3329
if (status?.lastEditedPublishedAt && status?.lastEditedDraftAt) {
@@ -50,7 +46,7 @@ function DocumentPreviewResolved({document}: DocumentPreviewProps): React.ReactN
5046
ref={ref}
5147
title={title}
5248
subtitle={subtitle}
53-
docType={document._type}
49+
docType={docHandle.documentType}
5450
media={media}
5551
status={statusLabel}
5652
onClick={() => alert(`Hello from ${title}`)}

apps/kitchensink-react/src/DocumentCollection/DocumentProjectionRoute.tsx

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,26 @@ interface AuthorProjection {
1414
}
1515

1616
// Component for displaying projection data with proper error handling
17-
function ProjectionData({data}: {data: AuthorProjection}) {
17+
function ProjectionData(docHandle: DocumentHandle) {
18+
const ref = useRef<HTMLTableCellElement>(null)
19+
const {data} = useProjection<AuthorProjection>({
20+
...docHandle,
21+
ref,
22+
projection: `{
23+
name,
24+
"address": "City: " + address.city + ", Country: " + address.country,
25+
"favoriteBookTitles": favoriteBooks[]->{title}.title
26+
}`,
27+
})
28+
1829
return (
1930
<>
20-
<TD padding={2}>{data.name || 'Untitled'}</TD>
31+
<TD ref={ref} padding={2}>
32+
{data.name || 'Untitled'}
33+
</TD>
2134
<TD padding={2}>{data.address || 'No address'}</TD>
2235
<TD padding={2}>
23-
{data.favoriteBookTitles.filter(Boolean).join(', ') || 'No favorite books'}
36+
{data.favoriteBookTitles?.filter(Boolean).join(', ') || 'No favorite books'}
2437
</TD>
2538
</>
2639
)
@@ -53,24 +66,12 @@ function ProjectionError({error}: {error: Error}): ReactNode {
5366
}
5467

5568
// Component for displaying a single author row with projection data
56-
function AuthorRow({document}: {document: DocumentHandle}) {
57-
const ref = useRef<HTMLTableRowElement>(null)
58-
59-
const {data} = useProjection<AuthorProjection>({
60-
document,
61-
projection: `{
62-
name,
63-
"address": "City: " + address.city + ", Country: " + address.country,
64-
"favoriteBookTitles": favoriteBooks[]->{title}.title
65-
}`,
66-
ref,
67-
})
68-
69+
function AuthorRow(docHandle: DocumentHandle) {
6970
return (
70-
<TR ref={ref}>
71+
<TR>
7172
<ErrorBoundary fallbackRender={({error}) => <ProjectionError error={error} />}>
7273
<Suspense fallback={<ProjectionFallback />}>
73-
<ProjectionData data={data} />
74+
<ProjectionData {...docHandle} />
7475
</Suspense>
7576
</ErrorBoundary>
7677
</TR>
@@ -289,7 +290,7 @@ export function DocumentProjectionRoute(): JSX.Element {
289290
</thead>
290291
<tbody>
291292
{data.length > 0 ? (
292-
data.map((doc) => <AuthorRow key={doc._id} document={doc} />)
293+
data.map((doc) => <AuthorRow key={doc.documentId} {...doc} />)
293294
) : (
294295
<TR>
295296
<TD padding={2}>

apps/kitchensink-react/src/DocumentCollection/MultiResourceRoute.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ export function MultiResourceRoute(): JSX.Element {
3434
}[]
3535
}
3636
const doc: DocumentHandle<Author> = {
37-
_type: 'author',
38-
_id: 'db06bc9e-4608-465a-9551-a10cef478037',
39-
resourceId: 'document:ppsg7ml5.test:db06bc9e-4608-465a-9551-a10cef478037',
37+
documentType: 'author',
38+
documentId: 'db06bc9e-4608-465a-9551-a10cef478037',
39+
projectId: 'ppsg7ml5',
40+
dataset: 'test',
4041
}
4142

4243
const doc2: DocumentHandle<Dog> = {
43-
_type: 'dog',
44-
_id: 'acc11e96-1a01-4907-bd0e-e8347217cf2f',
45-
resourceId: 'document:ezwd8xes.production:acc11e96-1a01-4907-bd0e-e8347217cf2f',
44+
documentType: 'dog',
45+
documentId: 'acc11e96-1a01-4907-bd0e-e8347217cf2f',
46+
projectId: 'ezwd8xes',
47+
dataset: 'production',
4648
}
4749

4850
const setAuthorName = useEditDocument(doc, 'name')

0 commit comments

Comments
 (0)