UNPKG

@sanity/sdk

Version:
106 lines (97 loc) 3.27 kB
import {type SanityClient} from '@sanity/client' import {type SanityDocument} from '@sanity/types' import {catchError, EMPTY, retry, switchMap, timer} from 'rxjs' import {getClientState} from '../client/clientStore' import {bindActionByDataset, type BoundDatasetKey} from '../store/createActionBinder' import {createStateSourceAction} from '../store/createStateSourceAction' import {defineStore, type StoreContext} from '../store/defineStore' import {listenQuery} from '../utils/listenQuery' import {sortReleases} from './utils/sortReleases' const ARCHIVED_RELEASE_STATES = ['archived', 'published'] /** * Represents a document in a Sanity dataset that represents release options. * @internal */ export type ReleaseDocument = SanityDocument & { name: string publishAt?: string state: 'active' | 'scheduled' metadata: { title: string releaseType: 'asap' | 'scheduled' | 'undecided' intendedPublishAt?: string description?: string } } export interface ReleasesStoreState { activeReleases?: ReleaseDocument[] error?: unknown } export const releasesStore = defineStore<ReleasesStoreState, BoundDatasetKey>({ name: 'Releases', getInitialState: (): ReleasesStoreState => ({ activeReleases: undefined, }), initialize: (context) => { const subscription = subscribeToReleases(context) return () => subscription.unsubscribe() }, }) /** * Get the active releases from the store. * @internal */ export const getActiveReleasesState = bindActionByDataset( releasesStore, createStateSourceAction({ selector: ({state}, _?) => state.activeReleases, }), ) const RELEASES_QUERY = 'releases::all()' const QUERY_PARAMS = {} const subscribeToReleases = ({ instance, state, key: {projectId, dataset}, }: StoreContext<ReleasesStoreState, BoundDatasetKey>) => { return getClientState(instance, { apiVersion: '2025-04-10', perspective: 'raw', projectId, dataset, }) .observable.pipe( switchMap((client: SanityClient) => // releases are system documents, and are not supported by useQueryState listenQuery<ReleaseDocument[]>(client, RELEASES_QUERY, QUERY_PARAMS, { tag: 'releases-listener', throttleTime: 1000, transitions: ['update', 'appear', 'disappear'], }).pipe( retry({ count: 3, delay: (error, retryCount) => { // eslint-disable-next-line no-console console.error('[releases] Error in subscription:', error, 'Retry count:', retryCount) return timer(Math.min(1000 * Math.pow(2, retryCount), 10000)) }, }), catchError((error) => { state.set('setError', {error}) return EMPTY }), ), ), ) .subscribe({ next: (releases) => { // logic here mirrors that of studio: // https://github.com/sanity-io/sanity/blob/156e8fa482703d99219f08da7bacb384517f1513/packages/sanity/src/core/releases/store/useActiveReleases.ts#L29 state.set('setActiveReleases', { activeReleases: sortReleases(releases ?? []) .filter((release) => !ARCHIVED_RELEASE_STATES.includes(release.state)) .reverse(), }) }, }) }