Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/kitchensink-react/src/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import {ProtectedRoute} from './ProtectedRoute'
import {DashboardContextRoute} from './routes/DashboardContextRoute'
import {DashboardWorkspacesRoute} from './routes/DashboardWorkspacesRoute'
import ExperimentalResourceClientRoute from './routes/ExperimentalResourceClientRoute'
import {ProjectsRoute} from './routes/ProjectsRoute'
import MediaLibraryRoute from './routes/MediaLibraryRoute'
import {PerspectivesRoute} from './routes/PerspectivesRoute'
import {ProjectsRoute} from './routes/ProjectsRoute'
import {ReleasesRoute} from './routes/releases/ReleasesRoute'
import {UserDetailRoute} from './routes/UserDetailRoute'
import {UsersRoute} from './routes/UsersRoute'
Expand Down Expand Up @@ -68,6 +69,10 @@ const documentCollectionRoutes = [
path: 'experimental-resource-client',
element: <ExperimentalResourceClientRoute />,
},
{
path: 'media-library',
element: <MediaLibraryRoute />,
},
{
path: 'presence',
element: <PresenceRoute />,
Expand Down
74 changes: 74 additions & 0 deletions apps/kitchensink-react/src/routes/MediaLibraryRoute.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {useQuery} from '@sanity/sdk-react'
import {Card, Spinner, Text} from '@sanity/ui'
import {type JSX, useState} from 'react'

export default function MediaLibraryRoute(): JSX.Element {
const [query] = useState('*[_type == "sanity.asset"][0...10] | order(_id desc)')
const [isLoading] = useState(false)

// for now, hardcoded. should be inferred from org later on
const {data, isPending} = useQuery({
mediaLibraryId: 'mlPGY7BEqt52',
query,
})

return (
<div style={{padding: '2rem', maxWidth: '800px', margin: '0 auto'}}>
<Text size={4} weight="bold" style={{marginBottom: '2rem', color: 'white'}}>
Media Library Query Demo
</Text>

<Text size={2} style={{marginBottom: '2rem'}}>
This route demonstrates querying against a Sanity media library. The MediaLibraryProvider is
automatically created by SanityApp when a media library config is present. The query runs
against: <code>https://api.sanity.io/v2025-03-24/media-libraries/mlPGY7BEqt52/query</code>
</Text>

<Card padding={3} style={{marginBottom: '2rem', backgroundColor: '#1a1a1a'}}>
<div style={{marginBottom: '1rem'}}>
<Text size={1} style={{color: '#ccc', marginBottom: '0.5rem'}}>
Current query:
</Text>
<code
style={{
display: 'block',
padding: '0.5rem',
backgroundColor: '#2a2a2a',
borderRadius: '4px',
fontFamily: 'monospace',
fontSize: '0.875rem',
color: '#fff',
wordBreak: 'break-all',
}}
>
{query}
</code>
</div>
</Card>

<Card padding={3} style={{backgroundColor: '#1a1a1a'}}>
<div style={{display: 'flex', alignItems: 'center', marginBottom: '1rem'}}>
<Text size={1} weight="medium" style={{color: '#fff'}}>
Query Results:
</Text>
{(isPending || isLoading) && <Spinner style={{marginLeft: '0.5rem'}} />}
</div>

<pre
style={{
backgroundColor: '#2a2a2a',
padding: '1rem',
borderRadius: '4px',
overflow: 'auto',
maxHeight: '400px',
fontSize: '0.875rem',
color: '#fff',
whiteSpace: 'pre-wrap',
}}
>
{JSON.stringify(data, null, 2)}
</pre>
</Card>
</div>
)
}
3 changes: 3 additions & 0 deletions apps/kitchensink-react/src/sanityConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export const devConfigs: SanityConfig[] = [
projectId: 'v28v5k8m',
dataset: 'production',
},
{
mediaLibraryId: 'mlPGY7BEqt52',
},
]

export const e2eConfigs: SanityConfig[] = [
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"prettier": "@sanity/prettier-config",
"dependencies": {
"@sanity/bifur-client": "^0.4.1",
"@sanity/client": "^7.10.0",
"@sanity/client": "7.11.1-allow-live.0",
"@sanity/comlink": "^3.0.4",
"@sanity/diff-match-patch": "^3.2.0",
"@sanity/diff-patch": "^6.0.0",
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/_exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ export {
createDatasetHandle,
createDocumentHandle,
createDocumentTypeHandle,
createMediaLibraryHandle,
createProjectHandle,
} from '../config/handles'
export {
type DatasetHandle,
type DocumentHandle,
type DocumentTypeHandle,
type MediaLibraryHandle,
type PerspectiveHandle,
type ProjectHandle,
type ReleasePerspective,
Expand Down Expand Up @@ -125,13 +127,16 @@ export {getProjectsState, resolveProjects} from '../projects/projects'
export {
getQueryKey,
getQueryState,
type MediaLibraryQueryOptions,
type MediaLibraryResolveQueryOptions,
parseQueryKey,
type QueryOptions,
resolveQuery,
} from '../query/queryStore'
export {getPerspectiveState} from '../releases/getPerspectiveState'
export type {ReleaseDocument} from '../releases/releasesStore'
export {getActiveReleasesState} from '../releases/releasesStore'
export {bindActionByMediaLibrary, bindActionByResource} from '../store/createActionBinder'
export {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
export {type Selector, type StateSource} from '../store/createStateSourceAction'
export {getUsersKey, parseUsersKey} from '../users/reducers'
Expand Down
28 changes: 25 additions & 3 deletions packages/core/src/client/clientStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const allowedKeys = Object.keys({
'maxRetries': null,
'dataset': null,
'projectId': null,
'mediaLibraryId': null,
'scope': null,
'apiVersion': null,
'requestTagPrefix': null,
Expand Down Expand Up @@ -86,6 +87,10 @@ export interface ClientOptions extends Pick<ClientConfig, AllowedClientConfigKey
* A required string indicating the API version for the client.
*/
'apiVersion': string
/**
* An optional media library ID for media library queries.
*/
'mediaLibraryId'?: string
/**
* @internal
*/
Expand Down Expand Up @@ -158,16 +163,33 @@ export const getClient = bindActionGlobally(
const {clients, authMethod} = state.get()
const projectId = options.projectId ?? instance.config.projectId
const dataset = options.dataset ?? instance.config.dataset
const mediaLibraryId = options.mediaLibraryId ?? instance.config.mediaLibraryId
const apiHost = options.apiHost ?? instance.config.auth?.apiHost

// Check if this is a media library configuration
const isMediaLibraryConfig = mediaLibraryId && !projectId && !dataset

const effectiveOptions: ClientOptions = {
...DEFAULT_CLIENT_CONFIG,
...((options.scope === 'global' || !projectId) && {useProjectHostname: false}),
token: authMethod === 'cookie' ? undefined : (tokenFromState ?? undefined),
...options,
...(projectId && {projectId}),
...(dataset && {dataset}),
...(apiHost && {apiHost}),
...(isMediaLibraryConfig
? {
// Media library specific configuration
'requestTagPrefix': 'sanity.media-library',
'~experimental_resource': {
type: 'media-library',
id: mediaLibraryId as string,
},
...(apiHost && {apiHost}),
}
: {
// Dataset specific configuration
...(projectId && {projectId}),
...(dataset && {dataset}),
...(apiHost && {apiHost}),
}),
}

if (effectiveOptions.token === null || typeof effectiveOptions.token === 'undefined') {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/config/handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type DatasetHandle,
type DocumentHandle,
type DocumentTypeHandle,
type MediaLibraryHandle,
type ProjectHandle,
} from './sanityConfig'

Expand Down Expand Up @@ -65,3 +66,16 @@ export function createDatasetHandle<
>(handle: DatasetHandle<TDataset, TProjectId>): DatasetHandle<TDataset, TProjectId> {
return handle
}

/**
* Creates or validates a `MediaLibraryHandle` object.
* Ensures the provided object conforms to the `MediaLibraryHandle` interface.
* @param handle - The object containing media library identification properties.
* @returns The validated `MediaLibraryHandle` object.
* @public
*/
export function createMediaLibraryHandle<TMediaLibraryId extends string = string>(
handle: MediaLibraryHandle<TMediaLibraryId>,
): MediaLibraryHandle<TMediaLibraryId> {
return handle
}
32 changes: 31 additions & 1 deletion packages/core/src/config/sanityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export interface DatasetHandle<TDataset extends string = string, TProjectId exte
dataset?: TDataset
}

/**
* Represents the configuration required to identify a Sanity media library.
* @public
*/
export interface MediaLibraryHandle<TMediaLibraryId extends string = string>
extends PerspectiveHandle {
mediaLibraryId?: TMediaLibraryId
}

/**
* Identifies a specific document type within a Sanity dataset and project.
* Includes `projectId`, `dataset`, and `documentType`.
Expand Down Expand Up @@ -67,7 +76,12 @@ export interface DocumentHandle<
* Represents the complete configuration for a Sanity SDK instance
* @public
*/
export interface SanityConfig extends DatasetHandle, PerspectiveHandle {
export interface SanityConfig extends DatasetHandle, PerspectiveHandle, MediaLibraryHandle {
/**
* Media library ID for media library queries
* @remarks When provided, enables media library functionality
*/
mediaLibraryId?: string
/**
* Authentication configuration for the instance
* @remarks Merged with parent configurations when using createChild
Expand All @@ -81,3 +95,19 @@ export interface SanityConfig extends DatasetHandle, PerspectiveHandle {
enabled: boolean
}
}

// /**
// * Configuration for a Sanity SDK instance with dataset support
// * @public
// */
// export interface DatasetSanityConfig extends SanityConfig {}

// /**
// * Configuration for a Sanity SDK instance with media library support
// * @public
// */
// export interface MediaLibrarySanityConfig extends SanityConfig {
// mediaLibraryId: string
// projectId?: never
// dataset?: never
// }
36 changes: 29 additions & 7 deletions packages/core/src/query/queryStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import {
} from 'rxjs'

import {getClientState} from '../client/clientStore'
import {type DatasetHandle} from '../config/sanityConfig'
import {type DatasetHandle, type MediaLibraryHandle} from '../config/sanityConfig'
import {getPerspectiveState} from '../releases/getPerspectiveState'
import {bindActionByDataset} from '../store/createActionBinder'
import {bindActionByResource} from '../store/createActionBinder'
import {type SanityInstance} from '../store/createSanityInstance'
import {
createStateSourceAction,
Expand Down Expand Up @@ -63,6 +63,18 @@ export interface QueryOptions<
params?: Record<string, unknown>
}

/**
* @beta
*/
export interface MediaLibraryQueryOptions<
TQuery extends string = string,
TMediaLibraryId extends string = string,
> extends Pick<ResponseQueryOptions, 'useCdn' | 'cache' | 'next' | 'cacheMode' | 'tag'>,
MediaLibraryHandle<TMediaLibraryId> {
query: TQuery
params?: Record<string, unknown>
}

/**
* @beta
*/
Expand All @@ -74,6 +86,16 @@ export interface ResolveQueryOptions<
signal?: AbortSignal
}

/**
* @beta
*/
export interface MediaLibraryResolveQueryOptions<
TQuery extends string = string,
TMediaLibraryId extends string = string,
> extends MediaLibraryQueryOptions<TQuery, TMediaLibraryId> {
signal?: AbortSignal
}

const EMPTY_ARRAY: never[] = []

/** @beta */
Expand Down Expand Up @@ -206,9 +228,9 @@ const listenToLiveClientAndSetLastLiveEventIds = ({
const liveMessages$ = getClientState(instance, {
apiVersion: QUERY_STORE_API_VERSION,
}).observable.pipe(
switchMap((client) =>
client.live.events({includeDrafts: !!client.config().token, tag: 'query-store'}),
),
switchMap((client) => {
return client.live.events({includeDrafts: !!client.config().token, tag: 'query-store'})
}),
share(),
filter((e) => e.type === 'message'),
)
Expand Down Expand Up @@ -278,7 +300,7 @@ export function getQueryState(
): ReturnType<typeof _getQueryState> {
return _getQueryState(...args)
}
const _getQueryState = bindActionByDataset(
const _getQueryState = bindActionByResource(
queryStore,
createStateSourceAction({
selector: ({state, instance}: SelectorContext<QueryStoreState>, options: QueryOptions) => {
Expand Down Expand Up @@ -337,7 +359,7 @@ export function resolveQuery<TData>(
export function resolveQuery(...args: Parameters<typeof _resolveQuery>): Promise<unknown> {
return _resolveQuery(...args)
}
const _resolveQuery = bindActionByDataset(
const _resolveQuery = bindActionByResource(
queryStore,
({state, instance}, {signal, ...options}: ResolveQueryOptions) => {
const normalized = normalizeOptionsWithPerspective(instance, options)
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/releases/getPerspectiveState.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {createSelector} from 'reselect'

import {type PerspectiveHandle, type ReleasePerspective} from '../config/sanityConfig'
import {bindActionByDataset} from '../store/createActionBinder'
import {bindActionByResource} from '../store/createActionBinder'
import {createStateSourceAction, type SelectorContext} from '../store/createStateSourceAction'
import {releasesStore, type ReleasesStoreState} from './releasesStore'
import {sortReleases} from './utils/sortReleases'
Expand Down Expand Up @@ -62,7 +62,7 @@ const memoizedOptionsSelector = createSelector(
*
* @public
*/
export const getPerspectiveState = bindActionByDataset(
export const getPerspectiveState = bindActionByResource(
releasesStore,
createStateSourceAction({
selector: createSelector(
Expand Down
Loading
Loading