UNPKG

@sanity/sdk

Version:
85 lines (77 loc) 2.67 kB
import {type ListenEvent, type SanityDocument} from '@sanity/client' import {createDocumentLoaderFromClient} from '@sanity/mutate/_unstable_store' import { first, map, merge, Observable, partition, share, shareReplay, Subject, switchMap, takeUntil, } from 'rxjs' import {getClientState} from '../client/clientStore' import {type SanityInstance} from '../store/createSanityInstance' const API_VERSION = 'v2025-05-06' export interface SharedListener { events: Observable<ListenEvent<SanityDocument>> dispose: () => void } export function createSharedListener(instance: SanityInstance): SharedListener { const dispose$ = new Subject<void>() const events$ = getClientState(instance, { apiVersion: API_VERSION, }).observable.pipe( switchMap((client) => // TODO: it seems like the client.listen method is not emitting disconnected // events. this is important to ensure we have an up to date version of the // doc. probably should introduce our own events for when the user goes offline client.listen( '*', {}, { events: ['mutation', 'welcome', 'reconnect'], includeResult: false, tag: 'document-listener', // // from manual testing, it seems like mendoza patches may be // // causing some ambiguity/wonkiness // includeMutations: false, // effectFormat: 'mendoza', }, ), ), takeUntil(dispose$), share(), ) const [welcome$, mutation$] = partition(events$, (e) => e.type === 'welcome') return { events: merge( // we replay the welcome event because that event kicks off fetching the document welcome$.pipe(shareReplay(1)), mutation$, ), dispose: () => dispose$.next(), } } export function createFetchDocument(instance: SanityInstance) { return function (documentId: string): Observable<SanityDocument | null> { return getClientState(instance, {apiVersion: API_VERSION}).observable.pipe( switchMap((client) => { // TODO: remove this once the client is updated to v7 the new type is available in @sanity/mutate/_unstable_store // eslint-disable-next-line @typescript-eslint/no-explicit-any const loadDocument = createDocumentLoaderFromClient(client as any) return loadDocument(documentId) }), map((result) => { if (!result.accessible) { if (result.reason === 'existence') return null throw new Error(`Document with ID \`${documentId}\` is inaccessible due to permissions.`) } return result.document as SanityDocument }), first(), ) } }