diff --git a/packages/core/src/document/documentStore.test.ts b/packages/core/src/document/documentStore.test.ts index f6404cc76..65d54438a 100644 --- a/packages/core/src/document/documentStore.test.ts +++ b/packages/core/src/document/documentStore.test.ts @@ -86,7 +86,7 @@ afterEach(() => { }) it('creates, edits, and publishes a document', async () => { - const doc = createDocumentHandle({documentId: 'doc-single', documentType: 'article'}) + const doc = {documentId: 'doc-single', documentType: 'article', source} const documentState = getDocumentState(instance, doc) // Initially the document is undefined @@ -122,7 +122,7 @@ it('creates, edits, and publishes a document', async () => { }) it('edits existing documents', async () => { - const doc = createDocumentHandle({documentId: 'existing-doc', documentType: 'article'}) + const doc = {documentId: 'existing-doc', documentType: 'article', source} const state = getDocumentState(instance, doc) // not subscribed yet so the value is undefined @@ -151,16 +151,16 @@ it('edits existing documents', async () => { }) it('sets optimistic changes synchronously', async () => { - const doc = createDocumentHandle({documentId: 'optimistic', documentType: 'article'}) + const doc = {documentId: 'optimistic', documentType: 'article'} - const state1 = getDocumentState(instance1, doc) - const state2 = getDocumentState(instance2, doc) + const state1 = getDocumentState(instance1, {...doc, source: source1}) + const state2 = getDocumentState(instance2, {...doc, source: source2}) const unsubscribe1 = state1.subscribe() const unsubscribe2 = state2.subscribe() // wait until the value is primed in the store - await resolveDocument(instance1, doc) + await resolveDocument(instance1, {...doc, source: source1}) // then the actions are synchronous expect(state1.getCurrent()).toBeNull() @@ -204,9 +204,9 @@ it('sets optimistic changes synchronously', async () => { }) it('propagates changes between two instances', async () => { - const doc = createDocumentHandle({documentId: 'doc-collab', documentType: 'article'}) - const state1 = getDocumentState(instance1, doc) - const state2 = getDocumentState(instance2, doc) + const doc = {documentId: 'doc-collab', documentType: 'article'} + const state1 = getDocumentState(instance1, {...doc, source: source1}) + const state2 = getDocumentState(instance2, {...doc, source: source2}) const state1Unsubscribe = state1.subscribe() const state2Unsubscribe = state2.subscribe() @@ -237,9 +237,9 @@ it('propagates changes between two instances', async () => { }) it('handles concurrent edits and resolves conflicts', async () => { - const doc = createDocumentHandle({documentId: 'doc-concurrent', documentType: 'article'}) - const state1 = getDocumentState(instance1, doc) - const state2 = getDocumentState(instance2, doc) + const doc = {documentId: 'doc-concurrent', documentType: 'article'} + const state1 = getDocumentState(instance1, {...doc, source: source1}) + const state2 = getDocumentState(instance2, {...doc, source: source2}) const state1Unsubscribe = state1.subscribe() const state2Unsubscribe = state2.subscribe() @@ -281,7 +281,7 @@ it('handles concurrent edits and resolves conflicts', async () => { }) it('unpublishes and discards a document', async () => { - const doc = createDocumentHandle({documentId: 'doc-pub-unpub', documentType: 'article'}) + const doc = {documentId: 'doc-pub-unpub', documentType: 'article', source} const documentState = getDocumentState(instance, doc) const unsubscribe = documentState.subscribe() @@ -312,7 +312,7 @@ it('unpublishes and discards a document', async () => { }) it('deletes a document', async () => { - const doc = createDocumentHandle({documentId: 'doc-delete', documentType: 'article'}) + const doc = {documentId: 'doc-delete', documentType: 'article', source} const documentState = getDocumentState(instance, doc) const unsubscribe = documentState.subscribe() @@ -333,7 +333,7 @@ it('deletes a document', async () => { }) it('cleans up document state when there are no subscribers', async () => { - const doc = createDocumentHandle({documentId: 'doc-cleanup', documentType: 'article'}) + const doc = {documentId: 'doc-cleanup', documentType: 'article', source} const documentState = getDocumentState(instance, doc) // Subscribe to the document state. @@ -356,7 +356,7 @@ it('cleans up document state when there are no subscribers', async () => { }) it('fetches documents if there are no active subscriptions for the actions applied', async () => { - const doc = createDocumentHandle({documentId: 'existing-doc', documentType: 'article'}) + const doc = {documentId: 'existing-doc', documentType: 'article', source} const {getCurrent} = getDocumentState(instance, doc) expect(getCurrent()).toBeUndefined() @@ -411,7 +411,7 @@ it('fetches documents if there are no active subscriptions for the actions appli }) it('batches edit transaction into one outgoing transaction', async () => { - const doc = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'article'}) + const doc = {documentId: crypto.randomUUID(), documentType: 'article', source} const unsubscribe = getDocumentState(instance, doc).subscribe() @@ -438,7 +438,7 @@ it('batches edit transaction into one outgoing transaction', async () => { }) it('provides the consistency status via `getDocumentSyncStatus`', async () => { - const doc = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'article'}) + const doc = {documentId: crypto.randomUUID(), documentType: 'article', source} const syncStatus = getDocumentSyncStatus(instance, doc) expect(syncStatus.getCurrent()).toBeUndefined() @@ -482,15 +482,18 @@ it('reverts failed outgoing transaction locally', async () => { }) const revertedEventPromise = new Promise((resolve) => { - const unsubscribe = subscribeDocumentEvents(instance, (e) => { - if (e.type === 'reverted') { - resolve(e) - unsubscribe() - } + const unsubscribe = subscribeDocumentEvents(instance, { + onEvent: (e) => { + if (e.type === 'reverted') { + resolve(e) + unsubscribe() + } + }, + source, }) }) - const doc = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'article'}) + const doc = {documentId: crypto.randomUUID(), documentType: 'article', source} const {getCurrent, subscribe} = getDocumentState(instance, doc) const unsubscribe = subscribe() @@ -546,15 +549,18 @@ it('reverts failed outgoing transaction locally', async () => { it('removes a queued transaction if it fails to apply', async () => { const actionErrorEventPromise = new Promise((resolve) => { - const unsubscribe = subscribeDocumentEvents(instance, (e) => { - if (e.type === 'error') { - resolve(e) - unsubscribe() - } + const unsubscribe = subscribeDocumentEvents(instance, { + onEvent: (e) => { + if (e.type === 'error') { + resolve(e) + unsubscribe() + } + }, + source, }) }) - const doc = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'article'}) + const doc = {documentId: crypto.randomUUID(), documentType: 'article', source} const state = getDocumentState(instance, doc) const unsubscribe = state.subscribe() @@ -587,10 +593,11 @@ it('returns allowed true when no permission errors occur', async () => { client.observable.request = vi.fn().mockReturnValue(of(datasetAcl)) // Create a document and subscribe to it. - const doc = createDocumentHandle({ + const doc = { documentId: 'doc-perm-allowed', documentType: 'article', - }) + source, + } const state = getDocumentState(instance, doc) const unsubscribe = state.subscribe() await applyDocumentActions(instance, {actions: [createDocument(doc)], source}).then((r) => @@ -606,6 +613,7 @@ it('returns allowed true when no permission errors occur', async () => { patches: [{set: {title: 'New Title'}}], }, ], + source, }) // Wait briefly to allow permissions calculation. await new Promise((resolve) => setTimeout(resolve, 10)) @@ -638,7 +646,7 @@ it('returns allowed false with reasons when permission errors occur', async () = vi.mocked(client.request).mockResolvedValue(datasetAcl) const doc = createDocumentHandle({documentId: 'doc-perm-denied', documentType: 'article'}) - const result = await resolvePermissions(instance, {actions: [createDocument(doc)]}) + const result = await resolvePermissions(instance, {actions: [createDocument(doc)], source}) const message = 'You do not have permission to create a draft for document "doc-perm-denied".' expect(result).toMatchObject({ @@ -659,17 +667,19 @@ it('fetches dataset ACL and updates grants in the document store state', async ( const book = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'book'}) const author = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'author'}) - expect(await resolvePermissions(instance, {actions: [createDocument(book)]})).toEqual({ + expect(await resolvePermissions(instance, {actions: [createDocument(book)], source})).toEqual({ allowed: true, }) - expect(await resolvePermissions(instance, {actions: [createDocument(author)]})).toMatchObject({ + expect( + await resolvePermissions(instance, {actions: [createDocument(author)], source}), + ).toMatchObject({ allowed: false, message: expect.stringContaining('You do not have permission to create a draft for document'), }) }) it('returns a promise that resolves when a document has been loaded in the store (useful for suspense)', async () => { - const doc = createDocumentHandle({documentId: crypto.randomUUID(), documentType: 'article'}) + const doc = {documentId: crypto.randomUUID(), documentType: 'article', source} expect(await resolveDocument(instance, doc)).toBe(null) @@ -691,7 +701,7 @@ it('returns a promise that resolves when a document has been loaded in the store it('emits an event for each action after an outgoing transaction has been accepted', async () => { const handler = vi.fn() - const unsubscribe = subscribeDocumentEvents(instance, handler) + const unsubscribe = subscribeDocumentEvents(instance, {onEvent: handler, source}) const documentId = crypto.randomUUID() const doc = createDocumentHandle({documentId, documentType: 'article'}) diff --git a/packages/core/src/document/documentStore.ts b/packages/core/src/document/documentStore.ts index 3da67d5a0..6e320cb99 100644 --- a/packages/core/src/document/documentStore.ts +++ b/packages/core/src/document/documentStore.ts @@ -27,7 +27,7 @@ import { } from 'rxjs' import {getClientState} from '../client/clientStore' -import {type DocumentHandle} from '../config/sanityConfig' +import {type DocumentHandle, type DocumentSource} from '../config/sanityConfig' import { bindActionByDataset, type BoundDatasetKey, @@ -141,10 +141,11 @@ export const documentStore = defineStore({ export interface DocumentOptions< TPath extends string | undefined = undefined, TDocumentType extends string = string, - TDataset extends string = string, - TProjectId extends string = string, -> extends DocumentHandle { +> { path?: TPath + documentId: string + documentType: TDocumentType + source: DocumentSource } /** @beta */ @@ -154,7 +155,7 @@ export function getDocumentState< TProjectId extends string = string, >( instance: SanityInstance, - options: DocumentOptions, + options: DocumentOptions, ): StateSource | undefined | null> /** @beta */ @@ -165,7 +166,7 @@ export function getDocumentState< TProjectId extends string = string, >( instance: SanityInstance, - options: DocumentOptions, + options: DocumentOptions, ): StateSource< JsonMatch, TPath> | undefined > @@ -215,12 +216,12 @@ export function resolveDocument< TProjectId extends string = string, >( instance: SanityInstance, - docHandle: DocumentHandle, + docHandle: Omit, ): Promise | null> /** @beta */ export function resolveDocument( instance: SanityInstance, - docHandle: DocumentHandle, + docHandle: Omit, ): Promise /** @beta */ export function resolveDocument( @@ -230,12 +231,9 @@ export function resolveDocument( } const _resolveDocument = bindActionByDataset( documentStore, - ({instance}, docHandle: DocumentHandle) => { + ({instance}, docHandle: Omit) => { return firstValueFrom( - getDocumentState(instance, { - ...docHandle, - path: undefined, - }).observable.pipe(filter((i) => i !== undefined)), + getDocumentState(instance, docHandle).observable.pipe(filter((i) => i !== undefined)), ) as Promise }, ) @@ -246,9 +244,9 @@ export const getDocumentSyncStatus = bindActionByDataset( createStateSourceAction({ selector: ( {state: {error, documentStates: documents, outgoing, applied, queued}}, - doc: DocumentHandle, + doc: Omit, ) => { - const documentId = typeof doc === 'string' ? doc : doc.documentId + const documentId = doc.documentId if (error) throw error const draftId = getDraftId(documentId) const publishedId = getPublishedId(documentId) @@ -265,6 +263,7 @@ export const getDocumentSyncStatus = bindActionByDataset( type PermissionsStateOptions = { actions: DocumentAction[] + source: DocumentSource } /** @beta */ @@ -294,9 +293,9 @@ export const resolvePermissions = bindActionByDataset( /** @beta */ export const subscribeDocumentEvents = bindActionByDataset( documentStore, - ({state}, eventHandler: (e: DocumentEvent) => void) => { + ({state}, {onEvent}: {onEvent: (e: DocumentEvent) => void; source: DocumentSource}) => { const {events} = state.get() - const subscription = events.subscribe(eventHandler) + const subscription = events.subscribe(onEvent) return () => subscription.unsubscribe() }, ) diff --git a/packages/react/src/hooks/document/useDocument.ts b/packages/react/src/hooks/document/useDocument.ts index 237d6c7d2..719abcc03 100644 --- a/packages/react/src/hooks/document/useDocument.ts +++ b/packages/react/src/hooks/document/useDocument.ts @@ -1,42 +1,26 @@ -import {type DocumentOptions, getDocumentState, type JsonMatch, resolveDocument} from '@sanity/sdk' +import {type DocumentOptions, getDocumentState, type JsonMatch} from '@sanity/sdk' import {type SanityDocument} from 'groq' -import {identity} from 'rxjs' +import {useMemo} from 'react' -import {createStateSourceHook} from '../helpers/createStateSourceHook' +import {type SourceOptions} from '../../type' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' +import {useStoreState} from '../helpers/useStoreState' // used in an `{@link useDocumentProjection}` and `{@link useQuery}` // eslint-disable-next-line import/consistent-type-specifier-style, unused-imports/no-unused-imports import type {useDocumentProjection} from '../projection/useDocumentProjection' // eslint-disable-next-line import/consistent-type-specifier-style, unused-imports/no-unused-imports import type {useQuery} from '../query/useQuery' -const useDocumentValue = createStateSourceHook({ - // Pass options directly to getDocumentState - getState: (instance, options: DocumentOptions) => - getDocumentState(instance, options), - // Pass options directly to getDocumentState for checking current value - shouldSuspend: (instance, {path: _path, ...options}: DocumentOptions) => - getDocumentState(instance, options).getCurrent() === undefined, - // Extract handle part for resolveDocument - suspender: (instance, options: DocumentOptions) => - resolveDocument(instance, options), - getConfig: identity as ( - options: DocumentOptions, - ) => DocumentOptions, -}) - -const wrapHookWithData = ( - useValue: (...params: TParams) => TReturn, -) => { - function useHook(...params: TParams) { - return {data: useValue(...params)} - } - return useHook -} +export interface UseDocumentOptions< + TPath extends string | undefined = undefined, + TDocumentType extends string = string, +> extends Omit, 'source'>, + SourceOptions {} interface UseDocument { /** @internal */ ( - options: DocumentOptions, + options: UseDocumentOptions, ): {data: SanityDocument | null} /** @internal */ @@ -46,7 +30,7 @@ interface UseDocument { TDataset extends string = string, TProjectId extends string = string, >( - options: DocumentOptions, + options: UseDocumentOptions, ): { data: JsonMatch, TPath> | undefined } @@ -124,7 +108,7 @@ interface UseDocument { TDataset extends string = string, TProjectId extends string = string, >( - options: DocumentOptions, + options: UseDocumentOptions, ): TPath extends string ? { data: @@ -194,13 +178,13 @@ interface UseDocument { * @inlineType DocumentOptions */ ( - options: DocumentOptions, + options: UseDocumentOptions, ): TPath extends string ? {data: TData | undefined} : {data: TData | null} /** * @internal */ - (options: DocumentOptions): {data: unknown} + (options: UseDocumentOptions): {data: unknown} } /** @@ -226,4 +210,16 @@ interface UseDocument { * * @function */ -export const useDocument = wrapHookWithData(useDocumentValue) as UseDocument +// export const useDocument: UseDocument = wrapHookWithData(useDocumentValue) + +export const useDocument = (({projectId, dataset, source, ...options}: UseDocumentOptions) => { + const [instance, actualSource] = useSanityInstanceAndSource({projectId, dataset, source}) + + const state = useMemo( + () => getDocumentState(instance, {...options, source: actualSource}), + [actualSource, instance, options], + ) + + const data = useStoreState(state) + return {data} +}) as UseDocument diff --git a/packages/react/src/hooks/document/useDocumentEvent.test.ts b/packages/react/src/hooks/document/useDocumentEvent.test.ts index e933b9a53..66d02d397 100644 --- a/packages/react/src/hooks/document/useDocumentEvent.test.ts +++ b/packages/react/src/hooks/document/useDocumentEvent.test.ts @@ -42,7 +42,7 @@ describe('useDocumentEvent hook', () => { expect(vi.mocked(subscribeDocumentEvents)).toHaveBeenCalledTimes(1) expect(vi.mocked(subscribeDocumentEvents).mock.calls[0][0]).toBe(instance) - const stableHandler = vi.mocked(subscribeDocumentEvents).mock.calls[0][1] + const stableHandler = vi.mocked(subscribeDocumentEvents).mock.calls[0][1].onEvent expect(typeof stableHandler).toBe('function') const event = {type: 'edited', documentId: 'doc1', outgoing: {}} as DocumentEvent diff --git a/packages/react/src/hooks/document/useDocumentEvent.ts b/packages/react/src/hooks/document/useDocumentEvent.ts index 8c06edd6c..564865397 100644 --- a/packages/react/src/hooks/document/useDocumentEvent.ts +++ b/packages/react/src/hooks/document/useDocumentEvent.ts @@ -1,15 +1,13 @@ -import {type DatasetHandle, type DocumentEvent, subscribeDocumentEvents} from '@sanity/sdk' +import {type DocumentEvent, subscribeDocumentEvents} from '@sanity/sdk' import {useCallback, useEffect, useInsertionEffect, useRef} from 'react' -import {useSanityInstance} from '../context/useSanityInstance' +import {type SourceOptions} from '../../type' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' /** * @public */ -export interface UseDocumentEventOptions< - TDataset extends string = string, - TProjectId extends string = string, -> extends DatasetHandle { +export interface UseDocumentEventOptions extends SourceOptions { onEvent: (documentEvent: DocumentEvent) => void } @@ -68,15 +66,14 @@ export interface UseDocumentEventOptions< * } * ``` */ -export function useDocumentEvent< - TDataset extends string = string, - TProjectId extends string = string, ->( - // Single options object parameter - options: UseDocumentEventOptions, -): void { +export function useDocumentEvent({ + projectId, + dataset, + source, + onEvent, +}: UseDocumentEventOptions): void { // Destructure handler and datasetHandle from options - const {onEvent, ...datasetHandle} = options + const [instance, actualSource] = useSanityInstanceAndSource({projectId, dataset, source}) const ref = useRef(onEvent) useInsertionEffect(() => { @@ -87,8 +84,7 @@ export function useDocumentEvent< return ref.current(documentEvent) }, []) - const instance = useSanityInstance(datasetHandle) useEffect(() => { - return subscribeDocumentEvents(instance, stableHandler) - }, [instance, stableHandler]) + return subscribeDocumentEvents(instance, {onEvent, source: actualSource}) + }, [actualSource, instance, onEvent, stableHandler]) } diff --git a/packages/react/src/hooks/document/useDocumentPermissions.ts b/packages/react/src/hooks/document/useDocumentPermissions.ts index 7a349256c..efcaa097a 100644 --- a/packages/react/src/hooks/document/useDocumentPermissions.ts +++ b/packages/react/src/hooks/document/useDocumentPermissions.ts @@ -2,7 +2,7 @@ import {type DocumentAction, type DocumentPermissionsResult, getPermissionsState import {useCallback, useMemo, useSyncExternalStore} from 'react' import {filter, firstValueFrom} from 'rxjs' -import {useSanityInstance} from '../context/useSanityInstance' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' /** * @@ -112,22 +112,22 @@ export function useDocumentPermissions( } } - const instance = useSanityInstance({projectId, dataset}) + const [instance, source] = useSanityInstanceAndSource({projectId, dataset}) const isDocumentReady = useCallback( - () => getPermissionsState(instance, {actions}).getCurrent() !== undefined, - [actions, instance], + () => getPermissionsState(instance, {actions, source}).getCurrent() !== undefined, + [actions, instance, source], ) if (!isDocumentReady()) { throw firstValueFrom( - getPermissionsState(instance, {actions}).observable.pipe( + getPermissionsState(instance, {actions, source}).observable.pipe( filter((result) => result !== undefined), ), ) } const {subscribe, getCurrent} = useMemo( - () => getPermissionsState(instance, {actions}), - [actions, instance], + () => getPermissionsState(instance, {actions, source}), + [actions, instance, source], ) return useSyncExternalStore(subscribe, getCurrent) as DocumentPermissionsResult diff --git a/packages/react/src/hooks/document/useDocumentSyncStatus.ts b/packages/react/src/hooks/document/useDocumentSyncStatus.ts index cf386bc51..becf16796 100644 --- a/packages/react/src/hooks/document/useDocumentSyncStatus.ts +++ b/packages/react/src/hooks/document/useDocumentSyncStatus.ts @@ -1,13 +1,8 @@ -import { - type DocumentHandle, - getDocumentSyncStatus, - resolveDocument, - type SanityInstance, - type StateSource, -} from '@sanity/sdk' -import {identity} from 'rxjs' +import {type DocumentSource, getDocumentSyncStatus} from '@sanity/sdk' +import {useMemo} from 'react' -import {createStateSourceHook} from '../helpers/createStateSourceHook' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' +import {useStoreState} from '../helpers/useStoreState' type UseDocumentSyncStatus = { /** @@ -42,20 +37,30 @@ type UseDocumentSyncStatus = { * // * ``` */ - (doc: DocumentHandle): boolean + (doc: { + documentId: string + documentType: string + + projectId?: string + dataset?: string + source?: DocumentSource + }): boolean } /** * @public - * @function */ -export const useDocumentSyncStatus: UseDocumentSyncStatus = createStateSourceHook({ - getState: getDocumentSyncStatus as ( - instance: SanityInstance, - doc: DocumentHandle, - ) => StateSource, - shouldSuspend: (instance, doc: DocumentHandle) => - getDocumentSyncStatus(instance, doc).getCurrent() === undefined, - suspender: (instance, doc: DocumentHandle) => resolveDocument(instance, doc), - getConfig: identity, -}) +export const useDocumentSyncStatus: UseDocumentSyncStatus = ({ + projectId, + dataset, + source, + ...options +}) => { + const [instance, actualSource] = useSanityInstanceAndSource({projectId, dataset, source}) + const state = useMemo( + () => getDocumentSyncStatus(instance, {...options, source: actualSource}), + [actualSource, instance, options], + ) + + return useStoreState(state) +} diff --git a/packages/react/src/hooks/document/useEditDocument.ts b/packages/react/src/hooks/document/useEditDocument.ts index 61f07037d..cc8b1372a 100644 --- a/packages/react/src/hooks/document/useEditDocument.ts +++ b/packages/react/src/hooks/document/useEditDocument.ts @@ -1,16 +1,16 @@ import { type ActionsResult, - type DocumentOptions, + applyDocumentActions, editDocument, getDocumentState, type JsonMatch, resolveDocument, } from '@sanity/sdk' import {type SanityDocument} from 'groq' -import {useCallback} from 'react' +import {useCallback, useMemo} from 'react' -import {useSanityInstance} from '../context/useSanityInstance' -import {useApplyDocumentActions} from './useApplyDocumentActions' +import {useSanityInstanceAndSource} from '../context/useSanityInstance' +import {type UseDocumentOptions} from './useDocument' const ignoredKeys = ['_id', '_type', '_createdAt', '_updatedAt', '_rev'] @@ -30,7 +30,7 @@ export function useEditDocument< TDataset extends string = string, TProjectId extends string = string, >( - options: DocumentOptions, + options: UseDocumentOptions, ): ( nextValue: Updater>, ) => Promise>> @@ -50,7 +50,7 @@ export function useEditDocument< TDataset extends string = string, TProjectId extends string = string, >( - options: DocumentOptions, + options: UseDocumentOptions, ): ( nextValue: Updater, TPath>>, ) => Promise>> @@ -65,7 +65,7 @@ export function useEditDocument< * Returns a promise resolving to the {@link ActionsResult}. */ export function useEditDocument( - options: DocumentOptions, + options: UseDocumentOptions, ): (nextValue: Updater) => Promise // Overload 4: Explicit type, path provided @@ -78,7 +78,7 @@ export function useEditDocument( * Returns a promise resolving to the {@link ActionsResult}. */ export function useEditDocument( - options: DocumentOptions, + options: UseDocumentOptions, ): (nextValue: Updater) => Promise /** @@ -258,10 +258,15 @@ export function useEditDocument( */ export function useEditDocument({ path, - ...doc -}: DocumentOptions): (updater: Updater) => Promise { - const instance = useSanityInstance(doc) - const apply = useApplyDocumentActions() + projectId, + dataset, + source, + ...options +}: UseDocumentOptions): (updater: Updater) => Promise { + const [instance, actualSource] = useSanityInstanceAndSource({projectId, dataset, source}) + + const doc = useMemo(() => ({...options, source: actualSource}), [actualSource, options]) + const isDocumentReady = useCallback( () => getDocumentState(instance, doc).getCurrent() !== undefined, [instance, doc], @@ -280,7 +285,10 @@ export function useEditDocument({ ? (updater as (prev: typeof currentValue) => typeof currentValue)(currentValue) : updater - return apply(editDocument(doc, {set: {[currentPath]: nextValue}})) + return applyDocumentActions(instance, { + actions: [editDocument(doc, {set: {[currentPath]: nextValue}})], + source: actualSource, + }) } const fullDocState = getDocumentState(instance, {...doc, path}) @@ -309,6 +317,6 @@ export function useEditDocument({ : editDocument(doc, {unset: [key]}), ) - return apply(editActions) + return applyDocumentActions(instance, {actions: editActions, source: actualSource}) } }